From 3451b653f53a2c4d4f2e1d562858c5cf3a889e66 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Thu, 25 Jul 2024 15:16:30 +0900 Subject: [PATCH 1/2] feature apple login --- build.gradle | 1 + .../OnO/backend/Auth/AppleTokenVerifier.java | 38 +++++++++++++++++++ .../backend/controller/AuthController.java | 33 ++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 src/main/java/com/aisip/OnO/backend/Auth/AppleTokenVerifier.java diff --git a/build.gradle b/build.gradle index 469c692..e68b6c0 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,7 @@ dependencies { implementation group: 'com.google.auth', name: 'google-auth-library-oauth2-http', version: '1.23.0' implementation group: 'com.google.http-client', name: 'google-http-client-jackson2', version: '1.44.2' implementation group: 'org.springframework.security', name: 'spring-security-core', version: '6.3.1' + implementation group: 'com.auth0', name: 'jwks-rsa', version: '0.22.1' implementation 'org.springframework.boot:spring-boot-starter-security' // Hibernate Core implementation 'org.hibernate:hibernate-core:6.5.2.Final' diff --git a/src/main/java/com/aisip/OnO/backend/Auth/AppleTokenVerifier.java b/src/main/java/com/aisip/OnO/backend/Auth/AppleTokenVerifier.java new file mode 100644 index 0000000..98dde98 --- /dev/null +++ b/src/main/java/com/aisip/OnO/backend/Auth/AppleTokenVerifier.java @@ -0,0 +1,38 @@ +package com.aisip.OnO.backend.Auth; + +import com.auth0.jwk.Jwk; +import com.auth0.jwk.JwkProvider; +import com.auth0.jwk.UrlJwkProvider; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.security.interfaces.RSAPublicKey; + +@Component +public class AppleTokenVerifier { + + private static final String APPLE_ISSUER = "https://appleid.apple.com"; + private static final String APPLE_KEYS_URL = "https://appleid.apple.com/auth/keys"; + + public DecodedJWT verifyToken(String idTokenString) throws GeneralSecurityException, IOException { + try { + JwkProvider provider = new UrlJwkProvider(new URL(APPLE_KEYS_URL)); + DecodedJWT jwt = JWT.decode(idTokenString); + Jwk jwk = provider.get(jwt.getKeyId()); + Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null); + JWTVerifier verifier = JWT.require(algorithm) + .withIssuer(APPLE_ISSUER) + .build(); + + return verifier.verify(idTokenString); + } catch (Exception e) { + throw new GeneralSecurityException("Invalid ID token."); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/aisip/OnO/backend/controller/AuthController.java b/src/main/java/com/aisip/OnO/backend/controller/AuthController.java index 4169770..b55bd22 100644 --- a/src/main/java/com/aisip/OnO/backend/controller/AuthController.java +++ b/src/main/java/com/aisip/OnO/backend/controller/AuthController.java @@ -1,9 +1,11 @@ package com.aisip.OnO.backend.controller; +import com.aisip.OnO.backend.Auth.AppleTokenVerifier; import com.aisip.OnO.backend.service.AuthService; import com.aisip.OnO.backend.Auth.GoogleTokenVerifier; import com.aisip.OnO.backend.Auth.JwtTokenProvider; import com.aisip.OnO.backend.entity.User; +import com.auth0.jwt.interfaces.DecodedJWT; import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.common.io.BaseEncoding; import org.springframework.beans.factory.annotation.Autowired; @@ -21,6 +23,9 @@ public class AuthController { @Autowired private GoogleTokenVerifier googleTokenVerifier; + @Autowired + private AppleTokenVerifier appleTokenVerifier; + @Autowired private AuthService authService; @@ -49,13 +54,41 @@ public ResponseEntity googleLogin(@RequestBody TokenRequest tokenRequest) { } } + @PostMapping("/apple") + public ResponseEntity appleLogin(@RequestBody TokenRequest tokenRequest) { + try { + DecodedJWT jwt = appleTokenVerifier.verifyToken(tokenRequest.getIdToken()); + String email = tokenRequest.getEmail(); + String name = tokenRequest.getName(); + User user = authService.registerOrLoginUser(email, name); + String token = jwtTokenProvider.createToken(user.getUserId(), user.getEmail()); + return ResponseEntity.ok(new AuthResponse(token)); + } catch (Exception e) { + e.printStackTrace(); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new ErrorResponse("Invalid Apple token")); + } + } + + public static class TokenRequest { private String idToken; + private String email; + + private String name; + public String getIdToken() { return idToken; } + public String getEmail(){ + return email; + } + + public String getName() { + return name; + } + public void setIdToken(String idToken) { this.idToken = idToken; } From e5196b9cdbc60ec24b2d0fe47711d56f79394aae Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Fri, 26 Jul 2024 13:45:55 +0900 Subject: [PATCH 2/2] start device test --- .../OnO/backend/Auth/GoogleTokenVerifier.java | 22 ++++++++++++++++++- .../backend/controller/AuthController.java | 8 ++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/aisip/OnO/backend/Auth/GoogleTokenVerifier.java b/src/main/java/com/aisip/OnO/backend/Auth/GoogleTokenVerifier.java index 36b7fce..dae817a 100644 --- a/src/main/java/com/aisip/OnO/backend/Auth/GoogleTokenVerifier.java +++ b/src/main/java/com/aisip/OnO/backend/Auth/GoogleTokenVerifier.java @@ -14,10 +14,19 @@ @Component public class GoogleTokenVerifier { + /* @Value("${spring.security.oauth2.client.registration.google.client-id}") private String clientId; // static 제거 + */ - public GoogleIdToken.Payload verifyToken(String idTokenString) throws GeneralSecurityException, IOException { + @Value("${spring.security.oauth2.client.registration.google.client-id.android}") + private String androidClientId; + + @Value("${spring.security.oauth2.client.registration.google.client-id.ios}") + private String iosClientId; + + public GoogleIdToken.Payload verifyToken(String idTokenString, String platform) throws GeneralSecurityException, IOException { + String clientId = getClientIdByPlatform(platform); GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new JacksonFactory()) .setAudience(Collections.singletonList(clientId)) @@ -30,4 +39,15 @@ public GoogleIdToken.Payload verifyToken(String idTokenString) throws GeneralSec throw new GeneralSecurityException("Invalid ID token."); } } + + private String getClientIdByPlatform(String platform) { + switch (platform.toLowerCase()) { + case "android": + return androidClientId; + case "ios": + return iosClientId; + default: + throw new IllegalArgumentException("Invalid platform specified"); + } + } } \ No newline at end of file diff --git a/src/main/java/com/aisip/OnO/backend/controller/AuthController.java b/src/main/java/com/aisip/OnO/backend/controller/AuthController.java index b55bd22..39777c8 100644 --- a/src/main/java/com/aisip/OnO/backend/controller/AuthController.java +++ b/src/main/java/com/aisip/OnO/backend/controller/AuthController.java @@ -35,7 +35,7 @@ public class AuthController { @PostMapping("/google") public ResponseEntity googleLogin(@RequestBody TokenRequest tokenRequest) { try { - GoogleIdToken.Payload payload = googleTokenVerifier.verifyToken(tokenRequest.getIdToken()); + GoogleIdToken.Payload payload = googleTokenVerifier.verifyToken(tokenRequest.getIdToken(), tokenRequest.getPlatform()); User user = authService.registerOrLoginUser(payload.getEmail(), (String) payload.get("name")); String token = jwtTokenProvider.createToken(user.getUserId(), user.getEmail()); return ResponseEntity.ok(new AuthResponse(token)); @@ -73,6 +73,8 @@ public ResponseEntity appleLogin(@RequestBody TokenRequest tokenRequest) { public static class TokenRequest { private String idToken; + private String platform; + private String email; private String name; @@ -89,6 +91,10 @@ public String getName() { return name; } + public String getPlatform() { + return platform; + } + public void setIdToken(String idToken) { this.idToken = idToken; }