Ssul's Blog
소셜로그인 구현 - apple 로그인 본문
#1. 애플 개발자계정 가입/로그인(https://developer.apple.com/)
#2. Identifiers > Apps IDs 만들기
+ 클릭
app ids 선택후 continue
app 선택하고 continue
[App id 등록하는 페이지 등장]
- App ID prefix 밑에 있는 코드 기록(Team ID로 사용)
- description 대충적고,
- bundle ID는 자신의 도메인 + 앱(서비스)이름으로 구성
예) 스쿨, school.co.kr > kr.co.school.school
- sign in with apple 체크
#2. Identifiers > Services IDs만들기
-오른쪽에 services IDs선택
-identifiers옆에 +선택
- description대충넣고
- identifier가 중요: 나중에 코딩시 이게 client_id에 들어감
- services id의 identifier가 client_id로 들어감
configure 클릭
-위에서 만든 App id선택하고
-website URL등록(도메인과 콜벡주소 입력)
*나는 백앤드 서버에서 로그인을 진행하므로
api.school.co.kr(예시임)과 https://api.school.co.kr/auth/providers/apple/callback(본인이 개발한 콜백주소)
#3. key생성
- 생성한 app id로 키생성
- key id와 key값 잘기억해서 개발시 사용
[환경변수 설정 참고]
APPLE_TEAM_ID=1번의 Team ID
APPLE_CLIENT_ID=2번 services id의 identifier
APPLE_KEY_ID=3번의 Key ID
APPLE_PRIVATE_KEY=3번의 키값
[코드]
- 클라이언트에서 애플로그인 버튼을 누른다
- 서버에서 request_apple_loging 호출됨(여기서 애플auth에 호출해서 로그인창 으로 이동후, 로그인 성공하면 callback주소로 호출)
def request_apple_login(request):
state = get_random_string(32, allowed_chars=string.ascii_letters + string.digits)
query = urlencode(
{
"client_id": APPLE_CLIENT_ID,
"redirect_uri": REDIRECT_URI,
"response_type": "code",
'response_mode': 'form_post',
"scope": "name email",
"access_type": "offline",
"state": state,
}
)
# 1. https://appleid.apple.com/auth/authorize 으로 로그인 요청 > 로그인 성공하면, callback으로
response = django_redirect(f"{APPLE_OAUTH_URL}?{query}")
cb = re.search("cb=(.+)", request.get_full_path())
cb = APP_URL + (cb and cb[1])
response.set_cookie("cb", cb, httponly=True)
response.set_cookie("state", state, httponly=True)
return response
- 애플아이디와 비번이 성공적으로 통과하면, 토큰 받아오기 시작
- code를 POST.get으로 가져와야 한다(form_post로 넘기기 때문에) 이걸로 이틀 고생함 ㅜㅜ
# 2. 로그인에 성공했으니, /apple/callback로 여기왔음
def authorize_with_apple(request):
# cb=/auth/signup-sso
cb = request.COOKIES.get("cb")
if not cb or cb == "None":
cb = "/"
# 애플 client_secret만들기
client_id = APPLE_CLIENT_ID
team_id = APPLE_TEAM_ID
key_id = APPLE_KEY_ID
key = APPLE_PRIVATE_KEY.replace('\\n', '\n')
headers = {
'kid': key_id,
'alg': 'ES256',
}
claims = {
'iss': team_id,
'iat': time.time(),
'exp': time.time() + 86400 * 180,
'aud': 'https://appleid.apple.com',
'sub': client_id,
}
client_secret = jwt.encode(claims, key, algorithm='ES256', headers=headers)
# 3. 토큰 호출해서 가져오기 APPLE_TOKEN_URL=https://appleid.apple.com/auth/token
token_res = requests.post(
APPLE_TOKEN_URL,
{
#중요 google은 query로 넘기는데, 애플은 form_post로 넘겼기 때문에 POST사용
"code": request.POST.get("code"),
"client_id": APPLE_CLIENT_ID,
"client_secret": client_secret,
"redirect_uri": REDIRECT_URI,
"grant_type": "authorization_code",
},
)
if not token_res.ok:
error_message = token_res.text # 응답 데이터를 문자열로 가져옴
return redirect(f"{APP_URL}/error?type=auth&status=423&next={cb}&error_message={error_message}")
token_body = token_res.json()
# 4. 사용자 정보 가져오기
id_token = token_body.get("id_token")
if not id_token:
return redirect(f"{APP_URL}/error?type=auth&status=424&next={cb}")
decoded_token = jwt.decode(id_token, options={"verify_signature": False})
service_id = decoded_token.get('sub')
# if not email or not service_id:
if not service_id:
return build_unauthorized_response("No sub in Apple ID token")
# Everything is ok, create or update the user in your database, set the cookies and return the response
response = build_authorized_response(cb)
response.set_cookie("provider", "apple", httponly=True, max_age=60 * 60 * 1)
response.set_cookie("service_id", service_id, httponly=True, max_age=60 * 60 * 1)
return response
'dev > 기능구현' 카테고리의 다른 글
[Django] username대신, email 사용하기, jwt로그인 2 (1) | 2023.12.19 |
---|---|
[Django] username대신, email 사용하기, jwt로그인 1 (0) | 2023.12.19 |
restframework-simplejwt 사용하기 (0) | 2023.04.19 |
React Native IOS배포하기 (0) | 2023.02.28 |
React Native 구글 소셜로그인 구현 (1) | 2023.02.12 |