Google Jules has been out for a few months now, and I decided to finally give it a real development task:
implement Google OAuth2 login in my Spring Boot + Angular application (N1netails)—while following the exact same authentication pattern I previously implemented for GitHub OAuth2.
A while back, I wrote a detailed guide covering the GitHub OAuth2 integration, which serves as the prequel to this article:
👉 https://dev.to/shahidfoy/how-i-implemented-github-oauth2-into-my-spring-boot-angular-app-n1netails-5bo
For this update, I reused the same structure and simply extended it for Google OAuth2.
- Tag: v0.3.14 https://github.com/n1netails/n1netails/tree/v0.3.14
- Pull Request: https://github.com/n1netails/n1netails/pull/203/files
Using Google Jules, I asked it to analyze the existing GitHub OAuth2 logic and apply the same pattern for the Google OAuth2 flow—making the integration faster, more consistent, and less error-prone.
🔐 Google OAuth2 in Spring Boot
The most important configuration piece is the registrationId Spring Security uses to differentiate OAuth providers.
It corresponds directly to your YAML keys:
spring.security.oauth2.client.registration.githubspring.security.oauth2.client.registration.google
OAuth2 Configuration (application-oauth.yml)
spring:
security:
oauth2:
client:
registration:
github:
client-id: ${GITHUB_CLIENT_ID:your-github-client-id}
client-secret: ${GITHUB_CLIENT_SECRET:your-github-client-secret}
scope: read:user,user:email
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" # /login/oauth2/code/github
client-name: GitHub
google:
client-id: ${GOOGLE_CLIENT_ID:your-google-client-id}
client-secret: ${GOOGLE_CLIENT_SECRET:your-google-client-secret}
scope: openid,email,profile
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" # /login/oauth2/code/google
client-name: Google
provider:
github:
authorization-uri: https://github.com/login/oauth/authorize
token-uri: https://github.com/login/oauth/access_token
user-info-uri: https://api.github.com/user
🔄 OAuth2 Success Handler
After a successful login, Spring Boot passes the OAuth token + user info to my OAuth2Service. From there, the service generates a JWT token for N1netails and redirects to the Angular frontend.
.oauth2Login(oauth2 -> oauth2
.successHandler((request, response, authentication) -> {
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
String provider = oauthToken.getAuthorizedClientRegistrationId();
String jwtToken;
if ("github".equalsIgnoreCase(provider)) {
jwtToken = oAuth2Service.loginGithub(oAuth2User, oauthToken);
} else if ("google".equalsIgnoreCase(provider)) {
jwtToken = oAuth2Service.loginGoogle(oAuth2User, oauthToken);
} else {
throw new IllegalStateException("Unexpected provider: " + provider);
}
response.sendRedirect(oAuth2RedirectsSuccess + jwtToken);
})
);
🧩 Google Login Service Logic
If you’re curious how oAuth2Service.loginGoogle() is implemented, you can see the full logic here:
In short:
- Spring Security sends the Google OAuth user details.
- The service creates or updates the user in the N1netails database.
- A JWT token is generated for the SPA (Angular).
- No passwords are stored—identity is validated by Google.
This is one of the biggest benefits of OAuth2:
authentication is delegated to the provider, reducing security risk in your system.
🖥️ Google Login on the Angular Frontend
Google Jules also helped mirror the GitHub login button structure on the Angular side.
HTML reference:
https://github.com/n1netails/n1netails/blob/v0.3.14/n1netails-ui/src/main/typescript/src/app/pages/login/login.component.html#L71-L81
<button
*ngIf="googleAuthEnabled"
nz-button
nzType="primary"
(click)="loginWithGoogle()"
class="login-btn google-login-btn"
type="button"
>
<nz-icon nzType="google" nzTheme="outline" style="margin-right: 8px;" />
Login with Google
</button>
Angular Login Method
loginWithGoogle() {
// window.location.href = 'http://localhost:9901/oauth2/authorization/google';
window.location.href = this.uiConfigService.getApiUrl() + '/oauth2/authorization/google';
}
The commented line (http://localhost:9901/...) is just the default local Spring Boot OAuth2 endpoint during development.
📌 Full Pull Request
To see every change involved in adding Google OAuth2 to both Spring Boot and Angular:
👉 https://github.com/n1netails/n1netails/pull/203/files
⭐ Final Thoughts
Using Google Jules to extend my OAuth2 implementation saved time and helped keep the pattern consistent across providers.
If you're building a Spring Boot + Angular app and want to offer multiple OAuth providers (GitHub, Google, etc.), this approach is clean, reusable, and secure.
If you found this helpful, please consider starring the repo 💙
👉 https://github.com/n1netails/n1netails
Top comments (0)