OAuth2 구성요소
Authorization Server ( 권한 서버 )
- Client를 등록하고, 권한을 관리해주는 서버
- 인증과정 (Authorized Grant Types) , 토큰 방식을 정의
- Access Token, Refresh Token 을 발급/재발급
Resource Server
- OAuth2 서비스를 제공하고 자원을 관리하는 서버
- 들어오는 OAuth2 토큰 ( Access Token ) 을 통해 자원 ( URL 경로 및 Resource ID ) 요청을 필터링
Client
- API 서비스 ( Resoruce Server가 제공 )를 이용하는 어플리케이션 또는 서비스
Access Token
- Authorization Server로 부터 발급 받은 인증 토큰
- Resource Server에 전달하여 서비스를 제공받을 수 있도록 함
- JWT ( JSON Web Tokens ) 로 이용가능
Resource Owner
- Resoruce Server의 계정을 가지고 있는 사용자
- 소유한 Role에 따라 자원 접근 권한이 다름
OAuth2 플로우
Access Token 발급
- User ( Resource Owner ) - Regular Web App ( Client ) - Auth0 Tenant ( Authorization Server )
API 서비스 요청 ( with Access Token )
- User ( Resource Owner ) - Regular Web App ( Client ) - Your API ( Resource Server )
Authorization Server 구성
- config/AuthorizationServerConfig.java
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
승인된 client 설정 / 권한 승인 방식 ( Password Grant ) 설정
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("cello") // client 이름
.secret("{noop}secret") // client 시크릿
.authorizedGrantTypes("refresh_token", "password", "client_credentials") // 권한 승인 방식 설정
.scopes("webclient");
}
토큰 인증 방식 설정
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer, jwtAccessTokenConverter));
endpoints.tokenStore(tokenStore)
.accessTokenConverter(jwtAccessTokenConverter)
.tokenEnhancer(tokenEnhancerChain)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
Resource Server 구성
- config/ResourceServerConfig.java
- 마이크로 서비스에서는 자원을 가지는 각 서비스마다 설정
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
각 자원에 대한 필터링 설정
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.GET, "/test/rs") // /test/rs 에 대한 GET 요청은
.hasRole("ADMIN_001") // "ADMIN_001" 가진 사용자만 가능하다.
.anyRequest() // 모든 요청은
.authenticated(); // 모든 요청은 인증이 필요하다.
}
- /test/rs 에 대한 GET 요청은 "ADMIN_001" 가진 사용자만 가능하다.
- 모든 요청은 인증이 필요하다.
WebSecurity 구성
- config/AuthorizationServerConfig.java
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
사용자 ( Resource Owner ) 및 Role 구성
- 일반사용자 - "USER_001" role 만 소유
- 관리자 - "USER_001" 과 "ADMIN_001" role 소유
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
auth.inMemoryAuthentication()
.withUser("yskim")
.password("{noop}1234")
.roles("USER_001")
.and()
.withUser("cello")
.password("{noop}1234")
.roles("USER_001", "ADMIN_001");
}
JWT 토큰 구성
@Configuration
public class JWTTokenStoreConfig {
토큰 서비스의 구현체 설정
- 스프링 시큐리티에 있는 기본 토큰 서비스의 구현체 사용
@Bean
@Primary
public DefaultTokenServices tokenServices () {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
토큰 변환 방법 정의
- 중요한 점은 토큰을 서명하는 서명 키 설정한다는 점
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("jwt-secret-key-123"); // 서명키 설정, TO-DO: 비대칭키로 전환 必
return converter;
}
토큰의 확장
@Bean
public TokenEnhancer jwtTokenEnhancer() {
return new JWTTokenEnhancer();
}
- config/JWTTokenEnhancer.java
public class JWTTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
Map<String, Object> additionalInfo = new HashMap<>();
String celloUid = "cello-uid-123-" + oAuth2Authentication.getName();
additionalInfo.put("cello-uid", celloUid); // JWT 토큰에 추가 될 내용.
((DefaultOAuth2AccessToken)oAuth2AccessToken).setAdditionalInformation(additionalInfo);
return oAuth2AccessToken;
}
}
참고 사이트
'Spring' 카테고리의 다른 글
[ Spring Authorization Server ] Access Token ( JWT ) 확장하기 (0) | 2021.12.29 |
---|---|
OAuth2 Grant 타입 (0) | 2021.12.22 |
[ Intellij ] lombok이 적용되지 않을 때 (0) | 2021.10.26 |
[ Maven ] dependency 수동으로 설치하기 (0) | 2021.10.15 |
MappedInterceptor를 이용한 Interceptor 등록 (0) | 2021.10.06 |