Skip to content

Commit 0b4e09e

Browse files
Fixed oauth2 redirect to Android, build authentication-service, @claude apply code coverage tests for this PR
1 parent 9e79bd7 commit 0b4e09e

4 files changed

Lines changed: 60 additions & 31 deletions

File tree

android-webapp/app/src/main/AndroidManifest.xml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,25 +39,26 @@
3939
<activity
4040
android:name=".ui.OAuth2CallbackActivity"
4141
android:exported="true"
42-
android:launchMode="singleTask">
43-
<intent-filter android:autoVerify="true">
42+
android:launchMode="singleTask"
43+
android:noHistory="true">
44+
<!-- Custom scheme for OAuth2 callback -->
45+
<intent-filter>
4446
<action android:name="android.intent.action.VIEW" />
4547
<category android:name="android.intent.category.DEFAULT" />
4648
<category android:name="android.intent.category.BROWSABLE" />
4749
<data
48-
android:scheme="https"
49-
android:host="spendingbetter.com"
50-
android:pathPrefix="/android/oauth2/callback" />
50+
android:scheme="spendingbetter"
51+
android:host="oauth2callback" />
5152
</intent-filter>
52-
<intent-filter>
53+
<!-- HTTPS deep link as fallback -->
54+
<intent-filter android:autoVerify="true">
5355
<action android:name="android.intent.action.VIEW" />
5456
<category android:name="android.intent.category.DEFAULT" />
5557
<category android:name="android.intent.category.BROWSABLE" />
5658
<data
5759
android:scheme="https"
5860
android:host="spendingbetter.com"
59-
android:port="443"
60-
android:path="/android/oauth2/callback" />
61+
android:pathPrefix="/android/oauth2/callback" />
6162
</intent-filter>
6263
</activity>
6364

android-webapp/app/src/main/java/com/springboot/android/ui/LoginActivity.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,13 @@ protected void onResume() {
141141
super.onResume();
142142

143143
// Check if user is authenticated after OAuth2 redirect
144+
// This handles the case where Chrome Custom Tab closes and returns to LoginActivity
144145
if (sessionManager.isLoggedIn()) {
146+
android.util.Log.d("LoginActivity", "User is logged in, redirecting to dashboard");
145147
Intent intent = new Intent(this, DashboardActivity.class);
146148
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
147149
startActivity(intent);
148-
finish();
150+
finishAffinity(); // Close this and any parent activities
149151
}
150152
}
151153
}

android-webapp/app/src/main/java/com/springboot/android/ui/OAuth2CallbackActivity.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,18 @@ public void onResponse(Call<AccountInfo> call, Response<AccountInfo> response) {
5858
android.util.Log.d("OAuth2Callback", "Using session cookie authentication");
5959
}
6060

61+
android.util.Log.d("OAuth2Callback", "Authentication successful, navigating to dashboard");
62+
6163
Toast.makeText(OAuth2CallbackActivity.this,
6264
"Welcome " + account.getFullName(), Toast.LENGTH_SHORT).show();
6365

64-
// Navigate to dashboard home
66+
// Navigate to dashboard home, clearing all previous activities
6567
Intent intent = new Intent(OAuth2CallbackActivity.this, DashboardActivity.class);
6668
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
6769
startActivity(intent);
68-
finish();
70+
71+
// Finish this activity and all parent activities
72+
finishAffinity();
6973
} else {
7074
android.util.Log.e("OAuth2Callback", "Authentication failed with code: " + response.code());
7175
Toast.makeText(OAuth2CallbackActivity.this,
Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,48 @@
11
package com.microservice.authentication.controller;
22

3-
import jakarta.servlet.http.HttpServletRequest;
3+
import java.io.IOException;
4+
import java.util.Optional;
5+
6+
import com.microservice.authentication.common.repository.AuthenticationCommonRepository;
7+
import jakarta.servlet.http.HttpServletResponse;
48
import lombok.extern.slf4j.Slf4j;
5-
import org.springframework.http.MediaType;
9+
610
import org.springframework.security.core.Authentication;
7-
import org.springframework.security.core.context.SecurityContextHolder;
811
import org.springframework.stereotype.Controller;
912
import org.springframework.web.bind.annotation.GetMapping;
10-
import org.springframework.web.bind.annotation.ResponseBody;
1113

1214
@Slf4j
1315
@Controller
1416
public class AndroidOAuth2Controller {
17+
private final AuthenticationCommonRepository authenticationCommonRepository;
18+
19+
public AndroidOAuth2Controller(AuthenticationCommonRepository authenticationCommonRepository) {
20+
this.authenticationCommonRepository = authenticationCommonRepository;
21+
}
1522

16-
@GetMapping(value = "/android/oauth2/callback", produces = MediaType.TEXT_HTML_VALUE)
17-
@ResponseBody
18-
public String androidOAuth2Callback(HttpServletRequest request) {
23+
@GetMapping(value = "/android/oauth2/callback")
24+
public void androidOAuth2Callback(Authentication authentication, HttpServletResponse response) throws IOException {
1925
// After successful OAuth2 authentication with Google,
2026
// Spring Security redirects here with authenticated session
21-
// Android app will intercept this URL via intent-filter
22-
// and handle the authentication
27+
// Redirect to custom scheme so Android app can intercept
2328

24-
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
2529
String username = "Unknown";
26-
String sessionId = request.getSession().getId();
30+
Optional<com.microservice.authentication.common.model.Authentication> findById = authenticationCommonRepository.findByEmail(authentication.getName());
2731

28-
if (auth != null && auth.isAuthenticated()) {
29-
username = auth.getName();
32+
if (findById.isPresent()) {
33+
username = findById.get().getFullName();
3034
log.info("Android OAuth2 callback - User authenticated: {}", username);
3135
}
3236

33-
return "<!DOCTYPE html>" +
37+
// Return HTML with multiple redirect methods
38+
response.setContentType("text/html");
39+
response.setStatus(HttpServletResponse.SC_OK);
40+
41+
String html = "<!DOCTYPE html>" +
3442
"<html>" +
3543
"<head>" +
3644
" <meta charset=\"UTF-8\">" +
3745
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">" +
38-
" <meta http-equiv=\"refresh\" content=\"0;url=spendingbetter://oauth2callback\">" +
3946
" <title>Authentication Successful</title>" +
4047
" <style>" +
4148
" body {" +
@@ -52,21 +59,36 @@ public String androidOAuth2Callback(HttpServletRequest request) {
5259
" .success-icon { font-size: 4rem; margin-bottom: 1rem; }" +
5360
" h1 { margin: 0 0 1rem 0; font-size: 2rem; }" +
5461
" p { margin: 0; font-size: 1.1rem; opacity: 0.9; }" +
62+
" .button {" +
63+
" display: inline-block;" +
64+
" margin-top: 2rem;" +
65+
" padding: 1rem 2rem;" +
66+
" background: rgba(255,255,255,0.2);" +
67+
" color: white;" +
68+
" text-decoration: none;" +
69+
" border-radius: 8px;" +
70+
" font-size: 1.1rem;" +
71+
" }" +
5572
" </style>" +
5673
" <script>" +
57-
" // Immediately redirect to the app using custom scheme" +
58-
" window.location.href = 'spendingbetter://oauth2callback';" +
74+
" // Try to redirect after a short delay to ensure page loads" +
75+
" setTimeout(function() {" +
76+
" window.location.replace('spendingbetter://oauth2callback');" +
77+
" }, 100);" +
5978
" </script>" +
6079
"</head>" +
6180
"<body>" +
6281
" <div class=\"container\">" +
6382
" <div class=\"success-icon\">✓</div>" +
6483
" <h1>Authentication Successful</h1>" +
65-
" <p>Redirecting to app...</p>" +
66-
" <p style=\"margin-top: 1rem; opacity: 0.7; font-size: 0.9rem;\">Welcome, " + username + "</p>" +
67-
" <p style=\"margin-top: 2rem; font-size: 0.9rem;\">If you're not redirected, <a href=\"spendingbetter://oauth2callback\" style=\"color: white; text-decoration: underline;\">click here</a></p>" +
84+
" <p>Welcome, " + username + "!</p>" +
85+
" <a href=\"spendingbetter://oauth2callback\" class=\"button\">Return to App</a>" +
86+
" <p style=\"margin-top: 2rem; font-size: 0.9rem; opacity: 0.7;\">Please click the button above to return to the app</p>" +
6887
" </div>" +
6988
"</body>" +
7089
"</html>";
90+
91+
response.getWriter().write(html);
92+
response.getWriter().flush();
7193
}
7294
}

0 commit comments

Comments
 (0)