Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package org.runnect.server.auth.service;


import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.jwk.source.RemoteJWKSet;
import com.nimbusds.jose.proc.JWSVerificationKeySelector;
import com.nimbusds.jose.proc.SecurityContext;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
import com.nimbusds.jwt.proc.DefaultJWTProcessor;
import lombok.RequiredArgsConstructor;
import okhttp3.OkHttpClient;
import okhttp3.FormBody;
Expand All @@ -13,9 +20,8 @@
import org.runnect.server.common.exception.UnauthorizedException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.nimbusds.jwt.SignedJWT;

import java.text.ParseException;
import java.net.URL;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
Expand Down Expand Up @@ -45,6 +51,8 @@ public class AppleSignInService {

@Value("${apple.revoke-url}")
private String APPLE_REVOKE_URL;
private static final String APPLE_JWKS_URL = "https://appleid.apple.com/auth/keys";

private PrivateKey PRIVATE_KEY;
@Value("${apple.p8key}")
private void getPrivateKey(String P8KEY){
Expand All @@ -61,13 +69,12 @@ private void getPrivateKey(String P8KEY){

public SocialInfoResponseDto getSocialInfo(String idToken) {


// 클라에서 준 인증토큰이 정말 애플에서 발급받은게 맞는지 확인
// (애플 공개키(JWKS)로 서명을 검증해야만 위조된 토큰을 걸러낼 수 있다 —
// 서명 검증 없이 파싱만 하면 누구나 클레임을 임의로 채운 토큰으로 로그인할 수 있음)

try{
//1. idToken을 parse
SignedJWT jwt = SignedJWT.parse(idToken);
JWTClaimsSet claimsSet = jwt.getJWTClaimsSet();
JWTClaimsSet claimsSet = verifySignatureAndGetClaims(idToken);

// 발급처, aud, 시간제한, 이메일 검증

Expand All @@ -90,13 +97,27 @@ public SocialInfoResponseDto getSocialInfo(String idToken) {

return SocialInfoResponseDto.of(claimsSet.getStringClaim("email"), claimsSet.getSubject());

}catch (ParseException e){
}catch (UnauthorizedException e){
throw e;
}catch (Exception e){
// 서명 검증 실패(BadJOSEException), 파싱 실패(ParseException), JWKS 조회 실패(JOSEException) 등
// 위조/변조된 토큰 또는 애플 검증 자체가 불가능한 경우 전부 동일하게 처리
throw new UnauthorizedException(ErrorStatus.INVALID_APPLE_ID_TOKEN_EXCEPTION,
ErrorStatus.INVALID_APPLE_ID_TOKEN_EXCEPTION.getMessage());
}

}

private JWTClaimsSet verifySignatureAndGetClaims(String idToken) throws Exception {
JWKSource<SecurityContext> keySource = new RemoteJWKSet<>(new URL(APPLE_JWKS_URL));
ConfigurableJWTProcessor<SecurityContext> jwtProcessor = new DefaultJWTProcessor<>();
JWSVerificationKeySelector<SecurityContext> keySelector =
new JWSVerificationKeySelector<>(JWSAlgorithm.RS256, keySource);
jwtProcessor.setJWSKeySelector(keySelector);
// 서명이 유효하지 않으면 여기서 BadJOSEException/JOSEException이 던져진다
return jwtProcessor.process(idToken, null);
}

// id_token 형태 :
// {
// "aud": 번들아이디,
Expand Down
Loading