본문 바로가기
JavaScript

JavaScript] 웹에서 Apple Login 구성하기

by Fastlane 2021. 10. 13.
728x90
반응형

Apple Developer Documentation : https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/configuring_your_webpage_for_sign_in_with_apple

 

참조 : https://sarunw.com/posts/sign-in-with-apple-4/

1. Apple Developer 에 로그인

https://developer.apple.com/account

 

2. Certificates, Identifiers & Profiles 메뉴에서 Service ID 설정한다.

자세한 내용은 아래 참조

https://help.apple.com/developer-account/#/dev1c0e25352

 

3. script 파일 추가, meta tag 추가, 로그인 버튼 추가

<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="[CLIENT_ID]">
        <meta name="appleid-signin-scope" content="[SCOPES]">
        <meta name="appleid-signin-redirect-uri" content="[REDIRECT_URI]">
        <meta name="appleid-signin-state" content="[STATE]">
        <meta name="appleid-signin-use-popup" content="true"> <!-- or false defaults to false -->
    </head>
    <body>
        <div id="appleid-signin" class="signin-button" data-color="black" data-border="true" data-type="sign in"></div>
    </body>
</html>

예를들면 아래와 같이 META TAG 세팅 가능하다.

<meta name="appleid-signin-client-id" content="kr.co.test.login">
<meta name="appleid-signin-scope" content="name email">
<meta name="appleid-signin-redirect-uri" content="https://test.co.kr/mobile/login.asp">
<meta name="appleid-signin-state" content="signin">
<meta name="appleid-signin-use-popup" content="true">

appleid-signin-client-id, appleid-signin-redirect-uri 값은 Service ID 설정값과 동일해야 한다.

그리고 appleid-signin-redirect-uri는 public access가 가능해야 한다.

외부 접속이 차단된 사이트에서는 애플 로그인 처리되지 않는다.

 

appleid-signin id 인 element를 클릭하면 로그인 팝업이 뜬다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

아래는, 최초 애플 로그인 시 추가로 보여지는 화면이다. 

차후 애플 로그인 시, 보여지지 않고 바로 로그인 된다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4. 응답값을 처리한다.

4.1 최초 애플 로그인 시

애플로그인 팝업에서 로그인을 하면 Apple로 정보를 보내고, Apple은 redirectURI로 인증 결과가 포함된 HTTP POST 를 request한다.

그 결과로 AppleIDSignInOnSuccess에서 수신된 data object 이다.

data.detail 데이터를 살펴보자.

code : 5분동안 유효한 single-use authentication code

id_token: 사용자 식별정보가 포함된 JSON web token

state : init function에서 전달된 상태

user : scope property에서 요청된 데이터가 포함된 JSON string

{ "name": { "firstName": string, "lastName": string }, "email": string }

사용자별로 최초 인증시에만 user object를 반환한다. 차후 인증시에는 user object가 포함되지 않는다.

로그인 시, 사용자가 email을 Hide 한 경우, example@prevaterelay.appleid.com 형식의 이메일 주소가 전달된다.

 

4.2 차후 애플 로그인 시

user json은 더 이상 전달되지 않는다.

 

user object를 테스트하기 위해서는, 해당 사이트에서의 Apple ID 사용을 정지처리 해야한다.

https://appleid.apple.com/ 접속 -> 로그인 했던 애플 계정으로 로그인 -> https://appleid.apple.com/account/manage 화면의 Security > SIGN IN WITH APPLE > Manage apps & websites 클릭 -> 앱 선택 -> Stop using Apple ID 처리

 

다시 로그인 하면, 최초 로그인으로 동작하며 user json 확인이 가능하다.

 

 

data.detail.authorization.id_token은 jwt 형태이다.

JWT의 payload 부분만 Base64 Decode해서 사용자 데이터를 확인한다.

	//Listen for authorization success
	document.addEventListener('AppleIDSignInOnSuccess', (data) => {

			//handle successful response
			console.log(typeof data.detail.authorization);
			console.log(data.detail.authorization);
			console.log(typeof data.detail.authorization.id_token);
			var token = data.detail.authorization.id_token;
			//var base64Payload = token.split('.')[1];
			var result = JSON.parse(base64_url_decode(token.split(".")[1]));

			//result json 값으로 로그인 처리 

	});
	//Listen for authorization failures
	document.addEventListener('AppleIDSignInOnFailure', (error) => {
		console.log(error);
		 //handle error.
	});
	function b64DecodeUnicode(str) {
	    return decodeURIComponent(
			atob(str).replace(/(.)/g, function (m, p) {
				var code = p.charCodeAt(0).toString(16).toUpperCase();
				if (code.length < 2) {
					code = "0" + code;
				}
				return "%" + code;
			})
	    );
	}

	
	function base64_url_decode(str) {
		var output = str.replace(/-/g, "+").replace(/_/g, "/");
		switch (output.length % 4) {
		case 0:
			break;
		case 2:
			output += "==";
			break;
		case 3:
			output += "=";
			break;
		default:
			throw "Illegal base64url string!";
		}

		try {
			return b64DecodeUnicode(output);
		} catch (err) {
			return atob(output);
		}
	}
728x90
반응형

댓글