Search

#088 #OAuth2.0 #크레덴셜/코드

코드방식 OAuth 시나리오

브라우저에 토큰을 주면 토큰이 전달 될 때마다 토큰이 노출된다. 이 때 내 토큰은 브라우저에도 저장되어 있고, 전달 선(?)에도 토큰을 주고, 스프링도 토큰을 주고, 이 모든 토큰 유니버스에 모두가 내 토큰을 가지게 되어버리는 세상, 너무 위험하다! 그래서 코드 방식이 나온 것! 토큰은 Resource서버만 가지고 있게 된다.

고객이 서버에 로그인 페이지를 요청한다.

제일 먼저 로그인 페이지를 요청하고 HTML로 페이지를 반환 받는다. 거기서 카카오 인증 버튼도 함께 받는다.

새창은 카카오에게 카카오 로그인 페이지를 요청한다.

카카오는 로그인 페이지 요청에서 페이지를 응답해주고, 카카오 내부DB를 조회해서 회원을 검증한다. 검증이 되면, 고객에게 임시코드를 발급해준다.

카카오가 발급해준 임시코드 형태

그럼 SSR 상황에서는 카카오가 임시코드를 제공한다. 토큰을 주는 것이 아니다. 해당 임시 코드에서 클라이언트는 redirection 상태코드와 함께, 재요청을 할 수 있는 URL을 제공 받는다.
// 실제 코드 형태 HTTP/1.1 302 Found Location: REDIRECT_URI?code=AUTHORIZATION_CODE&state=STATE
JavaScript
복사

SSR환경의 서버는 엑세스 토큰을 응답

클라이언트는 임시코드로 서버에 토큰을 요청하고, 서버는 해당 엑세트 토큰이 접근할 수 있는 범위를 나타내는 scope 와 함께 토큰을 리턴한다.
// 임시코드 요청후 서버로 부터 반환되는 JSON데이터의 형태 { "access_token": "ya29.a0AfH6SMC4...", "expires_in": 3600, "refresh_token": "1//0gZ5V_...", "scope": "https://www.googleapis.com/auth/userinfo.profile", "token_type": "Bearer", "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6..." }
JavaScript
복사
해당 예시의 scope는 https://www.googleapis.com/auth/userinfo.profile 로 응답이 되었는데, 이는 구글 사용자 프로필 정보에 접근할 수 있는 권한을 준다.
클라이언트는 발급받은 토큰으로 서버랑 통신할 수 있다.

크레덴셜 방식 OAuth 시나리오

핸드폰 앱은 SSR방식이 아니라 최초에 리소스서버에 그림을 요청할 필요가 없다. 때문에 앱에서 직접적으로 카카오에 API요청을 보낸다. 검증이 되면 카카오는 바로 엑세스 토큰을 발급해주고, 앱은 리소스서버에 요청할 때 카카오로 받은 엑세스토큰을 같이 전송한다

클라이언트가 카카오에 엑세스 토큰을 요청

클라이언트 (Resource Owner)가 카카오 (인증 서버 : Authoriztion Server)에게 엑세스 토큰을 요청한다. 이때 클라이언트 요청 헤더에는 ID와 Secret정보를 같이 전송한다.
// 클라이언트 요청 예시 POST /token Host: authorization-server.com Authorization: Basic BASE64_ENCODED(client_id:client_secret) Content-Type: application/x-www-form-urlencoded grant_type=client_credentials
JavaScript
복사

카카오가 클라이언트를 검증하고 엑세스 토큰을 발급한다.

인증 서버인 카카오는 클라이언트 ID와 시크릿을 검증하고, 유효한 경우에 엑세스 토큰을 발급한다.
// 응답 데이터 형태 예시 { "access_token": "2YotnFZFEjr1zCsicMWpAA", "token_type": "Bearer", "expires_in": 3600, "scope": "read write" }
JavaScript
복사

클라이언트는 받은 토큰으로 리소스서버에 요청한다.

클라이언트는 엑세스 토큰을 사용하여 리소스서버에 요청을 한다.
// 요청 예시 GET /resource Host: resource-server.com Authorization: Bearer ACCESS_TOKEN
JavaScript
복사

리소스 서버는 토큰을 인증 서버에 통신하여 검증한다.

리소스 서버는 클라이언트로 받은 토큰을 인증서버에 전달하여서 검증한다.
// 예시 코드 POST /introspect Host: authorization-server.com Authorization: Basic BASE64_ENCODED(client_id:client_secret) Content-Type: application/x-www-form-urlencoded token=ACCESS_TOKEN|
JavaScript
복사

인증이 되면 인증서버는 JSON데이터를 응답한다.

// 데이터 예시 { "active": true, "scope": "read write", "client_id": "client-id", "username": "user", "exp": 1609459200, "iat": 1609455600, "nbf": 1609455600, "sub": "user", "aud": "resource-server", "iss": "https://authorization-server.com", "jti": "unique-identifier" }
JavaScript
복사

리소스 서버는 카카오 토큰이 인증이 되면 폐기 후 자체 토큰을 제작한다.

인증된 토큰을 폐기후 자체 토큰을 제작하여서 고객과 통신한다.

Spring Securiuty를 사용한 Java 코드 예시