React에 Apple OAuth 적용 2

황세훈·2024년 7월 31일

cmc 프로젝트

목록 보기
3/10

Apple OAuth 2

Apple Oauth 1편

localhost 설정

sign with apple 사용 시 redirect URI로 localhost를 사용할 수 없다
따라서 ngrok을 사용한다

ngrok을 사용하여 로컬 서버를 공개적으로 접근할 수 있는 URL로 만들어 테스트할 수 있다.
로컬 개발 환경에서 HTTPS를 통해 접근할 수 있는 URL을 생성할 수 있음.

ngrok회원가입

이후 명령어대로 실행

ngrok http http://localhost:5173  // vite는 5173 port에 있음


해당주소로 접근할 수 있음

이후 redirectURI에 추가

그리고 RedirectURI 가 localhost, vercel에 따라 달라지기 때문에 이렇게 관리

const REDIRECT_URI = window.location.protocol + '//' + window.location.host + '/callback/apple';

localhost에서 정상 작동한다..!

OAuth 성공

OAuth 성공 시 주는 값

code

Apple 서버에서 제공하는 단기 사용 인증 코드
백엔드 서버에서 Apple 서버로 교환하여 사용자 액세스 토큰이나 ID 토큰을 받을 때 사용

id_token

jwt으로 인코딩된 사용자 정보
이 토큰을 디코딩하면 사용자 ID, 이메일, 인증 시간 등 여러 정보를 확인할 수 있음

redirect URI 에서 작업

redirect URI로 /callback/apple 로 설정해주었다.
하지만, 지정된 URI로 이동하지 않고 현재페이지에서 authroization 받았음

이유: usePopup:true , 이 경우 수동으로 리디렉션을 설정해야한다

따라서 팝업설정을 false로 변경

usePopup:false // 앱에서 활용될 때 팝업이 잘 되지 않을수도 있음

리디렉션 에러발생

무슨 이유인지 ngrok에서는 리디렉션을 제대로 해주어도 404에러가 발생하였다. (배포된 vercel에서는 리디렉션이 성공적으로 되었음.)

또한 vercel에서 리디렉션이 되어도 아무값도 받지 못한 상태였기 때문에 작업을 할 수 없는 상태였음.

해당문서 참고하여 진행

원인: responseMode:"form_post" 였기 때문

기본 모드가 from_post인데, 이것은 네이버나 카카오 로그인처럼 원래 페이지로 리다이렉션 되는 것이 아닌, 해당 redirect-uri 로 POST 요청이 날아갔던 것
실제로 log를 보면 post 요청을 보낸 것을 알 수 있음

responseMode: fragment 로 변경

apple 공식문서를 참고하여 코드 수정

export const appleLogin = async () => {
  const RESPONSE_TYPE = 'code id_token'; // 요청하는 응답 타입
  const RESPONSE_MODE = 'fragment';

  const AUTH_URL =
    `https://appleid.apple.com/auth/authorize?` +
    `client_id=${encodeURIComponent(APPLE_CLIENT_ID)}` +
    `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` +
    `&response_type=${encodeURIComponent(RESPONSE_TYPE)}` +
    `&response_mode=${encodeURIComponent(RESPONSE_MODE)}` +
    `&scope=${encodeURIComponent('')}` +
    `&state=${encodeURIComponent('previewInsure')}` +
    `&nonce=${encodeURIComponent('821')}`;

  // 브라우저에서 Apple 로그인 페이지로 리디렉션
  window.location.href = AUTH_URL;
};

잘 동작한다! ( 해결하는데 하루종일 걸렸......)

리디렉션경로에서 처리

import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';

function AppleLoginCallback() {
  const navigate = useNavigate(); // 이후 callback에서 나올 때 사용
  const [idToken, setIdToken] = useState(null);
  const [code, setCode] = useState(null);
  const [state, setState] = useState(null);

  useEffect(() => {
    const hash = window.location.hash.substring(1);
    const queryParams: any = new URLSearchParams(hash);
    setIdToken(queryParams.get('id_token'));
    setCode(queryParams.get('code'));
    setState(queryParams.get('state'));
  }, []);

  const handleSign = () => {
    const data = {
      id_token: idToken,
      code: code,
      state: state,
    };
    console.log(data);
  };

  useEffect(() => {
    if (state && idToken && code) {
      handleSign();
    }
  }, [state, idToken, code]);

  return (
    ... 
  );
}

export default AppleLoginCallback;

key 등록

서버에서 apple로 요청을 보낼 때 사용

키 파일 다운로드하기 (.p8)

참고

https://github.com/hmmhmmhm/how-to-using-sign-with-apple-js

https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/incorporating_sign_in_with_apple_into_other_platforms

profile
음.. 한줄로는 부족하다

0개의 댓글