Spring/Oauth2

Oauth2 Authorization Code Grant

hwanguu 2025. 1. 12. 20:50

개요

 

  • 1. 흐름 및 특징
    • 1) 사용자가 애플리케이션을 승인하면 인가서버는 Redirect URI 로 임시 코드 담아서 애플리케이션으로 다시 리다이렉션한다
    • 2) 애플리케이션은 해당 임시 코드를 인가서버로 전달하고 액세스 토큰으로 교환한다
    • 3) 애플리케이션이 액세스 토큰을 요청할 때 해당 요청을 클라이언트 암호로 인증할 수 있으므로 공격자가 인증 코드를 가로채서 스스로 사용할 위험이 줄어듬
    • 4) 액세스 토큰이 사용자 또는 브라우저에 표시되지 않고 애플리케이션에 다시 전달하는 가장 안전한 방법이므로 토큰이 다른 사람에게 누출될 위험이 줄어듬
  • 2. 권한부여코드 요청 시 매개변수
    • uri : /realms/'realm 명'/protocol/openid-connect/auth GET (keycloak 기준) 
    • response_type=code (필수)
    • client_id (필수)
    • redirect_uri (선택사항)
    • scope (선택사항)
    • state (선택사항)
  • 3. 액세스토큰 교환 요청 시 매개변수
    • grant_type=authorization_code (필수)
    • code (필수)
    • redirect_uri (필수 : 2. 에서 redirect_uri 을 보낸경우경우)
    • client_id (필수)
    • client_secret (필수)

 

흐름

 

 

실습

기본세팅 : https://hwanguu.tistory.com/71

 

Oauth2 Keycloak Docker compose, 기본세팅

version: '3.9'services: postgres: image: postgres:latest container_name: postgres restart: always environment: POSTGRES_USER: keycloak POSTGRES_PASSWORD: keycloak POSTGRES_DB: keycloak ports: - "5432:5432" keycloak: image: quay.io/keycloak/keycloak:19.0.1

hwanguu.tistory.com

 

url : localhost:8080/realms/oauth2/protocol/openid-connect/auth?response_type=code&client_id=oauth2-client-app&scope=profile email&redirect_uri=http://localhost:8081

 

1. 인증 서버 로그인

 

2. 로그인 성공시 return 값 확인

http://localhost:8081/?session_state=785dbead-0011-4939-9219-806e49651453&code=9d77339d-60f7-4630-828e-65838ca30293.785dbead-0011-4939-9219-806e49651453.a86f1300-5de6-4970-b889-a72430531df5

1번에서 파라미터로 보냈던 redirect_url 로 code가 담겨져서 온다.

 

3. code를 이용하여 token 요청

* 주의사항 *

    •   2번에서 받았던 code 2번에서 보냈던 redirect_url은  그대로 넣어서 요청한다.
    •   code를 발급후 token 발급할 때 expiredTime이 짧기 때문에 바로 요청을 해야한다.
    •   그리고 code는 재사용 할 수 없다. 1번만 사용가능

 

4. 결과 확인

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqOXYyeTNJN0RzTy02aFhqanFGUi1YSURWd2RvWUwyemRfVjN3c05EREFZIn0.eyJleHAiOjE3MzY2ODI0NzUsImlhdCI6MTczNjY4MjE3NSwiYXV0aF90aW1lIjoxNzM2NjgyMDc3LCJqdGkiOiJkOTI1MDNhZC0xNjMzLTRkMGItOThhZC0wNjhmY2M2ZmRiMGEiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL29hdXRoMiIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJiN2JmNzk5OC01Yzk4LTQ4NmItOTdiYi1iODMwMzc0MGRkYjciLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJvYXV0aDItY2xpZW50LWFwcCIsInNlc3Npb25fc3RhdGUiOiI3ODVkYmVhZC0wMDExLTQ5MzktOTIxOS04MDZlNDk2NTE0NTMiLCJhY3IiOiIwIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJkZWZhdWx0LXJvbGVzLW9hdXRoMiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiZW1haWwgcHJvZmlsZSIsInNpZCI6Ijc4NWRiZWFkLTAwMTEtNDkzOS05MjE5LTgwNmU0OTY1MTQ1MyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6ImNob2kgc2Vod2FuIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidXNlciIsImdpdmVuX25hbWUiOiJjaG9pIiwiZmFtaWx5X25hbWUiOiJzZWh3YW4iLCJlbWFpbCI6InVzZXJAbmF2ZXIuY29tIn0.LRmQZEM82DIWPRKvdWLZNPyj7Je_AYlEEmkPJF4M9RADzWh7hd8lMoQg-HRl6o1QI6oUPXRFOEpXTgIeqxCKQ1ExVKshbFZ0a3Fqh5kMkbZwsqnFzlJJqJdkV7-_yI2gGBlMgJ4LaMt5mr5umQf20itHdFGpgSRqrJ54pNcVDmQhpfSi_GF7p-_Wq_tZ5z0816DPq-uLc3A6xS0nrqTU6VmoQQd9MXHGgz_-3FzHcNlcr3AIABO5Yrh3jETtHFX1vG5Qai8AokEOQGj3zd8wj9TZhEK95T1uiGVdPXMi2GuHiCGJUHPa9wqQOnfm582QjmPyJcF5neBatZxMx2p65Q",
    "expires_in": 300,
    "refresh_expires_in": 1800,
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4NWNmMTZkNS04OWY1LTQxY2EtOWQ4ZS1hMjZiODFiMGVmNjgifQ.eyJleHAiOjE3MzY2ODM5NzUsImlhdCI6MTczNjY4MjE3NSwianRpIjoiMjJiMjMwODUtNDcxMC00NGQxLTliYmYtNjNmZGIwYWQ2NzEzIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9vYXV0aDIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL29hdXRoMiIsInN1YiI6ImI3YmY3OTk4LTVjOTgtNDg2Yi05N2JiLWI4MzAzNzQwZGRiNyIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJvYXV0aDItY2xpZW50LWFwcCIsInNlc3Npb25fc3RhdGUiOiI3ODVkYmVhZC0wMDExLTQ5MzktOTIxOS04MDZlNDk2NTE0NTMiLCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiI3ODVkYmVhZC0wMDExLTQ5MzktOTIxOS04MDZlNDk2NTE0NTMifQ.8hbCJ4SAyiXadsnru8RU6zPzDR8ZYkNEz_PT5rf1Q1w",
    "token_type": "Bearer",
    "not-before-policy": 0,
    "session_state": "785dbead-0011-4939-9219-806e49651453",
    "scope": "email profile"
}

 

위와같이 access_token, refresh_token이 응답으로 온다.

 

 

만일 2번에서 token 전송시 expiredTime 이 초과 되었거나, code를 2번사용한경우 아래와 같은 에러가 발생한다.

 

References 및 사진 출처

정수원 스프링 시큐리티 OAuth2

'Spring > Oauth2' 카테고리의 다른 글

Oauth2 Password Grant  (0) 2025.01.12
Oauth2 Implicit Grant  (0) 2025.01.12
Oauth2 Keycloak Docker compose, 기본세팅  (0) 2025.01.12
Oauth2 매개 변수 용어  (0) 2025.01.12
Oauth2 Grant Type 권한부여 유형  (0) 2025.01.12