본문 바로가기

STUDY/Spring

Spring Boot | Spring Security OAuth2 (4) JWT TokenStore

이전까지는 짧은 문자열 토큰을 받았다면, 이제 JWT를 이용해 길고.. 정보가 담긴... 토큰을 받아보려 한다!

JWT토큰으로 발급받으면 더 이상 데이터베이스에 토큰을 저장하지 않아도 된다...?

 

0. 의존성 추가

jwt를 사용하기 위해서는 spring-securiti-jwt를 추가해야 함

// JWT
implementation group: 'org.springframework.security', name: 'spring-security-jwt', version: '1.1.1.RELEASE'

 

1. CustomUserDetailService만들기

그런데 그 전에..! User를 수정해준다 UserDetails를 상속받아 오버라이딩 해주기..

@Data
@ToString
public class User implements UserDetails {
    private String id;
    private String name;
    private String password;
    private String authorities;

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

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

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

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

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

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        ArrayList<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
        authList.add(new SimpleGrantedAuthority(authorities));
        return authList;
    }
}

 

그리고 이제 진짜로 CustomUserDetailService를 작성

@AllArgsConstructor
@Service
public class CustomUserDetailService implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    private final AccountStatusUserDetailsChecker detailsChecker = new AccountStatusUserDetailsChecker();

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.findByName(username);
        if(user == null)
            throw new UsernameNotFoundException("유저 정보 찾을 수 없음");
        return user;
    }
}

 

2. Ouath2AuthorizationConfig 수정

JWT를 사용하겠다는 설정을 해준다.

userDetailsService를 통해 기한이 만료된 access_token을 refresh_token을 이용해 갱신할 수 있게됨!

@AllArgsConstructor
@Configuration
@EnableAuthorizationServer    // OAuth2 인증 서버를 사용하겠다는 뜻
public class Oauth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    private AuthenticationManager authenticationManager;  // grant_type password를 사용하려면 필수
    private DataSource dataSource;
    private PasswordEncoder passwordEncoder;
    private CustomUserDetailService customUserDetailService;

    /* OAuth2 서버가 작동하기 위한 EndPoint에 대한 정보 설정 */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore())
                .authenticationManager(authenticationManager)
                .accessTokenConverter(jwtAccessTokenConverter())
                .userDetailsService(customUserDetailService);
    }

    /* token store로 JWTTokenStore를 사용하겠다 */
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /* JWT 디코딩 하기 위한 설정 */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setSigningKey("jwtKey");
        return jwtAccessTokenConverter;
    }

    /* 클라이언트 대한 정보를 설정하는 부분 */
    /* jdbc(DataBase)를 이용하는 방식 */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
    }

}

 

3. 테스트

우선 grant_type을 password로 정하고, 토큰을 발급받는다.

response값을 보면 알겠지만 access_token의 기한이 매우 짧다. (29초 남음)

 

이제 refresh_token을 이용해 access_token을 갱신(재발급)해보자

grant_type을 refresh_token으로 설정하고, refresh_token값을 보내면 access_token을 갱신할 수 있다.

(위의 캡쳐와 비교하면 달라져있음!)

📌 계속 refresh_token이 안온다...?

=> grant_type에 refresh_token이 있는지 확인하기! inMemory형식이면 (... , "refresh_token)이런식으로 추가하고,

JDBC를 이용하면 아래처럼 콤마(,)로 구분해 여러 개를 작성할 수 있다!

📌 access_token 유효시간 설정

 

+) 참고

 

OAuth 2.0 Refresh Token Example - Apps Developer Blog

In this tutorial, you will learn how to refresh OAuth 2.0 access token using the Refresh Token OAuth 2.0 Grant Type. To learn how to use other OAuth 2.0 grant types, please check out the following tutorials: Client Credentials Grant Type with Keycloak, OAu

www.appsdeveloperblog.com