What I'm going to do is like this.
- post additional parameter when user submit on consent page.
- send posted additional parameter to redirect uri.
I've checked through AuthorizationRequestConverter
that OAuth2AuthorizationCodeRequestAuthenticationToken
has the parameter which user has uploaded.
But I don't know why OAuth2Authorization
doesn't save additional parameters on Database.
Cause of above I cant' reach to additional parameters and can't post data to redirect URI.
I've referred to this repository.
sjohnr/spring-authorization-server
Here's my auth server configuration
- AuthorizationServerConfig
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer<>();
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
authorizationServerConfigurer
.authorizationEndpoint(authorizationEndPoint ->
authorizationEndPoint
.consentPage(CUSTOM_CONSENT_PAGE_URI)
.authorizationRequestConverter(customAuthorizationRequestConverter())
.authorizationResponseHandler(authorizationResponseHandler())
)
.withObjectPostProcessor(new ObjectPostProcessor<OAuth2AuthorizationCodeRequestAuthenticationProvider>() {
@Override
public <O extends OAuth2AuthorizationCodeRequestAuthenticationProvider> O postProcess(O object) {
object.setAuthenticationValidatorResolver(createDefaultAuthenticationValidatorResolver());
return object;
}
});
http
.requestMatcher(endpointsMatcher)
.authorizeRequests(authorizeRequest ->
authorizeRequest.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
.apply(authorizationServerConfigurer);
return http.build();
}
private AuthenticationConverter customAuthorizationRequestConverter() {
final OAuth2AuthorizationCodeRequestAuthenticationConverter delegate = new OAuth2AuthorizationCodeRequestAuthenticationConverter();
return (request) -> {
OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication =
(OAuth2AuthorizationCodeRequestAuthenticationToken) delegate.convert(request);
return authorizationCodeRequestAuthentication;
};
}
// ... validator and authorizationResponseHandler are same as reference
- Authentication Provider
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
@RequiredArgsConstructor
@Component
@Slf4j
public class CustomAuthenticationProvider implements AuthenticationProvider {
private final UserMapper userMapper;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
User user = getUser(username);
validatePassword(username, user.getPassword(), password);
return new UsernamePasswordAuthenticationToken(username, password, user.getAuthorities());
}
private User getUser(String username) {
User user = userMapper.fetchUserByUsername(username);
if (user == null)
throw new BusinessException("oauth.user.0100", HttpStatus.NOT_FOUND);
return user;
}
private void validatePassword(String username, String userPassword, String reqPassword) {
if(StringUtils.equals(userPassword, userMapper.fetchEncryptPassword(reqPassword)))
return;
userMapper.updateFailedLoginCount(username);
throw new BusinessException("oauth.user.0100", HttpStatus.NOT_FOUND);
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(
UsernamePasswordAuthenticationToken.class);
}
}