들어가며
이번 ‘요즘카페’ 팀 프로젝트를 진행하면서 먼저 로그인 파트를 진행하게 되었다. 우리는 프로젝트로 로컬 로그인 외에 OAuth 로그인을 진행하게 되었다. 지금까지 프로젝트를 진행하면서 로그인 기능을 진행해보지 않았기 때문에 진행해보게 되었다.
OAuth 흐름
1. Get /auth/{provider} 요청
사용자가 프론트엔드 로그인을 클릭시 서버로 Redirect를 한다.
이후 요청을 받은 서버는 Provider로 authURi를 생성하여 Redirect한다.
이후 Provider는 클라이언트로 Authorization code를 받는다.
💡 클라이언트에서 바로 Provider로 요청하지 않는 이유 ClientId, clientSecret 등 공개되지 않아야 하는 정보를 서버에서만 처리를 한다면 응집도 높게 이곳에서만 처리할 수 있고 관리가 쉽다는 장점 때문에 이런 방식을 택하였다.
2. Post /auth/{provider}
클라이언트는 서버로 인증코드와 함께 post요청을 보낸다.
서버에서는 Token 반환 url로 요청을 보내고 토큰을 반환 받는다.
반환된 토큰을 ‘요즘카페’ 만의 jwt를 생성한 후 클라이언트로 제공한다.
RefreshToken은 쿠키와 함께 제공하며, AccessToken은 body 값으로 제공된다.
💡 Cookie의 path 문제 처음 우리는 쿠키의 경로를 아무 설정해주지 않았다. 배포를 하고 보니 특정 메소드 외에는 쿠키가 탑재되지 않는 문제를 발견하였다. 아무 설정해주지 않았을 경우 쿠키 생성 경로가 path라는 것을 인지하고 cookie.setPath("/"); 요즘카페 내에서 모두 사용할 수 있도록 설정하였다.
3. Get /auth
클라이언트에서 작동하다가 ArgumentResolver와 같은 리졸버에서 유효기간 만료로 401 같은 예외가 발생할 경우, refreshtoken을 가지고 accesstoken을 갱신해야한다.
refreshToken을 검증 후 새로운 accesstoken을 제공한다.
4. 로그아웃
현재 쿠키에 존재하는 refreshToken을 제거하며 accesstoken을 제거한다..
js로는 제거할 수 없기에 서버에서 처리해 주는 것이다.
구현 코드
최대한 객체지향적으로 추상화 수준을 높이면서 개발을 하고자 하였다.
요청이 들어오면 OAuth타입에 맞게 Provider를 설정한다.
public enum OAuthProvider {
GOOGLE,
KAKAO;
private OAuthClient oAuthClient;
...
}
이후 OAuthClient에서 타입별 client에게 요청을한다.
OAuthClient 같은 경우에는 GoogleOauthToken 과 KakaoOauthToken으로 분리하였다.
이렇게 분리한 이유는 공통의 기능이지만 바인딩 되어야할 값들이 properties에서 달랐기 때문에 진행하였다.
@Component
public class GoogleOAuthClient extends OAuthClient {
@Value("${spring.auth.google.tokenUri}")
private String googleTokenUri;
@Value("${spring.auth.google.clientId}")
private String clientId;
@Value("${spring.auth.google.clientSecret}")
private String clientSecret;
@Value("${spring.auth.google.redirectUri}")
private String redirectUri;
@Value("${spring.auth.google.authUri}")
private String googleAuthUri;
@Value("${spring.auth.google.scope}")
private String scope;
...
}
Token 도메인 같은 경우에는 GoogleToken 과 KakaoToken으로 분리하였다.
public abstract class OAuthToken {
protected OAuthToken(@JsonProperty("id_token") String idToken, String subject, String name, String image) {
this.idToken = idToken;
this.subject = subject;
this.name = name;
this.image = image;
}
...
}
public class GoogleToken extends OAuthToken {
...
}
public class KakaoToken extends OAuthToken {
...
}
만약 우리가 github와 같은 새로운 OAuth가 추가된다면 enum 타입에 github를 추가하고, token과 oAuthClient만 생성해주면 바로 사용 가능하다.
최소한의 변화로 추가 시킬 수 있도록 하였다.
'코코코딩공부 > Spring' 카테고리의 다른 글
restAssured를 이용한 restDocs 와 OAS (1) | 2023.08.10 |
---|---|
orElse 에서 생긴 문제 해결 (0) | 2023.07.30 |
Repository 사용기 (0) | 2023.06.07 |
도메인은 id 값을 가져도 될까 ? (0) | 2023.05.28 |
[Spring] Argument Resolver 내부 구경 하기 (0) | 2023.04.30 |