OAuth2 Login with JWT - 4[Filter & UserPrincipal]

조건웅·2023년 10월 11일

OAuth2 Login

목록 보기
4/8
post-thumbnail

Filter

TokenAuthenticationFilter

우리가 로그인을 진행하기 전에 HttpServletRequest를 탐색해서 만약, AccessToken을 받았을 경우 SecurityContextHolder에 해당 인증 정보를 저장해야 한다.

해당 내용을 아래의 코드와 같이 정리하였다.

@Slf4j
@RequiredArgsConstructor
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    private final AuthTokenProvider tokenProvider;

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        log.info("gwj : TokenAuthenticationFilter.doFilterInternal");

        // HTTP 요청에서 Access Token을 가져옵니다.
        String tokenStr = HeaderUtil.getAccessToken(request);

        // Access Token을 이용하여 AuthToken 객체로 변환합니다.
        AuthToken token = tokenProvider.convertAuthToken(tokenStr);

        // AuthToken이 유효한지 확인하고, 유효하다면 인증을 가져온 후 SecurityContext에 설정합니다.
        if (token.validate()) {
            Authentication authentication = tokenProvider.getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        // 다음 필터로 체인을 전달합니다.
        filterChain.doFilter(request, response);
    }
}

UserPrincipal

우리는 0번째 포스팅에서 얘기했듯이, 인증 및 인가 성공시 인증 정보가 SecurityContext에 저장된다고 하였다. 과연 어떻게 저장할 지 아래와 같이 코딩하였다.

여기서 중요하게 봐야할 점은 "우리가 로그인할 떄 local로 로그인할 때와 oAuth2으로 로그인할 때를 어떻게 처리하냐" 이다.

단순히, 따로따로 처리하게 되면 쓸데없이 유지 보수 비용이 증가할 것이다. 그래서 어댑터 패턴을 사용해서 두 가지 경우에도 하나의 클래스로 처리할 수 있도록 하였다.

나중에 OAuth2UserService의 loadUser를 오버라이딩할 때, 해당 UserPrincipal을 기반으로 생성할 것이다.

@Getter
@Setter
@RequiredArgsConstructor
public class UserPrincipal implements OAuth2User, UserDetails, OidcUser {
    private final String userId;
    private final String password;
    private final ProviderType providerType;
    private final RoleType roleType;
    private final Collection<GrantedAuthority> authorities;
    private Map<String, Object> attributes;

    // OAuth2User
    @Override
    public Map<String, Object> getAttribute(String name) {
        return attributes;
    }

    @Override
    public String getName() {
        return userId;
    }

    // UserDetails
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getUsername() {
        return userId;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    // OidcUser

    @Override
    public Map<String, Object> getClaims() {
        return null;
    }

    @Override
    public OidcUserInfo getUserInfo() {
        return null;
    }

    @Override
    public OidcIdToken getIdToken() {
        return null;
    }

    public static UserPrincipal create(SiteUser user) {
        return new UserPrincipal(
                user.getUserId(),
                user.getPassword(),
                user.getProviderType(),
                RoleType.USER,
                Collections.singletonList(new SimpleGrantedAuthority(RoleType.USER.getCode()))
        );
    }

    public static UserPrincipal create(SiteUser user, Map<String, Object> attributes) {
        UserPrincipal userPrincipal = create(user);
        userPrincipal.setAttributes(attributes);

        return userPrincipal;
    }

}

전체 코드 Github

https://github.com/gwj0421/OAuth2Login/tree/main

profile
내게 남은 소중한 자식은 누군지 아나? 쑨양이다!

0개의 댓글