애플 로그인을 시작하기 전에 애플 개발자 사이트에서 ‘Services ID’ 라고 되어 있는 ‘client id’ 를 얻어야 한다. 이 포스트는 ‘Services ID’를 발급받았다고 가정하에 작성하였다.
Apple 로그인 설정하러 가기
Apple Developer Documentation 문서를 참고해서 함께 보면 좋을 것 같다.

애플 로그인 버튼 생성 & Apple JS로 로그인

Javascript를 사용해서 애플 인증 기능으로 로그인에 액세스 할 수 있다.

client-id : client id는 service id 등록 시에 입력했던 Identifier를 입력
scope : scope는 애플로 로그인 시, 애플에서 받아올 유저의 정보를 입력, 사용자의 이름이나 이메일을 요청할 수 있다. 둘 다 요청할 수 있고, 안 할 수도 있다.
redirect-uri : redirect uri는 service id 등록시에 입력했던 redirect url을 입력
state : state는 CSRF공격을 완화하기 위한 OAuth 파라미터 이다. 어떠한 문자가 들어가도 상관없지만, 아무도 추정할 수 없도록 유니크한 값이어야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<head>
<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<meta name="appleid-signin-client-id" content="${SYSTEM_APPLE_CLIENTID}">
<meta name="appleid-signin-scope" content="email">
<meta name="appleid-signin-redirect-uri" content="${SYSTEM_JSP_SITEURL}/login/snsApplelogin">
<meta name="appleid-signin-state" content="${SYSTEM_APPLE_STATE}">
<meta name="appleid-signin-use-popup" content="false"> <!-- or false defaults to false -->
</head>
<body>
<!-- 애플아이디로로그인 버튼 노출 영역 -->
<div id="appleid-signin" data-mode="logo-only" data-color="black" data-border="false" data-border-radius="15" data-size="60"></div>
</body>
</html>

여기까지하면 애플로그인 버튼이 생성되는 것을 확인할 수 있다. 버튼을 클릭하여 애플 아이디로 로그인을 하면 로그인 처리가 완료되고 응답값을 redirect-uri로 넘겨주게 될 것이다.
사용자가 Apple로 로그인 버튼을 클릭하면 프레임 워크가 인증 정보를 Apple로 보내준다. Apple은 인증 요청을 처리하고 인증 결과가 포함 된 HTTP POST 요청을 제공된 redirect-uri로 보내준다.

승인 응답값 확인

응답값은 content-type이 application/x-www-form-urlencoded 로 넘어오게 된다.

code : 5 분 동안 유효한 일회용 인증 코드
id_token : 사용자의 식별 정보가 포함 된 JSON 웹 토큰 (JWT)
state : init함수가 전달한 상태
user : scope 속성에서 요청 된 데이터가 포함 된 JSON 문자열

여기서 중요한게 user는 사용자가 앱을 처음으로 인증할 때만 개체를 반환해준다. 처음 인증할 경우에만 user객체가 넘어오고 다음 인증 부터는 user객체가 넘어오지 않는다.
사용자의 email 정보를 사용하기 위해서 id_token으로 넘어오는 JSON 웹 토큰을 decode해줄것이다. 이 문서를 보면 id_token에 포함된 데이터를 알 수 있다.

Decode된 JWT 토큰 확인

JWT는 header, payload, signature 세 파트로 나누어지며 우리는 payload 데이터를 사용할 것이다.

https://jwt.io/
위 사이트에서 Encoded에 애플에서 전달 받은 id_token 값을 입력하면, Decoded된 값을 확인 할 수 있다.
이제 payload에 있는 email 값을 사용할 수 있다.
JWT토큰확인

JWT 라이브러리 추가

실제 코드에서 Json 웹 토큰(JWT)을 처리하기 위해 JWT 관련 라이브러리를 이용해 줄 것이다.
JWT 관련 라이브러리는 “nimbus-jose-jwt(v3.10)”를 이용했다. pom.xml에 아래 코드를 추가해주었다. nimbus-jose-jwt 라이브러리 다운

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt -->
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>3.10</version>
</dependency>

Controller에서 응답값 실제 처리 코드

응답값의 content-type이 application/x-www-form-urlencoded 로 넘어오기 때문에 MultiValueMap<String, Object> 를 사용해서 data를 받아주었다. 받아 온 data 중 우리가 사용해야할 데이터는 id_token값이므로 id_token값을 가지고 사용자의 email 정보를 가져왔다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** 애플 sns 로그인 redirect 페이지 */
@RequestMapping(value = "/snsApplelogin")
@ResponseBody
public ModelAndView snsApplelogin(@RequestBody MultiValueMap<String, Object> data, HttpServletRequest request) {
//전달 받은 data에서 token 값 저장
String id_token = data.get("id_token").toString();
String email = "";
try {
//token값 decode처리
SignedJWT signedJWT = SignedJWT.parse(id_token);
//token값에서 payload 저장
ReadOnlyJWTClaimsSet payload = signedJWT.getJWTClaimsSet();
//payload에서 email 값 저장
email = payload.getClaim("email").toString();

} catch (Exception e) {
e.printStackTrace();
}

return this.redirect("/login/snsLoginWithPhone?snsType=A&phone=" + email);

}