Feature/oauth2 google login - #47
Merged
Merged
Conversation
declaration fix
The previous teams created two independent services (backend and testapi) to run the TestAPI functionality, but only backend-team2 was included in the local deployment configuration. This caused the backend to fail when trying to forward API test execution requests to the testapi service. Changes: - Add testapi-team2 service definition (build from testapi-Service/testapi, port 8082, mapped to host 8086) - Fix TEST_API_SERVICE_PORT for backend-team2 (8080 -> 8082) - Add testapi-team2 to backend-team2 depends_on
The testapi microservice crashed with NullPointerException or unhandled ConnectException when: 1. The target API was unreachable (e.g. DNS resolution failure inside Docker container) 2. The request body was missing optional fields like expectedHeaders Changes: - Add try-catch in execute() to handle ConnectException when the target API is unreachable - Add null check for response in getAnswer() to return a structured error message instead of crashing - Add null check in checkResponseHeaders() for missing expectedHeaders field Before: 500 Internal Server Error with raw stack trace After: Structured JSON response with clear error message
The testapi container could not resolve external domain names due to Docker's internal DNS limitations, causing Rest-Assured API calls to fail with ConnectException. Added Google public DNS (8.8.8.8, 8.8.4.4) to testapi-team2 service to enable external API access from within the container.
Updated field annotations to provide meaningful default values in Swagger UI "Try it out", replacing generic "string" placeholders with realistic examples (method: GET, apiUrl: jsonplaceholder endpoint, statusCode: 200). This makes the Swagger interface more user-friendly for testing and demo purposes.
Java and spring boot version conflict solved
Backend crashes with E11000 duplicate key error on taf.roles collection every time it restarts against an existing MongoDB instance. This happens because Spring Data MongoDB attempts to recreate the unique index on the Role.name field at every startup, conflicting with already existing data. Changed auto-index-creation from true to false in application.yml. The index already exists from the first successful startup, so there is no need to recreate it on every restart.
Multiple .env and config files contained hardcoded external IPs (185.133.251.89, 15.133.251.89, 198.7.119.0) from previous semesters' AWS deployments that no longer exist. These have been replaced with localhost for local development. Changes: - testapi-Service/.env: Fix typos (DOKCER→DOCKER, PASWORD→PASSWORD, PERFORMACE→PERFORMANCE), replace external IPs with localhost, update MongoDB credentials to local defaults - testapi-Service/backend/.env: Replace DB_URI and EUREKA_HOST external IPs with localhost - frontend environment.ts: Update apiUrl from external IP to localhost - build.sh: Sync variable references with corrected spelling - Delete .docker_config.env.old (contained stale plaintext credentials)
- Remove 8 duplicate variables from root .env that already exist in backend/.env (DB_URI, DB_NAME, DB_AUTH, EUREKA_HOST/PORT/USERNAME/PASSWORD, GATEWAY_PORT) - Remove 3 dead variables from root .env never referenced by any config (GATEWAY_HOST, PERFORMANCE_DB_NAME, PERFORMANCE_DB_URI) - Remove 5 lines of commented-out MySQL config from backend/.env containing hardcoded credentials, typos (DATABSE, HIBERNETE) - Root .env now only holds Docker build variables; backend/.env holds all Spring Boot runtime variables
Activate the dormant JWT authentication system and integrate it with Swagger UI for the TAF backend. Changes: Rename AuthController.java_ → AuthController.java to enable /api/auth/signup and /api/auth/signin endpoints Configure WebSecurityConfig to enforce authentication: only auth, swagger, actuator, test, and error paths are public; all other requests require a valid JWT Create OpenApiConfig.java with @Securityscheme (Bearer JWT) and server URLs (localhost:8084, gateway, relative) Add @securityrequirement("bearerAuth") to TestApiController, GatlingApiController, TestSeleniumController, TestController Add @Schema examples to SignupRequest and LoginRequest for better Swagger UI defaults Add jaxb-api:2.3.1 dependency to fix javax.xml.bind.DatatypeConverter ClassNotFoundException with jjwt:0.9.1 on Java 17 Add okhttp:4.12.0 version, upgrade maven-compiler-plugin to 3.13.0 Upgrade spring-boot to 3.5.10, add xstream:1.4.21 to fix CVE-2024-47072 Update settings.json for Java Language Server Maven project recognition
…ests d'API - Ajout table des matières avec ancres - Ajout diagramme de flux du test d'API (Frontend → Backend → TestAPI → API cible) - Ajout section complète Tests d'API : utilisation UI, format requête/réponse JSON, 3 assertions (status code, corps JSON, en-têtes), exemple curl - Compression de la section Authentification (JWT + OAuth2 en résumé) - Réorganisation générale : fonctionnalité principale avant authentification
…s contrôleurs - Ajout @nonnull sur les paramètres de méthodes pour supprimer les avertissements - Fichiers modifiés : DevCorsConfiguration, JwtAuthenticationFilter, UserRepository
michelzzw
force-pushed
the
feature/oauth2-google-login
branch
from
February 13, 2026 04:10
1a97f06 to
5839077
Compare
- Utiliser le header 'Authorization' au lieu de 'x-access-token' dans l'intercepteur HTTP (compatibilité Spring Boot) - Lire le champ 'token' du service auth en plus de 'accessToken' lors du login (compatibilité avec le microservice auth séparé)
…a EE - Migrer javax.validation vers jakarta.validation (Spring Boot 3.x) - Gérer le cas NullNode dans checkOutput() pour éviter les faux négatifs - Ignorer la vérification du temps de réponse quand non défini (responseTime <= 0) - Optimiser le Dockerfile avec -DskipTests -B pour accélérer le build
Removed contact information section from README.
cal-lie
self-requested a review
March 10, 2026 19:13
michelzzw
added a commit
that referenced
this pull request
Mar 11, 2026
cal-lie
approved these changes
Mar 11, 2026
Valeeeu
self-requested a review
March 11, 2026 23:48
Valeeeu
approved these changes
Mar 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Équipe 3 – Phase 2: Google OAuth2 Authentication + Code Quality
Summary
This PR delivers the second part of the Phase 2 milestone for Équipe 3 — Google OAuth2 Login, Code Cleanup & Documentation. The objective was to add a second authentication method (Google OAuth2) alongside the existing JWT system, integrate it into the Angular frontend, clean up code quality issues across the entire Team 2 codebase, and update the README.
When we started this work, the application only supported username/password authentication via JWT (delivered in the first Phase 2 PR). There was no social login capability, and the codebase contained numerous unused imports, dead code, logic bugs, and an outdated README referencing deleted configuration files.
After our changes, users can log in with either their local credentials (JWT) or their Google account (OAuth2). The Angular frontend has a "Se connecter avec Google" button on the login page. After a successful Google login, the user is automatically registered in MongoDB (or linked to an existing account) and receives a JWT token — the same token format used by the local login, ensuring a unified authentication experience. Additionally, 20+ code quality issues have been fixed across 6 modules, and the README has been completely rewritten.
Problems Found & Changes Made
1. No social login — only username/password authentication
Problem: The application only supported local registration and login. Users had to create a new account with a unique username, email, and password. There was no way to use an existing identity provider (e.g., Google) to sign in, which is inconvenient for users who prefer single sign-on.
Changes (Backend — OAuth2 Integration):
spring-boot-starter-oauth2-clientdependency to bothbackend/pom.xmlandbackend/pom.docker.xmlapplication.yml:${GOOGLE_CLIENT_ID}and${GOOGLE_CLIENT_SECRET}(defaults toplaceholderif not set)openid, profile, emailoauth2FrontendRedirectUrlproperty to control where the frontend callback livesOAuth2LoginSuccessHandler.java(security/oauth2/):SimpleUrlAuthenticationSuccessHandlersub(Google ID),email, andnamefrom the OAuth2 principalgoogleId→ find byemail(link existing account) → create new userJwtUtils.generateJwtTokenForUsername(){frontendRedirectUrl}/oauth2/callback?token={jwt}&userInfo={base64}@Autowired ObjectMapper(Spring DI, notnew ObjectMapper()) per project conventionsOAuth2Controller.java(controller/):GET /api/oauth2/login-url— returns the OAuth2 authorization URL (/oauth2/authorization/google) for frontend reference@Tagand@Operationfor API documentationWebSecurityConfig.java:.oauth2Login(oauth2 -> oauth2.successHandler(oAuth2LoginSuccessHandler))SessionCreationPolicy.STATELESS→SessionCreationPolicy.IF_REQUIRED— OAuth2 requires a temporary HTTP session during the authorization code exchange; JWT authentication remains stateless viaAuthTokenFilter/oauth2/**and/login/oauth2/**(Spring Security's OAuth2 endpoints)/api/oauth2/login-urlUser.javaentity:providerfield ("local"or"google")googleIdfield for Google account linkingUser(fullName, username, email, provider, googleId)for OAuth2 users withUUID.randomUUID()password@NotBlankfrompasswordfield (OAuth2 users don't have a user-chosen password)usernamemax size from 20 → 50 (Google email prefixes can be long)UserRepository.java: AddedfindByEmail()andfindByGoogleId()query methodsJwtUtils.java: AddedgenerateJwtTokenForUsername(String username)— generates a JWT directly from a username string, bypassingAuthenticationobject (needed for OAuth2 where there's no password-basedAuthentication)OpenApiConfig.java: Updated API description to mention both JWT and OAuth2 authentication methods2. No frontend support for Google login
Problem: Even with a working OAuth2 backend, there was no way for users to trigger the Google login flow from the Angular frontend.
Changes (Frontend — Angular):
OAuth2CallbackComponent(oauth2-callback/):oauth2-callback.component.ts: Subscribes to route query parameters, extractstokenanduserInfo, decodes base64url JSON, saves toTokenStorageService, and redirects to/home. Includes TypeScript type annotations (params: { [key: string]: string },token: string | undefined,userInfo: Record<string, unknown>)oauth2-callback.component.html: Shows a loading spinner during processing and a clear error message in French if authentication failsoauth2-callback.component.css: Centered layout with Google-branded color schemelogin.component.ts: AddedloginWithGoogle()method that redirects the browser toenvironment.oauth2BackendUrl + '/oauth2/authorization/google'login.component.html: Added a styled "Se connecter avec Google" button with SVG Google icon and visual separator ("— OU —") between local and Google login formslogin.component.css: Added styles for the Google button (white background, Google brand border, hover effects) and the separatorapp-routing.module.ts: Added route{ path: 'oauth2/callback', component: OAuth2CallbackComponent }app.module.ts: DeclaredOAuth2CallbackComponentenvironment.ts: Addedoauth2BackendUrl: 'http://localhost:8084'environment.prod.ts: Addedoauth2BackendUrl: 'http://localhost:8084'(Docker-mapped port)3. Docker not configured for OAuth2 credentials
Problem: The Docker Compose configuration had no way to pass Google OAuth2 credentials to the backend container.
Changes (
docker-compose-local-test.yml):backend-team2service:GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-placeholder}GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-placeholder}OAUTH2_FRONTEND_REDIRECT_URL: http://frontend-team2:4200$env:GOOGLE_CLIENT_IDand$env:GOOGLE_CLIENT_SECRETin the same shell session before runningdocker compose up4. Unused imports and dead code across 6 modules
Problem: Multiple modules contained unused imports, unreferenced fields, and dead methods — leftover from previous development phases. This increases compilation warnings, reduces readability, and violates project conventions.
Changes (Code Cleanup):
gateway/GatewayApplication.javaMapimportauth/services/CustomUserDetailsService.javaArrayListimportauth/services/JwtService.javaUser,ResponseEntity,UserDetailsimportsauth/AuthGatewayApplication.javaServiceInstance,Listimportsselenium/requests/UseSelenium.javaTimeUnit,Arraysimports; fixed deprecatedimplicitlyWait(long, TimeUnit)→implicitlyWait(Duration.ofSeconds(1)); fixed deprecatedgetAttribute()→getDomAttribute()selenium/SeleniumApplicationTests.javaTestimportuser/payload/request/PasswordRequest.javaSetimportuser/jwt/JwtUtil.javacreateToken()andrefreshToken()methods, unusedTokenClaimsimportuser/controller/UserController.javaAuthenticationManagerandJwtServicefield injectionsuser/services/JwtService.javaUser,ResponseEntity, etc. imports5. Logic bugs in UserService
Problem:
UserService.update()contained a boolean inversion bug:if (user.getFullName().isEmpty())should have beenif (!user.getFullName().isEmpty()). The method was updating fields only when they were empty, and skipping updates when values were provided — the exact opposite of intended behavior. Additionally,findById()returned null without checkingOptional.isPresent().Changes (
user/services/UserService.java):isEmpty()→!isEmpty()forfullName,email, andusernamechecks inupdate()methodisPresent()null check infindById()to avoidNoSuchElementException6. Missing
@NonNullannotations causing compiler warningsProblem: Several Spring component methods had parameters that could theoretically be null, generating
-Xlint:nullawayor IDE warnings.Changes:
selenium/config/DevCorsConfiguration.java: Added@NonNulltoaddCorsMappings(CorsRegistry)parameteruser/jwt/JwtAuthenticationFilter.java: Added@NonNulltodoFilterInternal()parametersuser/repository/UserRepository.java: Added@NonNulltofindById()parameter7. Frontend JWT authentication broken — wrong header and field name
Problem: The Angular frontend could not execute authenticated API requests. Two separate bugs were preventing the JWT token from being sent correctly:
auth.interceptor.tswas usingx-access-token(Node.js Express convention) instead ofAuthorization(Spring Boot convention). The backend'sAuthTokenFilteronly reads theAuthorizationheader.login.component.tswas readingdata.accessTokenfrom the login response, but theauthmicroservice (separate container) returns the JWT in a field namedtoken(Lombok@Getteronprivate String token). This causedsessionStorageto store"undefined", and the backend reported: "Invalid JWT token: JWT strings must contain exactly 2 period characters. Found: 0".Changes (Frontend):
auth.interceptor.ts: ChangedTOKEN_HEADER_KEYfrom'x-access-token'to'Authorization'login.component.ts: Changeddata.accessTokentodata.token || data.accessTokenfor compatibility with both the standaloneauthmicroservice and the backend's ownJwtResponse8. TestAPI microservice build failure and false test results
Problem: The TestAPI microservice had three issues:
javax.validationincompatible with Spring Boot 3.x:TestApiController.javaandTestApiRequest.javausedjavax.validationimports, but Spring Boot 3.x requiresjakarta.validation. This caused a Docker build failure.checkOutput()NullNode bug: WhenexpectedOutputis JSONnull, Jackson deserializes it asNullNode(not Javanull). The original code only checkedexpectedOutput == null, soNullNodefell through toNullNode.equals(actualResponse)→ alwaysfalse.checkResponseTime()always fails when not set: When no response time was specified (responseTime = 0),response.getTime() < 0was alwaysfalse, causing unnecessary test failures.Changes (TestAPI):
TestApiController.java/TestApiRequest.java: Migratedjavax.validation→jakarta.validationRequestController.java: AddedexpectedOutput.isNull()check incheckOutput(); addedresponseTime <= 0guard incheckResponseTime()Dockerfile: Added-DskipTests -Bflags tomvn clean installto speed up Docker buildspom.xml: Addedspring-boot-starter-validationdependency (committed in earlier phase)9. Outdated README referencing deleted files
Problem:
testapi-Service/README.mdwas significantly outdated:.docker_config.envwhich was deleted in Phase 1Changes (
testapi-Service/README.md):docker-compose-local-test.ymlTesting & Validation
Google OAuth2 Flow
localhost:8084/login/oauth2/code/googleprovider:"google", JWT generated/homegoogleId, no duplicate createdJWT Authentication (Regression Test)
/api/auth/signup/api/auth/signinOAuth2 User Account Linking
provider:"google"googleIdandproviderfields updated_g{googleId[0:6]}System Health
Files Modified (Phase 2 — OAuth2)
New Files (OAuth2 Core)
backend/src/.../security/oauth2/OAuth2LoginSuccessHandler.javabackend/src/.../controller/OAuth2Controller.javafrontend/src/app/oauth2-callback/oauth2-callback.component.tsfrontend/src/app/oauth2-callback/oauth2-callback.component.htmlfrontend/src/app/oauth2-callback/oauth2-callback.component.cssModified Files (OAuth2 Integration)
backend/src/.../security/WebSecurityConfig.java.oauth2Login(), changed session policy to IF_REQUIRED, added OAuth2 permitAll pathsbackend/src/.../entity/User.javaprovider,googleIdfields; OAuth2 constructor; relaxedpasswordvalidationbackend/src/.../repository/UserRepository.javafindByEmail(),findByGoogleId()backend/src/.../security/jwt/JwtUtils.javagenerateJwtTokenForUsername(String)for OAuth2 usersbackend/src/.../config/OpenApiConfig.javabackend/src/main/resources/application.ymloauth2FrontendRedirectUrlbackend/pom.xmlspring-boot-starter-oauth2-clientbackend/pom.docker.xmlspring-boot-starter-oauth2-clientfrontend/src/app/login/login.component.tsloginWithGoogle()methodfrontend/src/app/login/login.component.htmlfrontend/src/app/login/login.component.cssfrontend/src/app/app-routing.module.ts/oauth2/callbackroutefrontend/src/app/app.module.tsOAuth2CallbackComponentfrontend/src/environments/environment.tsoauth2BackendUrlfrontend/src/environments/environment.prod.tsoauth2BackendUrldocker-compose-local-test.ymlGOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,OAUTH2_FRONTEND_REDIRECT_URLModified Files (Frontend Auth Fix)
frontend/src/app/_helpers/auth.interceptor.tsx-access-token→Authorizationheaderfrontend/src/app/login/login.component.tsdata.accessToken→data.token || data.accessTokenModified Files (TestAPI Fix)
testapi/src/.../RequestController.javaNullNodehandling incheckOutput(), guard incheckResponseTime()testapi/src/.../TestApiController.javajavax.validation→jakarta.validationtestapi/src/.../TestApiRequest.javajavax.validation→jakarta.validationtestapi/Dockerfile-DskipTests -Bto Maven buildModified Files (Code Cleanup & Bug Fixes)
gateway/.../GatewayApplication.javaMapimportauth/.../CustomUserDetailsService.javaArrayListimportauth/.../JwtService.javaUser,ResponseEntity,UserDetailsimportsauth/.../AuthGatewayApplication.javaServiceInstance,Listimportsselenium/.../UseSelenium.javaselenium/.../SeleniumApplicationTests.javaTestimportuser/.../UserController.javaAuthenticationManager,JwtServicefieldsuser/.../JwtUtil.javacreateToken(),refreshToken()methodsuser/.../PasswordRequest.javaSetimportuser/.../JwtService.javauser/.../UserService.javaisEmpty()→!isEmpty()bug inupdate(), added null check infindById()user/.../JwtAuthenticationFilter.java@NonNullannotationsuser/.../UserRepository.java@NonNullannotationselenium/.../DevCorsConfiguration.java@NonNullannotationDocumentation
testapi-Service/README.mdCommit History
feat(oauth2)feat(frontend-oauth2)feat(docker)refactor(cleanup)fix(user)docs(testapi)refactor(backend)fix(frontend)fix(testapi)Architecture Notes
Google OAuth2 Authentication Flow
Key Design Decisions
SessionCreationPolicy.IF_REQUIREDinstead ofSTATELESSAuthTokenFiltervalidates the token on every request without touching the sessionUUID.randomUUID()generates a cryptographically random string that the user doesn't know