-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Feature/#62/login apple
- Loading branch information
Showing
4 changed files
with
119 additions
and
10 deletions.
There are no files selected for viewing
96 changes: 86 additions & 10 deletions
96
src/main/java/com/umc/networkingService/domain/member/client/AppleMemberClient.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,106 @@ | ||
package com.umc.networkingService.domain.member.client; | ||
|
||
import com.umc.networkingService.domain.member.dto.client.AppleResponse; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.umc.networkingService.domain.member.dto.client.ApplePublicKeyResponse; | ||
import com.umc.networkingService.global.common.exception.RestApiException; | ||
import com.umc.networkingService.global.common.exception.code.AuthErrorCode; | ||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.Jwts; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.reactive.function.client.WebClient; | ||
|
||
import java.io.UnsupportedEncodingException; | ||
import java.math.BigInteger; | ||
import java.security.KeyFactory; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.security.PublicKey; | ||
import java.security.spec.InvalidKeySpecException; | ||
import java.security.spec.RSAPublicKeySpec; | ||
import java.util.Base64; | ||
import java.util.Map; | ||
|
||
@Component | ||
public class AppleMemberClient { | ||
private WebClient webClient; | ||
|
||
public AppleMemberClient(WebClient.Builder webclientBuilder){ | ||
this.webClient = webclientBuilder | ||
.baseUrl("https://appleid.apple.com/auth/keys") | ||
.baseUrl("https://appleid.apple.com/auth") | ||
.build(); | ||
} | ||
|
||
public String getappleClientID(final String accessToken){ | ||
AppleResponse response = webClient.get() | ||
.header("Authorization", "Bearer " + accessToken) | ||
public String getappleClientID(final String accessToken) { | ||
Claims claims = getClaimsBy(accessToken); | ||
validateClaims(claims); | ||
|
||
return claims.getSubject(); | ||
} | ||
|
||
/* | ||
* μ ν κ²μ¦ λ¨κ³ (https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/verifying_a_user) | ||
* 1. μλ²μ κ³΅κ° ν€λ₯Ό μ¬μ©νμ¬ JWS E256 μλͺ μ κ²μ¦ | ||
* 2. μΈμ¦μ λν nonceλ₯Ό κ²μ¦ | ||
* 3. iss νλκ° https://appleid.apple.comμ ν¬ν¨νλμ§ νμΈ | ||
* 4. aud νλκ° κ°λ°μμ ν΄λΌμ΄μΈνΈ IDλ₯Ό ν¬ν¨νλμ§ νμΈ | ||
* 5. νμ¬ μκ°μ κΈ°μ€μΌλ‘ exp νλκ° μ ν¨νμ§ νμΈ | ||
* */ | ||
|
||
//1. Appleμ 곡κ°ν€λ₯Ό μ¬μ©νμ¬ identityTokenμ κ²μ¦ | ||
|
||
//InvalidKeySpecException, NoSuchAlgorithmException, UnsupportedEncodingException, JsonProcessingException | ||
public Claims getClaimsBy(String identityToken) { | ||
|
||
try { | ||
ApplePublicKeyResponse response = getAppleAuthPublicKey(); //곡κ°ν€ κ°μ Έμ€κΈ° | ||
|
||
//κ³΅κ° ν€λ₯Ό μ¬μ©νμ¬ identityTokenμ κ²μ¦ | ||
String headerOfIdentityToken = identityToken.substring(0, identityToken.indexOf(".")); | ||
Map<String, String> header = new ObjectMapper().readValue(new String(Base64.getDecoder().decode(headerOfIdentityToken), "UTF-8"), Map.class); | ||
ApplePublicKeyResponse.Key key = response.getMatchedKeyBy(header.get("kid"), header.get("alg")) | ||
.orElseThrow(() -> new RestApiException(AuthErrorCode.FAILED_GET_APPLE_KEY)); //곡κ°ν€λ₯Ό κ°μ Έμ€λλ° μ€ν¨ | ||
|
||
byte[] nBytes = Base64.getUrlDecoder().decode(key.getN()); | ||
byte[] eBytes = Base64.getUrlDecoder().decode(key.getE()); | ||
|
||
BigInteger n = new BigInteger(1, nBytes); | ||
BigInteger e = new BigInteger(1, eBytes); | ||
|
||
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n, e); | ||
KeyFactory keyFactory = KeyFactory.getInstance(key.getKty()); | ||
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); | ||
|
||
return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(identityToken).getBody(); | ||
}catch (InvalidKeySpecException | NoSuchAlgorithmException | UnsupportedEncodingException | JsonProcessingException e) { | ||
throw new RestApiException(AuthErrorCode.FAILED_GET_APPLE_KEY); | ||
} | ||
} | ||
|
||
public ApplePublicKeyResponse getAppleAuthPublicKey() { //Appleμ 곡κ°ν€λ₯Ό κ°μ Έμ€κΈ° | ||
return webClient.get() | ||
.uri("/keys") | ||
.retrieve() | ||
.bodyToMono(AppleResponse.class) | ||
.bodyToMono(ApplePublicKeyResponse.class) | ||
.block(); | ||
} | ||
|
||
//2. μΈμ¦μ λν nonceλ₯Ό κ²μ¦ | ||
//3. iss νλκ° https://appleid.apple.comμ ν¬ν¨νλμ§ νμΈ | ||
//4. aud νλκ° κ°λ°μμ ν΄λΌμ΄μΈνΈ IDλ₯Ό ν¬ν¨νλμ§ νμΈ | ||
//5. νμ¬ μκ°μ κΈ°μ€μΌλ‘ exp νλκ° μ ν¨νμ§ νμΈ | ||
public void validateClaims(Claims claims) { | ||
if (claims == null){ | ||
throw new RestApiException(AuthErrorCode.FAILED_SOCIAL_LOGIN); | ||
} | ||
|
||
//TODO μ 보 λ°κΈ° μ€ν¨ μμΈ μ²λ¦¬ | ||
if(response == null) | ||
return null; | ||
if (!claims.getIssuer().contains("https://appleid.apple.com")) | ||
throw new RestApiException(AuthErrorCode.INVALID_APPLE_ID_TOKEN); | ||
|
||
return response.getSub(); | ||
//if (!claims.getAudience().contains("com.networkingService.umc")) | ||
// throw new RestApiException(AuthErrorCode.INVALID_APPLE_ID_TOKEN); | ||
|
||
if (claims.getExpiration().before(new java.util.Date())) | ||
throw new RestApiException(AuthErrorCode.INVALID_APPLE_ID_TOKEN); | ||
} | ||
} | ||
|
30 changes: 30 additions & 0 deletions
30
src/main/java/com/umc/networkingService/domain/member/dto/client/ApplePublicKeyResponse.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.umc.networkingService.domain.member.dto.client; | ||
|
||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
@Getter | ||
@Setter | ||
public class ApplePublicKeyResponse { | ||
private List<Key> keys; | ||
|
||
@Getter | ||
@Setter | ||
public static class Key { | ||
private String kty; | ||
private String kid; | ||
private String use; | ||
private String alg; | ||
private String n; | ||
private String e; | ||
} | ||
|
||
public Optional<Key> getMatchedKeyBy(String kid, String alg) { | ||
return this.keys.stream() | ||
.filter(key -> key.getKid().equals(kid) && key.getAlg().equals(alg)) | ||
.findFirst(); | ||
} | ||
} |
This file contains 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
This file contains 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