java
package com.kongjs.smo.common.oauth2.server.config;
import com.kongjs.smo.common.oauth2.server.authorization.Oauth2AuthorizationErrorResponseHandler;
import com.kongjs.smo.common.oauth2.server.authorization.Oauth2AuthorizationResponseHandler;
import com.kongjs.smo.common.security.handler.RestAccessDeniedHandler;
import com.kongjs.smo.common.security.handler.RestAuthenticationEntryPoint;
import com.kongjs.smo.common.security.resolver.CommonBearerTokenResolver;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import static org.springframework.security.config.Customizer.withDefaults;
@Configuration(proxyBeanMethods = false)
public class Oauth2Config {
@Resource
private RestAccessDeniedHandler restAccessDeniedHandler;
@Resource
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Resource
private Oauth2AuthorizationResponseHandler oauth2AuthorizationResponseHandler;
@Resource
private Oauth2AuthorizationErrorResponseHandler oauth2AuthorizationErrorResponseHandler;
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) {
http
.oauth2AuthorizationServer((authorizationServer) -> {
http.securityMatcher(authorizationServer.getEndpointsMatcher());
authorizationServer.oidc(withDefaults())
.authorizationEndpoint(authorizationEndpoint -> {
authorizationEndpoint
.authorizationResponseHandler(oauth2AuthorizationResponseHandler)
.errorResponseHandler(oauth2AuthorizationErrorResponseHandler);
});
})
.oauth2ResourceServer(oauth2ResourceServer -> {
CommonBearerTokenResolver bearerTokenResolver = new CommonBearerTokenResolver();
bearerTokenResolver.setAllowCookieToken(true);
oauth2ResourceServer
.accessDeniedHandler(restAccessDeniedHandler)
.authenticationEntryPoint(restAuthenticationEntryPoint)
.bearerTokenResolver(bearerTokenResolver)
.jwt(withDefaults());
})
.authorizeHttpRequests((authorize) ->
authorize
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(Customizer.withDefaults());
return http.build();
}
}
java
package com.kongjs.smo.common.oauth2.server.config;
import com.kongjs.smo.system.auth.service.OidcUserInfoService;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
@Configuration(proxyBeanMethods = false)
public class TokenCustomizerConfig {
@Resource
private OidcUserInfoService oidcUserInfoService;
@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> tokenCustomizer() {
return (context) -> {
if (OidcParameterNames.ID_TOKEN.equals(context.getTokenType().getValue())) {
OidcUserInfo userInfo = oidcUserInfoService.loadUserByUsername(context.getPrincipal().getName());
context.getClaims().claims(claims -> claims.putAll(userInfo.getClaims()));
}
if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
context.getClaims().claims((claims) -> {
claims.put("claim-1", "value-1");
claims.put("claim-2", "value-2");
});
}
};
}
}
java
package com.kongjs.smo.common.oauth2.server.authorization;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationException;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Component
public class Oauth2AuthorizationErrorResponseHandler implements AuthenticationFailureHandler {
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
OAuth2AuthorizationCodeRequestAuthenticationException authorizationCodeRequestAuthenticationException = (OAuth2AuthorizationCodeRequestAuthenticationException) exception;
OAuth2Error error = authorizationCodeRequestAuthenticationException.getError();
OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication = authorizationCodeRequestAuthenticationException
.getAuthorizationCodeRequestAuthentication();
if (authorizationCodeRequestAuthentication == null
|| !StringUtils.hasText(authorizationCodeRequestAuthentication.getRedirectUri())) {
response.sendError(HttpStatus.BAD_REQUEST.value(), error.toString());
return;
}
UriComponentsBuilder uriBuilder = UriComponentsBuilder
.fromUriString(authorizationCodeRequestAuthentication.getRedirectUri())
.queryParam(OAuth2ParameterNames.ERROR, error.getErrorCode());
if (StringUtils.hasText(error.getDescription())) {
uriBuilder.queryParam(OAuth2ParameterNames.ERROR_DESCRIPTION,
UriUtils.encode(error.getDescription(), StandardCharsets.UTF_8));
}
if (StringUtils.hasText(error.getUri())) {
uriBuilder.queryParam(OAuth2ParameterNames.ERROR_URI,
UriUtils.encode(error.getUri(), StandardCharsets.UTF_8));
}
if (StringUtils.hasText(authorizationCodeRequestAuthentication.getState())) {
uriBuilder.queryParam(OAuth2ParameterNames.STATE,
UriUtils.encode(authorizationCodeRequestAuthentication.getState(), StandardCharsets.UTF_8));
}
// build(true) -> Components are explicitly encoded
String redirectUri = uriBuilder.build(true).toUriString();
this.redirectStrategy.sendRedirect(request, response, redirectUri);
}
}
java
package com.kongjs.smo.common.oauth2.server.authorization;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Component
public class Oauth2AuthorizationResponseHandler implements AuthenticationSuccessHandler {
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication = (OAuth2AuthorizationCodeRequestAuthenticationToken) authentication;
String redirectUriForResponse = authorizationCodeRequestAuthentication.getRedirectUri();
Assert.notNull(redirectUriForResponse, "redirectUri cannot be null");
OAuth2AuthorizationCode authorizationCode = authorizationCodeRequestAuthentication.getAuthorizationCode();
Assert.notNull(authorizationCode, "authorizationCode cannot be null");
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(redirectUriForResponse)
.queryParam(OAuth2ParameterNames.CODE, authorizationCode.getTokenValue());
if (StringUtils.hasText(authorizationCodeRequestAuthentication.getState())) {
uriBuilder.queryParam(OAuth2ParameterNames.STATE,
UriUtils.encode(authorizationCodeRequestAuthentication.getState(), StandardCharsets.UTF_8));
}
// build(true) -> Components are explicitly encoded
String redirectUri = uriBuilder.build(true).toUriString();
this.redirectStrategy.sendRedirect(request, response, redirectUri);
}
}