[Spring Security] JWT + OAuth2.0 적용해보기 - (2)
https://mintgreentea.tistory.com/49
[Spring Security] JWT + OAuth2.0 적용해보기 - (1)
spring security 학습과 Spring boot 에 JWT, OAuth2.0 적용을 위해 간단한 프로젝트를 진행해 보았습니다. 이번 프로젝트로 filter 기반의 Spring Security 아키텍처를 이해하고, JWT 와 OAuth2.0 의 이해 및 적용을
mintgreentea.tistory.com
위에서 진행한 프로젝트를 기반으로 OAtuh2.0 로그인을 추가해보았다. OAuth2.0 를 통해 access token 과 refresh token 을 받으면, 인증이 필요한 request 나 access token 재발급 등은 이전에 구현된 코드들로 인해 처리 될 것이다.
OAuth2.0 flow
Resource Owner : 개인 정보 소유자(ex. 유저A)
Client : 제 3의 서비스로부터 인증을 받고자 하는 서버(ex. 직접 개발한 웹사이트)
Resource Server : 개인 정보를 저장하고 있는 서버(ex. google, naver, ...)
Authorization Server : 권한 관리하는 서버. Token 발급 및 재발급 함
1. 로그인 요청
2. 백엔드로 GET "localhost:8080/oauth2/authorize/google?redirect_uri=http://localhost:8080/oauth2/redirect' 요청. 이때 redirect_uri 는 OAuth2 인증이 성공하면 사용자 측에서 리다이렉션 되는 uri 이다.
3. provider 의 AuthorizationUrl 로 리다이렉트 (ex. google 의 로그인 창)
ex) https://accounts.google.com/o/oauth2/v2/auth/identifier?response_type=code&client_id=}&scope=profile%20email&state={}&service=lso&o2v=2&flowName=GeneralOAuthFlow
4. 리다이렉트 화면에서 provider 서비스에 로그인
사용자는 앱에대한 권한을 허용/거부할 수 있다.
거부하면 error 를 가진 상태로 콜백 url 로 리다이렉션한다. error 를 가진 콜백은 OAuth2AuthenticationFailureHandler 호출하고 query 에 에러메세지를 담아 redirect_uri 로 리다이렉트한다.
5. 로그인이 완료된 후, Authorize server 로부터 백엔드로 Authorization code 응답
권한 요청과 관련된 모든 상태 (OAuth2AuthorizationRequest) 는 AuthorizationRequestRepository 를 사용하여 저장된다. 디폴트 구현체로 HttpSession 에 저장하는 HttpSessionOAuth2AuthorizationRequestRepository 이 있고, stateless 한 구현을 위해 쿠키에 저장하는 CookieAuthorizationRequestRepository 를 구현했다.
6. 백엔드에서 Authorization code 를 이용하여 Authorization Server 에 access token 요청
7. access token 획득
8. access token을 이용하여 Resource Server 에 유저 데이터 요청
허용시 콜백 url (provider api 에 등록된 uri, OAuth2 redirectUri) 로 리다이렉션한다.
콜백 성공하고 Authorization code 가진 경우, access toekn 획득 후 유저 데이터 요청한다.
요청을 위해 server 는 CustomOAuth2UserService 를 호출한다. DefaultOAuth2UserService 클래스의 loadUser() 메서드를 사용하면 OAuth2UserRequest 를 사용해 사용자 정보를 불러올 수 있다.
9. 획득한 유저 데이터를 사용해 유저를 DB에 저장 or 유저 가져오기, JWT access token, refresh token 생성
loadUser 를 사용해 획득한 OAuth2User 를 사용해 나머지 작업을 수행한다.
마지막으로 OAuth2AuthenticationSuccessHandler 가 호출된다.
10. refresh token 은 쿠키에, access token 과 추가 정보는 redirect uri 의 쿼리 스트링에 담아 리다이렉트
OAuth2AuthenticationSuccessHandler 에서 refresh token 과 access token 생성한 후, redirect_uri 에 access token 과 memberId 를 쿼리에 담아 리다이렉트
OAuth2 flow 에는여러가지 uri 가 나오는데, 이것이 흐름을 이해하는 데 걸림돌이었다. uri 들은 다음과 같다.
- Authorization Uri : frontend 에서 backend 로 소셜 로그인 요청하는 uri. authorizationEndpoint().baseUri 에서 설정. default 는 /oauth2/authorization/{provider}
- OAuth2 redirectUri : Authorization 과정이 끝나면 Authorization Code 와 함께 redirect 되는 uri. redirectionEndpoint().baseUri 에서 설정. default 는 /login/oauth2/code/{provider}
- redirect_uri : 인증 성공 후 redirect 할 uri. 처음 provider 에 get 요청 시 쿼리스트링에 입력
실제 구현한 코드는 Github 링크를 올려 놓을 예정이다.
참조
https://deeplify.dev/back-end/spring/oauth2-social-login#%EC%A0%84%EC%B2%B4-%EC%8B%9C%ED%80%80%EC%8A%A4-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8
http://yoonbumtae.com/?p=3000
https://europani.github.io/spring/2022/01/15/036-oauth2-jwt.html