[기본 개념] Oauth 2.0의 완전 기초에 대해 알아보자

찐찐·2022년 6월 9일
1

요즘 토이 프로젝트에 소셜 로그인을 넣고 있는데, 문득 OAuth가 뭔지 대략적으로만 알면서 사용한다는 생각이 들어 이참에 정리해보고자 만들었다!

OAuth 2.0

요약

third-party application이 사용자를 대신해서 다른 곳에서 사용 중인 resource에 접근할 수 있도록 하는 프레임워크이다.

  • 2012년에 OAuth 1.0을 대체했다.
  • 동의된 권한과 제한된 액션(client app이 사용자를 대신해서 리소스를 사용할 수 있는) 것만 제공한다.
    • 동의 없이는 절대 자격 증명을 공유하지 않는다.
  • Web이 OAuth 2의 메인 플랫폼이긴 하지만 다른 client type에서도 사용할 수 있다.
    - browser-based applications, server-side web applications, native/mobile apps, connected devices, etc.

원칙

  1. authorization protocol이지 authentication protocol이 아니다.
    • 액세스 권한을 부여하기 위한 수단으로 설계 됐다. (Ex. 사용자의 데이터)

    Authentication Vs. Authorization

    • Authentication(인증): 사용자가 누구인지 검증하는 과정
      - Ex) 공항 검색대에서 신분증 보여주기
    • Authorization(인가): 사용자가 어디에 접근할 수 있는지 검증하는 과정
      - Ex) 비행기에 타기 위해 비행기 티켓 보여주기
    • 리소스는 두 가지 모두에 의해 보호된다.
  2. Access Token을 사용한다.
    • access token: end-user를 대신해 리소스에 접근할 수 있는 권한을 대표하는 조각.
  3. Access Token의 특정한 형식을 정의하지 않는다.
    • JWT가 자주 사용된다.
    • 토큰 issuer가 토큰 자체에 데이터를 넣을 수 있게 해준다.
    • 보안상의 이유로 token은 만료 기간이 있는 것이 좋다.

역할

OAuth 2.0 시스템에 필수적인 요소들을 정의한다.
1. Resource Owner: 보호받는 리소스를 소유하고 있고, 접근 권한을 위임할 수 있는 user나 시스템
2. Client: 보호받는 리소스에 접근해야 하는 시스템. 접근하기 위해서는 적절한 access token을 갖고 있어야 한다.
3. Authroization Server: client에게 access token request를 받고, resousce owner가 동의하고 인가(authenticaiton)에 성공하면 토큰을 발행해준다.

  • 두 개의 endpoint를 갖는다.
    1. Authroization endpoint: authenticaiton과 사용자의 동의를 다룬다.
    2. Token endpoint: machine to machie intreaction과 관계된 endpoint
  1. Resource Server: 사용자의 리소스를 보호하고 client로부터 접근 요청을 받는다. 유요한 access token을 받으면 적절한 리소스를 client에게 return 한다.

scopes

scope는 OAuth 2.0의 주요한 개념이다. 사용자의 계정에 앱의 접근을 제한하는 OAuth 2.0의 메커니즘이다.

  • 하나 또는 여러 개의 scope를 사용해 요청을 보낼 수 있고, 동의 화면에서 사용자에게 보여준 후 부여된 scope로 제한된 Access Token을 발급한다.
  • 서버 구조에 따라 다르기 때문에 scope의 특정한 값을 지정해 놓지는 않았다.

Access Token과 Authorization Code

OAuth 2의 Authroization Server는 Resource Owner가 인증해도 바로 access token을 주지 않을 수도 있다. 대신 보안을 위해, Authorization Code를 사용한다. (access token과 교환할 수 있는)

+) 추가로 access token과 refresh token이 함께 발급 될 수도 있는데, Refresh Token은 유효기간이 길고 Access Token이 만료된 후 새 토큰으로 교환할 수 있도록 도와주는 토큰이다. (따라서 client가 적절히 보관하고 있어야 한다.)

동작 방법

OAuth 사용 전

client가 Authorization Server로부터 인증 정보(client id, client secret)을 얻어야 한다. 이를 통해 access token 요청 시, authenticate가 가능하다.

OAuth 사용 시

접근 요청이 client의 주도로 사용된다.

  1. Client가 Authorization server에 인증하고, 식별을 위해 client ID와 secret을 제출한다.
    • 이때 token 혹은 code를 받을 scope와 endpoint URI(Redirect URI)도 함께 제출한다.
  2. Authorization server는 Cleint를 authenticate하고, 요청된 scope가 허용된 것인지 검증한다.
  3. Resource Owner는 접근을 승인하기 위해 Authroization server와 상호작용한다.
  4. Authroizaiton server는 Client에게 code나 token을 리다이렉트해준다. (grant type에 따라 다름. 다음 파트에서 설명)
  5. client는 access token을 가지고 resource server에 리소스 접근을 요청한다.

  • 카카오 디벨로퍼 공식 문서에 나와있는 설명 사진

Grant Type

  1. Authroization Code grant: Authorization server가 Access Token과 교환할 수 있는 1회용 code를 발급해준다.
    • 전통적인 웹 앱에서 가장 좋은 방법이다. 서버 측에서 발생하는 부작용에서 안전할 수 있기 때문이다.
    • SPA나 mobile/native app에서 사용된다.
    • 이떄는 Client Secret을 안전하게 보관할 수 없으므로 ID만 사용해서 code를 받는다.
  2. Implicit Grant: Access Token이 바로 Client에게 반환되는 가장 간단한 방법이다.
    - Redirect URI의 파라미터나 response로 token이 전달된다.
    - 토큰 누출의 가능성이 있어 이젠 추천하지 않는 방법이다.
    etc.. 여러가지 방법이 더 있으나 주로 Code grant를 활용하는 것 같아 더 알아보지 않았다.

Nest로 OAuth 2.0 카카오 로그인 사용해보기

0. 사전 환경 설정

  1. kakao developers내 애플리케이션 등록하고 key 확인하기
    • 내 애플리케이션 > 앱 설정 > 요약 정보에서 확인 가능
    • REST API를 사용하니 해당하는 key를 확인하면 된다.
  2. 내 애플리케이션 > 제품 설정 > 카카오 로그인에서 카카오 로그인 활성화
  3. 내 애플리케이션 > 제품 설정 > 카카오 로그인에서 redirect URI 등록
    • 해당 URL로 엔드 포인트를 만들어서 코드를 작성한다.

1. 인가 코드 받기

인가 코드는 카카오 로그인에 사용할 access_token을 발급받기 위해 필요한 코드다.

  1. 해당 URL을 통해 request
// GET
https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code
  • REST API KEY: 사전 환경 설정 1번에서 확인한 key
  • REDIRECT_URL: 사전 환경 설정 3번에서 등록한 URI
  1. Redirect URL의 parameter code={code}로 인가 코드가 전달된다.
// constroller
@Get('/kakao/callback')
kakaoLogin(@Query('code') code: string) {
  return this.signupService.kakaoLogin(code);
}
  • Nest에서는 @Query를 통해 받아올 수 있다.

2. 인가 코드를 통해 access_token 받기

여기부터는 service kakaoLogin 내부에서 진행

access_token 은 사용자 정보에 접근하기 위해 필요한 토큰이다.

  1. 해당 URL을 통해 request
//POST
const kakao_api_url = `https://kauth.kakao.com/oauth/token
	?grant_type=authorization_code
	&client_id=${this.config.get('KAKAO_CLIENT_ID')}
	&redirect_url=${this.config.get('KAKAO_REDIRECT_URL')}
	&code=${code}`;
  • grant type: authorization_code 고정
  • client id: 사전 환경 설정 1번에서 확인한 REST API KEY
  • redirect url: 사전 환경 설정 3번에서 등록한 URI
  • code: 위의 과정(1. 인가 코드 받기)을 통해 발급받은 인가 코드
  1. response로 토큰이 전달된다.
// request 보내기
const token_res = await firstValueFrom(this.axios.post(kakao_api_url));
const access_token: string = token_res.data.access_token;
  • response의 자세한 내용은 여기 참고

3. access_token 을 통해 사용자 정보 받아오기

  1. 해당 URL을 통해 request
// GET, POST
'https://kapi.kakao.com/v2/user/me'
// header
Authorization: `Bearer ${access_token}`
  1. response로 사용자 정보가 전달된다.
const user_ifo = await firstValueFrom(
  this.axios.get('https://kapi.kakao.com/v2/user/me', {
    headers: {
      Authorization: `Bearer ${access_token}`
    },
  }),
);
const user_id: string = user_ifo.data.id;
  • response의 자세한 내용은 여기 참고

참고

profile
백엔드 개발자 지망생

0개의 댓글