1. 개요
때로는 OAuth2 API가 표준과 약간 다를 수 있으며,이 경우 표준 OAuth2 요청에 대한 사용자 정의를 수행해야합니다.
Spring Security 5.1은 OAuth2 인증 및 토큰 요청 사용자 정의를 지원합니다.
이 사용방법(예제)에서는 요청 매개 변수 및 응답 처리를 사용자 지정하는 방법을 살펴 봅니다.
2. 사용자 지정 승인 요청
먼저 OAuth2 인증 요청을 사용자 정의합니다. 표준 매개 변수를 수정하고 필요에 따라 인증 요청에 추가 매개 변수를 추가 할 수 있습니다.
이를 위해서는 자체 OAuth2AuthorizationRequestResolver 를 구현해야합니다 .
public class CustomAuthorizationRequestResolver
implements OAuth2AuthorizationRequestResolver {
private OAuth2AuthorizationRequestResolver defaultResolver;
public CustomAuthorizationRequestResolver(
ClientRegistrationRepository repo, String authorizationRequestBaseUri) {
defaultResolver = new DefaultOAuth2AuthorizationRequestResolver(repo, authorizationRequestBaseUri);
}
// ...
}
기본 기능을 제공하기 위해 DefaultOAuth2AuthorizationRequestResolver 를 사용했습니다 .
또한 resolve () 메서드를 재정 의하여 사용자 지정 논리를 추가합니다.
public class CustomAuthorizationRequestResolver
implements OAuth2AuthorizationRequestResolver {
//...
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
OAuth2AuthorizationRequest req = defaultResolver.resolve(request);
if(req != null) {
req = customizeAuthorizationRequest(req);
}
return req;
}
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId) {
OAuth2AuthorizationRequest req = defaultResolver.resolve(request, clientRegistrationId);
if(req != null) {
req = customizeAuthorizationRequest(req);
}
return req;
}
private OAuth2AuthorizationRequest customizeAuthorizationRequest(
OAuth2AuthorizationRequest req) {
// ...
}
}
다음 섹션에서 설명 하겠지만 나중에 customizeAuthorizationRequest () 메서드 를 사용하여 사용자 지정을 추가 할 것입니다.
사용자 정의 OAuth2AuthorizationRequestResolver를 구현 한 후 Security 구성에 추가해야합니다.
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2Login()
.authorizationEndpoint()
.authorizationRequestResolver(
new CustomAuthorizationRequestResolver(
clientRegistrationRepository(), "/oauth2/authorize-client"))
//...
}
}
여기에서는 oauth2Login (). authorizationEndpoint (). authorizationRequestResolver () 를 사용하여 사용자 정의 OAuth2AuthorizationRequestResolver 를 삽입 했습니다.
3. 인증 요청 표준 매개 변수 사용자 정의
이제 실제 사용자 정의에 대해 설명하겠습니다. 원하는만큼 OAuth2AuthorizationRequest 를 수정할 수 있습니다 .
우선, 각 인증 요청에 대한 표준 매개 변수를 수정할 수 있습니다.
예를 들어 다음과 같이 자체 "상태" 매개 변수를 생성 할 수 있습니다 .
private OAuth2AuthorizationRequest customizeAuthorizationRequest(
OAuth2AuthorizationRequest req) {
return OAuth2AuthorizationRequest
.from(req).state("xyz").build();
}
4. 승인 요청 추가 매개 변수
OAuth2AuthorizationRequest 의 additionalParameters () 메소드를 사용하고 맵 을 전달 하여 OAuth2AuthorizationRequest 에 추가 매개 변수를 추가 할 수도 있습니다 .
private OAuth2AuthorizationRequest customizeAuthorizationRequest(
OAuth2AuthorizationRequest req) {
Map<String,Object> extraParams = new HashMap<String,Object>();
extraParams.putAll(req.getAdditionalParameters());
extraParams.put("test", "extra");
return OAuth2AuthorizationRequest
.from(req)
.additionalParameters(extraParams)
.build();
}
또한 새 추가 매개 변수를 추가 하기 전에 이전 추가 매개 변수를 포함했는지 확인해야 합니다.
Okta Authorization Server와 함께 사용되는 인증 요청을 사용자 지정하여보다 실용적인 예를 살펴 보겠습니다.
4.1. 맞춤 Okta 승인 요청
Okta 에는 사용자에게 더 많은 기능을 제공하기 위해 인증 요청에 대한 추가 선택적 매개 변수가 있습니다. 예를 들어 ID 공급자를 나타내는 idp 입니다.
ID 공급자는 기본적으로 Okta이지만 idp 매개 변수를 사용하여 사용자 지정할 수 있습니다 .
private OAuth2AuthorizationRequest customizeOktaReq(OAuth2AuthorizationRequest req) {
Map<String,Object> extraParams = new HashMap<String,Object>();
extraParams.putAll(req.getAdditionalParameters());
extraParams.put("idp", "https://idprovider.com");
return OAuth2AuthorizationRequest
.from(req)
.additionalParameters(extraParams)
.build();
}
5. 사용자 지정 토큰 요청
이제 OAuth2 토큰 요청을 사용자 지정하는 방법을 살펴 보겠습니다.
OAuth2AccessTokenResponseClient 를 사용자 지정하여 토큰 요청을 사용자 지정할 수 있습니다 .
OAuth2AccessTokenResponseClient 의 기본 구현 은 DefaultAuthorizationCodeTokenResponseClient 입니다.
사용자 정의 RequestEntityConverter 를 제공하여 토큰 요청 자체를 사용자 정의 할 수 있으며 DefaultAuthorizationCodeTokenResponseClient RestOperations 를 사용자 정의하여 토큰 응답 처리를 사용자 정의 할 수도 있습니다 .
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.tokenEndpoint()
.accessTokenResponseClient(accessTokenResponseClient())
//...
}
@Bean
public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient(){
DefaultAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new DefaultAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.setRequestEntityConverter(new CustomRequestEntityConverter());
OAuth2AccessTokenResponseHttpMessageConverter tokenResponseHttpMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
tokenResponseHttpMessageConverter.setTokenResponseConverter(new CustomTokenResponseConverter());
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(), tokenResponseHttpMessageConverter));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
accessTokenResponseClient.setRestOperations(restTemplate);
return accessTokenResponseClient;
}
}
tokenEndpoint (). accessTokenResponseClient ()를 사용하여 자체 OAuth2AccessTokenResponseClient 를 삽입 할 수 있습니다 .
토큰 요청 매개 변수를 사용자 정의하기 위해 CustomRequestEntityConverter를 구현 합니다. 마찬가지로 토큰 응답 처리를 사용자 지정하기 위해 CustomTokenResponseConverter를 구현 합니다.
다음 섹션에서는 CustomRequestEntityConverter 와 CustomTokenResponseConverter 를 모두 설명 합니다.
6. 토큰 요청 추가 매개 변수
이제 사용자 지정 변환기 를 구축하여 토큰 요청에 추가 매개 변수를 추가하는 방법을 살펴 보겠습니다 .
public class CustomRequestEntityConverter implements
Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>> {
private OAuth2AuthorizationCodeGrantRequestEntityConverter defaultConverter;
public CustomRequestEntityConverter() {
defaultConverter = new OAuth2AuthorizationCodeGrantRequestEntityConverter();
}
@Override
public RequestEntity<?> convert(OAuth2AuthorizationCodeGrantRequest req) {
RequestEntity<?> entity = defaultConverter.convert(req);
MultiValueMap<String, String> params = (MultiValueMap<String,String>) entity.getBody();
params.add("test2", "extra2");
return new RequestEntity<>(params, entity.getHeaders(),
entity.getMethod(), entity.getUrl());
}
}
우리의 컨버터는 변환 OAuth2AuthorizationCodeGrantRequest를 A를 RequestEntity.
기본 변환기 OAuth2AuthorizationCodeGrantRequestEntityConverter 를 사용하여 기본 기능을 제공하고 RequestEntity 본문에 추가 매개 변수를 추가했습니다 .
7. 사용자 지정 토큰 응답 처리
이제 토큰 응답 처리를 사용자 정의합니다.
기본 토큰 응답 변환기 OAuth2AccessTokenResponseHttpMessageConverter 를 시작점 으로 사용할 수 있습니다 .
CustomTokenResponseConverter 를 구현 하여 "scope" 매개 변수를 다르게 처리합니다 .
public class CustomTokenResponseConverter implements
Converter<Map<String, String>, OAuth2AccessTokenResponse> {
private static final Set<String> TOKEN_RESPONSE_PARAMETER_NAMES = Stream.of(
OAuth2ParameterNames.ACCESS_TOKEN,
OAuth2ParameterNames.TOKEN_TYPE,
OAuth2ParameterNames.EXPIRES_IN,
OAuth2ParameterNames.REFRESH_TOKEN,
OAuth2ParameterNames.SCOPE).collect(Collectors.toSet());
@Override
public OAuth2AccessTokenResponse convert(Map<String, String> tokenResponseParameters) {
String accessToken = tokenResponseParameters.get(OAuth2ParameterNames.ACCESS_TOKEN);
Set<String> scopes = Collections.emptySet();
if (tokenResponseParameters.containsKey(OAuth2ParameterNames.SCOPE)) {
String scope = tokenResponseParameters.get(OAuth2ParameterNames.SCOPE);
scopes = Arrays.stream(StringUtils.delimitedListToStringArray(scope, ","))
.collect(Collectors.toSet());
}
//...
return OAuth2AccessTokenResponse.withToken(accessToken)
.tokenType(accessTokenType)
.expiresIn(expiresIn)
.scopes(scopes)
.refreshToken(refreshToken)
.additionalParameters(additionalParameters)
.build();
}
}
토큰 응답 변환기는 Map 을 OAuth2AccessTokenResponse 로 변환 합니다.
이 예에서는 공백으로 구분 된 문자열 대신 쉼표로 구분 된 "scope" 매개 변수를 구문 분석했습니다 .
LinkedIn을 인증 서버로 사용하여 토큰 응답을 사용자 지정하는 또 다른 실제 예를 살펴 보겠습니다.
7.1. LinkedIn 토큰 응답 처리
마지막으로 LinkedIn 토큰 응답 을 처리하는 방법을 살펴 보겠습니다 . 여기에는 access_token 및 expires_in 만 포함 되지만 token_type 도 필요 합니다.
자체 토큰 응답 변환기를 구현하고 token_type을 수동으로 설정할 수 있습니다.
public class LinkedinTokenResponseConverter
implements Converter<Map<String, String>, OAuth2AccessTokenResponse> {
@Override
public OAuth2AccessTokenResponse convert(Map<String, String> tokenResponseParameters) {
String accessToken = tokenResponseParameters.get(OAuth2ParameterNames.ACCESS_TOKEN);
long expiresIn = Long.valueOf(tokenResponseParameters.get(OAuth2ParameterNames.EXPIRES_IN));
OAuth2AccessToken.TokenType accessTokenType = OAuth2AccessToken.TokenType.BEARER;
return OAuth2AccessTokenResponse.withToken(accessToken)
.tokenType(accessTokenType)
.expiresIn(expiresIn)
.build();
}
}
8. 결론
이 기사에서는 요청 매개 변수를 추가하거나 수정하여 OAuth2 인증 및 토큰 요청을 사용자 정의하는 방법을 배웠습니다.
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/spring-security-custom-oauth-requests
'Java' 카테고리의 다른 글
Spring Security를 사용하여 Amazon Cognito로 인증 (0) | 2021.04.11 |
---|---|
Spring Security 5 – OAuth2 로그인 (0) | 2021.04.10 |
Spring LDAP 개요 (0) | 2021.04.10 |
SpringData LDAP 사용방법(예제) (0) | 2021.04.10 |
JDBC를 사용한 Spring 세션 (0) | 2021.04.10 |