Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

Β 

History

51 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Auth-Prod

  • step1 : backend project setup

  • step2: frontend at different origin so CORS

  • adding Jwt filters

  • Oauth concept -pending

  • Security : access_token and refresh_token both only access by one user only / self only

API Documation : Swagger

http://localhost:{9081==PORT}/swagger-ui/index.html#/

Postman

https://crimson-comet-847628.postman.co/workspace/springBoot-fitness~3624bf6f-c3b5-4845-b04e-6d7f7fcd62fc/collection/25455646-cd70689a-dba5-41cc-8c5e-2caa1c08674c?action=share&creator=25455646

[TODO] Oauth with google/github server----------do it rightnow

Oauth -- Only Treat on backend --[Backend As a Service]

πŸ” OAuth2 Login with Google & GitHub

Backend as a Service (Spring Boot Only)


πŸ“Œ Overview

This project implements OAuth2 authentication using Google and GitHub in a Spring Boot backend.

It follows a Backend-as-a-Service (BaaS) pattern:

  • No frontend token handling logic
  • Backend manages OAuth flow
  • Backend generates JWT tokens
  • Backend acts as:
    • OAuth2 Client
    • Internal JWT Authorization Server
    • Resource Server (secured APIs)

πŸ— Architecture

User
↓
Browser (React or any client)
↓
Spring Boot Backend
↓
Google / GitHub (OAuth Provider)


🎯 Roles Explained

Component Role
Browser / React Triggers login
Spring Boot OAuth Client + JWT Issuer + Resource Server
Google / GitHub External Authentication Provider
JWT Secures APIs

/login ==> JWT

1. SecurityConfig          β€” stateless, permit /auth/**, filter chain
2. JwtService              β€” generate / validate / extract claims
3. JwtAuthFilter           β€” OncePerRequestFilter, reads Bearer token
4. UserDetailsServiceImpl  β€” loadUserByUsername via email
5. AuthService             β€” authenticate, persist refresh, generate tokens
6. AuthController          β€” POST /api/v1/auth/login

sequence

Client β†’ POST /login (email, password)
  β†’ AuthController
    β†’ AuthService.login()
      β†’ AuthenticationManager.authenticate()         [1. verify credentials]
        β†’ UserDetailsServiceImpl.loadUserByUsername() [2. load from DB]
      β†’ RefreshTokenRepository.save()                [3. persist jti to DB]
      β†’ JwtService.generateAccessToken()             [4. sign access JWT]
      β†’ JwtService.generateRefreshToken(jti)         [5. sign refresh JWT]
      β†’ CookieService.attachRefreshTokenCookie()     [6. HttpOnly cookie]
  ← LoginResponse(accessToken, expiresIn, "Bearer")

Every subsequent request:
Client β†’ GET /any (Authorization: Bearer <token>)
  β†’ JwtAuthFilter
    β†’ JwtService.extractEmail()
    β†’ UserDetailsServiceImpl.loadUserByUsername()
    β†’ SecurityContextHolder.setAuthentication()
  β†’ Controller (authenticated)

πŸ” OAuth Flow (Backend Only)

1. SecurityConfig          β€” add oauth2Login, successHandler, failureHandler
2. OAuth2UserInfo          β€” abstract, normalize Google/GitHub provider data
3. GoogleOAuth2UserInfo    β€” extract fields from Google attributes
4. GithubOAuth2UserInfo    β€” extract fields from GitHub attributes
5. CustomOAuth2UserService β€” loadUser, upsert User in DB
6. OAuth2SuccessHandler    β€” generate JWT, attach cookie, redirect
7. OAuth2FailureHandler    β€” redirect with error param

sequence

Client β†’ GET /oauth2/authorize/google
  β†’ Spring redirects to Google consent screen

Google β†’ GET /login/oauth2/code/google?code=xxx
  β†’ CustomOAuth2UserService.loadUser()
    β†’ fetch attributes from Google
    β†’ OAuth2UserInfoFactory.getOAuth2UserInfo()   [normalize provider data]
    β†’ userRepository.findByEmail()
      β†’ EXISTS  β†’ update name/image                [returning user]
      β†’ NOT EXISTS β†’ create new User               [first time OAuth]
  β†’ OAuth2SuccessHandler.onAuthenticationSuccess()
    β†’ RefreshTokenRepository.save(jti)
    β†’ JwtService.generateAccessToken()
    β†’ JwtService.generateRefreshToken(jti)
    β†’ CookieService.attachRefreshTokenCookie()
    β†’ redirect β†’ frontend/dashboard?accessToken=xxx

Client (subsequent requests same as JWT flow)
  β†’ JwtAuthFilter β†’ SecurityContext β†’ Controller

OIDC vs OAuth2

OAuth2   β†’ "Can I access your Google data?"     β†’ gives you ACCESS TOKEN
OIDC     β†’ "Who are you?"                        β†’ gives you ID TOKEN (JWT with user claims)

OAuth2UserService  β†’ calls /userinfo endpoint separately to get user data
OidcUserService    β†’ ID token already HAS user claims (sub, email, name, picture)
                     no extra HTTP call needed β†’ faster + standard

What changes from your current OAuth2 setup

CustomOAuth2UserService   β†’  CustomOidcUserService
  extends DefaultOAuth2UserService  β†’  extends OidcUserService
  OAuth2User return type            β†’  OidcUser return type
  manual attribute extraction       β†’  standardClaims() built-in

SecurityConfig
  .userService(customOAuth2UserService)   β†’  .oidcUserService(customOidcUserService)

application.yml
  scope: email, profile   β†’  scope: openid, email, profile   ← openid triggers OIDC

sequence

Client β†’ GET /oauth2/authorize/google
  β†’ Spring appends scope=openid β†’ triggers OIDC flow

Google β†’ returns ID TOKEN (JWT) + optional access token
  β†’ Spring validates ID token signature (via Google JWKS endpoint)
  β†’ Spring calls CustomOidcUserService.loadUser()
    β†’ OidcUserInfo has standardClaims() β€” no extra /userinfo call
    β†’ upsert User in DB same as before
  β†’ OAuth2SuccessHandler (unchanged)
    β†’ generate JWT, attach cookie, redirect

OAuth2 vs OIDC side by side

OAuth2 (GitHub)              OIDC (Google)
─────────────────────────────────────────────────────────────────
scope               user:email, read:user        openid, email, profile
token returned      access token only            ID token (JWT) + access token
user data           extra /userinfo HTTP call     already in ID token claims
signature verify    no                           yes β€” Spring checks Google JWKS
your service        CustomOAuth2UserService      CustomOidcUserService
principal type      OAuth2User                   OidcUser
email extracted     attributes.get("email")      oidcUser.getEmail()
sub claim           attributes.get("id")         oidcUser.getSubject()

APIs

POST /api/v1/auth/register   β†’  email/password β†’ JWT
POST /api/v1/auth/login      β†’  email/password β†’ JWT
GET  /oauth2/authorize/google β†’  OIDC  β†’ ID token validated β†’ JWT
GET  /oauth2/authorize/github β†’  OAuth2 β†’ /userinfo call   β†’ JWT

All three end up at OAuth2SuccessHandler or AuthService
β†’ same RefreshToken table
β†’ same JwtService
β†’ same HttpOnly cookie + accessToken response
  1. User clicks Login with Google/GitHub

  2. Browser redirects to:

    /oauth2/authorization/google
    
  3. Spring Boot redirects to Google/GitHub

  4. User authenticates

  5. Provider redirects to:

    ${api_domain:http://localhost}:${PORT}/login/oauth2/code/google
    
  6. Spring Boot:

    • Receives authorization code
    • Exchanges code for access token
    • Fetches user info
    • Creates or updates user in DB
    • Generates:
      • JWT Access Token
      • JWT Refresh Token
    • Stores refresh token in DB
    • Sends:
      • Access token in redirect URL
      • Refresh token as HttpOnly cookie

πŸ”‘ Authorized Redirect URLs

Configure in Google/GitHub console:

http://localhost:9081/login/oauth2/code/google
http://localhost:9081/login/oauth2/code/github

🧠 System Design

Backend Acts As:

1️⃣ OAuth2 Client

Configured using:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: YOUR_GOOGLE_CLIENT_ID
            client-secret: YOUR_GOOGLE_CLIENT_SECRET

2️⃣ Authorization Server (Internal JWT Issuer)

After successful OAuth login:

  • Generates Access Token
  • Generates Refresh Token
  • Stores refresh token in database

3️⃣ Resource Server

All secured APIs validate:

  • JWT Access Token
  • Token expiry
  • User roles

πŸ” Token Strategy

Token Storage TTL
Access Token Frontend (memory) Short-lived
Refresh Token HttpOnly Cookie + DB Long-lived

πŸ—‚ Database Tables

users

  • id
  • email
  • name
  • provider
  • providerId
  • roles

refresh_tokens

  • id
  • jti
  • user_id
  • revoked
  • expires_at

πŸš€ Login Endpoints

Provider Endpoint
Google /oauth2/authorization/google
GitHub /oauth2/authorization/github

πŸ“¦ Required Dependency

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

πŸ”’ Production Notes

  • Set cookie-secure: true
  • Use HTTPS
  • Rotate JWT secret
  • Implement refresh token revocation
  • Add role-based authorization
  • Enable correlation ID logging

🎯 Final Summary

βœ” Uses Google & GitHub as authentication providers
βœ” Issues its own JWT tokens
βœ” Stores refresh tokens securely
βœ” Acts as OAuth client and resource server
βœ” No frontend token logic required


About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages