개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

공부 › 보안 › 인증

OAuth 로그인 흐름

"카카오로 로그인"을 누르면 오가는 것들

소셜 로그인은 우리 서비스가 사용자의 비밀번호를 받지 않고도, 사용자의 동의 아래 그 사람의 정보에 접근할 권한을 얻는 절차입니다. 브라우저를 거쳐 오가는 것과 서버끼리 직접 주고받는 것이 나뉘어 있습니다.

문서·표준 대조 · OAuth 2.0 표준(RFC 6749)

이 실습에 나오는 개념

OAuth 2.0
사용자가 비밀번호를 알려 주지 않고도 제3의 애플리케이션이 자신의 자원에 제한적으로 접근하도록 허락할 수 있게 하는 인가 프레임워크다. 사용자가 인가 서버(구글, 카카오 등)에서 로그인하고 동의하면, 애플리케이션은 그 결과로 액세스 토큰을 받아 자원에 접근한다. 소셜 로그인이 이 흐름을 이용한다.
인증과 인가
인증(Authentication)은 사용자가 누구인지 확인하는 것이고, 인가(Authorization)는 확인된 사용자가 특정 자원이나 기능을 사용할 권한이 있는지 판단하는 것이다. 인증이 먼저 이뤄지고 그 결과를 바탕으로 인가를 판단한다. HTTP 상태 코드로는 인증 실패가 401, 인가 실패가 403에 해당한다.
액세스 토큰과 리프레시 토큰
액세스 토큰은 API를 호출할 때 제시하는 토큰으로, 탈취되었을 때의 피해를 줄이기 위해 유효 기간을 짧게 둔다. 리프레시 토큰은 액세스 토큰이 만료되었을 때 새 액세스 토큰을 발급받는 데 쓰는 토큰으로, 유효 기간이 길고 더 안전하게 보관한다. 서버는 리프레시 토큰을 폐기해 재발급을 막을 수 있다.
CSRF(사이트 간 요청 위조)
사용자가 로그인된 상태임을 이용해, 공격자가 만든 페이지에서 사용자의 브라우저가 의도하지 않은 요청을 대상 사이트로 보내게 하는 공격이다. 브라우저가 쿠키를 자동으로 붙여 보내기 때문에 서버는 정상 요청으로 판단한다. 서버가 발급한 예측 불가능한 토큰을 요청에 포함하게 하거나 쿠키의 SameSite 속성으로 막는다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. 사용자가 우리 서비스(shop.example)에서 "카카오로 로그인" 버튼을 누릅니다.
  2. 우리 서비스가 브라우저를 카카오의 인가 주소로 보냅니다. 누가 요청하는지(client_id), 끝나면 돌아올 주소(redirect_uri), 원하는 정보의 범위(scope), 그리고 이 요청을 식별할 임의의 값(state)을 함께 붙입니다. state는 세션에 기억해 둡니다.
  3. 사용자가 카카오의 화면에서 로그인하고 정보 제공에 동의합니다. 아이디와 비밀번호는 카카오에만 입력됩니다. 우리 서비스는 이것을 볼 수 없습니다.
  4. 카카오가 브라우저를 우리 서비스의 redirect_uri로 돌려보내며 인가 코드를 붙입니다. 이 코드는 수명이 매우 짧은 일회용 교환권입니다. 브라우저 주소창을 거치므로 노출될 수 있다고 가정하고 설계돼 있습니다.
  5. 우리 서버가 돌아온 state를 세션에 기억해 둔 값과 비교합니다. 같으므로 진행합니다.
  6. 우리 서버가 카카오의 토큰 주소로 직접 요청합니다. 인가 코드와 함께, 우리 서버만 아는 client_secret을 보냅니다. 이 통신은 브라우저를 거치지 않습니다.
  7. 카카오가 코드와 비밀값을 확인하고 액세스 토큰을 발급합니다. 토큰은 브라우저에 노출되지 않고 우리 서버에만 전달됩니다. 인가 코드는 이 순간 폐기됩니다.
  8. 우리 서버가 액세스 토큰으로 카카오의 사용자 정보 API를 호출합니다. 토큰에 허용된 범위(scope)의 정보만 받을 수 있습니다.
  9. 사용자 정보를 받았습니다. 우리 서비스는 카카오 회원 번호로 우리 회원을 찾거나 새로 가입시킵니다.
  10. 마지막으로 우리 서비스 자체의 로그인 처리를 합니다. 이후의 요청은 카카오와 무관하게 우리 서비스의 세션이나 토큰으로 인증합니다.

실행 결과

코드

# application.yml (스프링 시큐리티 OAuth2 클라이언트)
spring.security.oauth2.client.registration.kakao:
  client-id: abc123                     # 공개돼도 되는 값
  client-secret: ********               # 서버만 아는 값
  authorization-grant-type: authorization_code
  redirect-uri: https://shop.example/login/oauth2/code/kakao
  scope: profile_nickname, account_email

// 아래 과정은 스프링 시큐리티가 대신 처리한다

이 모형의 전제

OAuth 2.0의 인가 코드 방식(Authorization Code Grant)을 표준 문서(RFC 6749)의 흐름대로 옮겼습니다. 카카오는 예시일 뿐이며 구글, 네이버 등 다른 제공자도 흐름이 같습니다. 코드와 토큰 값은 설명을 위한 가짜 값입니다.

앞 실습: JWT의 구조와 검증 · 다음 실습: 세션 하이재킹과 세션 고정

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요