ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OAuth와 Kakao, Google 로그인 API 곁들이기
    Protocol/OAuth 2024. 8. 7. 21:53

     

    들어가기 전에

    인증 서비스 프로젝트를 진행하던 중 우리가 자주 볼 수 있는 카카오 or 구글 로그인이 내부적으로 어떻게 동작되는지 알아보기 위해 구현한 내용을 작성한다.

     

    OAuth 의미

    OAuth(Open Authorization)은 액세스 위임을 위한 개방형 표준 인가 프로토콜이다.

    다시말해, 내가 가지고 있는 자원(resource)을 누군가 요청했을 때 A만 허락할지, A ~ F 까지 허락할지 정해주는 것이다.

     

    인증(Authentication)과 인가(Authorization)

    여기서 하나 더 알고 가야될 것 인증, 인가의 차이점이다.

    여러가지 해석이 있지만 이해하기 쉬운 해석으로 풀어보자면, 은행을 방문한다고 가정하자.

     

    은행원: 안녕하세요! 홍길동님. 무엇을 도와드릴까요?
    홍길동(나): 대출하러 왔습니다.

    은행원: 먼저, 본인 확인부터 할게요. 신분증 보여주세요.
    홍길동(나): (신분증 제시함)

    은행원: 본인 확인 되셨습니다. 얼마나 대출하시나요?
    홍길동(나): 5천만원이요.
    은행원: 대출 가능 여부 확인해보겠습니다.
    대출 가능 여부 확인중....

    은행원: 홍길동님은 대출이 1천만원 가능합니다.
    홍길동(나): 아니! 왜요?
    은행원: 신용 점수가 너무 낮으시네요 ^^

     

    위 대화흐름에서 신분증 확인이 인증이다. 먼저 대출을 하기전에 당신이 우리 고객이 맞는지 확인하는 것

    대출 가능 여부 확인 과정이 인가이다. 당신이 우리 고객인건 알겠는데 신용점수(대출조건)가 낮아서 1천만원 까지만 대출이 허가되는 것

     

    여기까지 알아보았으니 다시 구글 개발자 문서를 기반으로 시나리오를 구성해보자. (카카오 문서도 유사하다)

     

    시나리오

    구글 Cloud API 문서에서는 5개의 시나리오를 제공한다.

    • 웹 서버 애플리케이션
    • 설치된 애플리케이션
    • 클라이언트 측(자바스크립트) 애플리케이션
    • 입력이 제한된 기기의 애플리케이션
    • 서비스 계정

     

    여기서는 웹 서버 애플리케이션 시나리오로 설명한다. (나머지 시나리오도 중간 과정에 차이가 있을 뿐 큰 흐름은 똑같다)

     

    google oauth flow

     

    시나리오 흐름은 아래와 같다.

    • Google Cloud Platform Console 에서 승인 사용자 인증 정보를 만든다.
    • Console 에서 생성한 앱에 엑세스 범위를 식별한다. (실제 구현전에 앱에서 액세스 권한이 필요한 범위를 정하는 것)
    • 엑세스 토큰을 가져온다.
      • 승인(인가) 코드 발급받을 매개변수 설정
      • Google OAuth 2.0 서버로 Redirection
      • Google 에서 사용자에게 동의 요청 메시지 표시
      • OAuth 2.0 서버 응답 처리
      • 승인 코드를 갱신 토큰 및 액세스 토큰으로 교환
    • 사용하고 싶은 Google API 호출
      • 사용자 계정을 대신하여 토큰 사용
      • 쿼리 매개변수 또는 HTTP 헤더에 access_token 포함 (HTTP 헤더 사용 권장.)
    HTTP 헤더 사용 예.
    GET /drive/v2/files HTTP/1.1
    Host: www.googleapis.com
    Authorization: Bearer {access_token}

    쿼리 매개변수 사용 예.
    GET https://www.googleapis.com/drive/v2/files?access_token={access_token}

     

     

    Tip. 사용자 동의 요청 메시지 표시

     

    코드 흐름

    Spring Boot를 사용해 구현됨.

    Controller -> Service -> Redirect View

    • 고객이 google login 버튼을 누르면 /google-login 컨트롤러 매핑되어 goGoogleOAuth() 실행
    • AuthorizationCodeFlow 객체에 Builder 생성 및 승인 코드 매개변수 설정 후 객체 반환
    • newAuthorizationUrl() 승인 코드 발급 요청
    • Redirection View /google-login-callback 컨트롤러 매핑되어 googleLoginCallback(String) 실행
    • newTokenRequest(String) 엑세스 토큰 발급 요청
    • 발급된 액세스 토큰은 Base64로 인코딩된 JSON 객체인 JWT
    • Base64url 인코딩된 값을 디코딩하고 내부 JSON을 파싱해 사용자 정보 사용

    OAuth 2.0 액세스 토큰 가져오기

    OAuth 2.0 서버 흐름

     

    @RequestMapping("/google-login")
    public RedirectView goGoogleOAuth() {
        return googleService.goGoogleOAuth();
    }
    
    @RequestMapping("/google-login-callback")
    public RedirectView googleLoginCallback(@RequestParam("code") String code){
        return googleService.loginCallback(code);
    }

     

    구현 중 보게 된 오류

    Base64url로 인코딩된 값을 디코딩 하는데 발생한 오류와 google api endpoint 이슈를 만나게 되었다.

    1. java.lang.1IllegalArgumentException: Illegal base64 character 20

    2. java.lang.IllegalArgumentException: Illegal base64 character 2e

    3. Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: java.net.UnknownHostException: apitest.acme.com] with root cause

     

    오류 1번은 base64로 구성된 문자 중 (공백) ASCII 값이 발견되어 발생하는 오류이다.

    -> base64Url을 base64로 변환할 때 공백을 제거했다. String.replace(" ", "");

     

    오류 2번은 base64로 구성된 문자 중 .(닷) ASCII 값이 발견되어 발생하는 오류이다.

    -> 문자열을 .(닷)을 기준으로 분리해주었다. String.split("\\.");

     

    오류 3번은 api endpoint (apitest.acme.com) 주소를 알 수 없다는 오류이다.

    -> google api token endpoint를 구글 문서에서 확인해 변경했다. https://oauth2.googleapis.com/token

     

    추가 이슈.

    Base64Url은 내부 문자열 구성에 '-'(대시), '_'(언더바)를 포함하고 있는데 Base64 변환시 해당 기호를 해석하지 못한다.

    그래서 String.replace("-","+") 와 String.replace("_","/")로 먼저 교체하고 Base64로 변환 해야한다.

     

    Base64 인코딩에서는 문자열의 길이가 4의 배수가 되어야 하므로, 부족한 패딩을 채워줘야한다.

     

Designed by Tistory.