How do disable CSRF for the specific origin - spring-boot

I needed to add auth in Swagger, but I have no idea how to pass the CSRF token to each request. If I disabled the CSRF token protection then it works fine, but its not a solution, so now I need to disable CSRF for this specific origin
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.exceptionHandling().authenticationEntryPoint(authEntryPoint)
.and()
.authorizeHttpRequests()
.antMatchers("/swagger-resources/**","/v2/api-docs","/swagger- ui/**","/auth/**","/user","/csrf")
.permitAll()
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authenticationProvider(authenticationProvider)
.addFilterBefore(malformedTokenHandler, LogoutFilter.class)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
I also have SwaggerConfig class like this:
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.securityContexts(Arrays.asList(securityContext()))
.securitySchemes(Arrays.asList(apiKey()))
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
private ApiKey apiKey() {
return new ApiKey("JWT", "Authorization", "header");
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope
= new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference("JWT", authorizationScopes));
}
private List<Parameter> operationParameters(CsrfTokenRepository csrfTokenRepository) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
CsrfToken csrfToken = csrfTokenRepository.loadToken(request);
return Arrays.asList(
new ParameterBuilder()
.name("X-CSRF-TOKEN")
.modelRef(new ModelRef("string"))
.parameterType("header")
.defaultValue(csrfToken.getToken())
.required(false)
.build());
}
}
I tried:
http.csrf().ignoringAntMatchers("/swagger-resources/**","/v2/api-docs","/swagger-ui/**")
But still it doesn't work.

Try:
http.csrf().requireCsrfProtectionMatcher(yourCsrfMatcher)
and you'll find the documention for the class RequestMatcher here:
public class YourCsrfMatcher implements RequestMatcher {
#override
public boolean matches(HttpServletRequest request){
// add your logic here and return false for the specific origin
return true;
}
}

Related

Cannot redirect to a URL was defiend before in spring boot project with Oauth2 Login google

Hi i am new member of stackoverflow, i had a problem with my springboot project.Im trying to redirect after login google is successful, but its always show "There was an unexpected error (type=Not Found, status=404).
This is my configuration:
#Configuration
#EnableWebSecurity
#Order(2)
#PropertySource("classpath:application.properties")
public class ConfigSecuriry extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/api/login/**",
"/login/oauth2/code/google",
"/login/google",
"/api/token/refresh",
"**/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**",
"/swagger-resources",
"/swagger-resources/configuration/ui",
"/swagger-resources/configuration/security"
).permitAll();
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.loginPage("/login/google")
.defaultSuccessUrl("/abc")
.successHandler(savedRequestAwareAuthenticationSuccessHandler())
.and()
.oauth2Client();
}
private SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler() {
SavedRequestAwareAuthenticationSuccessHandler successHandler
= new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setDefaultTargetUrl("/abc"); // The URL to redirect to after a successful login
successHandler.setAlwaysUseDefaultTargetUrl(true);
return successHandler;
}
#Bean
public static ClientRegistrationRepository clientRegistrationRepository() {
ClientRegistration registration = ClientRegistration.withRegistrationId("google")
.clientId("XXXXXXXX")
.clientSecret("XXXXXXX")
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
return new InMemoryClientRegistrationRepository(registration);
}
}
and this is my controller:
#RestController
public class LoginGoogle {
#GetMapping("/abc")
public String sucess(){
return "Succes login google";
}
private final OAuth2AuthorizedClientService authorizedClientService;
public LoginGoogle(OAuth2AuthorizedClientService authorizedClientService) {
this.authorizedClientService = authorizedClientService;
}
#GetMapping("/login/google")
public RedirectView googleLogin(HttpServletRequest request) throws Exception {
String redirectUri = UriComponentsBuilder.fromHttpUrl(getBaseUrl(request))
.path("/login/oauth2/code/google")
.toUriString();
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
new NetHttpTransport(),
new JacksonFactory(),
"XXXXXXXX",
"XXXXXXXX",
Arrays.asList("email", "profile"))
.setAccessType("offline")
.build();
String url = flow.newAuthorizationUrl()
.setRedirectUri(redirectUri)
.setAccessType("offline")
.setApprovalPrompt("force")
.build();
return new RedirectView(url);
}
private String getBaseUrl(HttpServletRequest request) {
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
}
}
i was try anything i found but it doesn't seem to work.I look forward to receiving your contributions,thank you for all your assistance

include ROLE_ADMIN by default in #RolesAllowed annotation

I created a role based application, I know that the admin has all the rights so instead of adding ROLE_ADMIN evry time, I am locking for a way to give the admin all the rights, so instead of writting #RolesAllowed({"ROLE_ADMIN","ROLE_MANAGER","ROLE_CLIENT"}), I want only to write #RolesAllowed({"ROLE_MANAGER","ROLE_CLIENT"}), beucause I have to many APIs, and including ROLE_ADMIN each time is not a good deal, here is my security config :
public SecurityConfig(InnerRbacProxy rbacProxy) {
this.rbacProxy = rbacProxy;
}
#Bean
JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri(jwtSetUri).build();
}
#Override
public void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.cors()
.and()
.cors().and()
.csrf().disable() //NOSONAR
.exceptionHandling()
.accessDeniedHandler(securityAccessDeniedHandler())
.authenticationEntryPoint(securityAuthEntryPoint());
if (!securityEnabled) {
http.authorizeRequests().anyRequest().permitAll();
} else {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests(authRequests -> {
// Permissions OPTIONS
authRequests.mvcMatchers(HttpMethod.OPTIONS).permitAll();
// Management endpoints
authRequests.mvcMatchers("/management/**", "/docs/**", "/webjars/**").permitAll();
// Business APIs
authRequests.anyRequest().authenticated();
});
http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
}
// #formatter:on
}
#Bean
PasswordEncoder setPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
var corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedHeaders(List.of("*"));
corsConfiguration.setAllowedMethods(List.of("*"));
corsConfiguration.setAllowedOriginPatterns(List.of("*"));
var source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return source;
}
#Bean
public AccessDeniedHandler securityAccessDeniedHandler() {
return new SecurityAccessDeniedHandler();
}
#Bean
public AuthenticationEntryPoint securityAuthEntryPoint() {
return new SecurityAuthEntryPoint();
}
JwtAuthenticationConverter jwtAuthenticationConverter() {
var customAuthoritiesConverter = new CustomAuthoritiesConverter();
var authenticationConverter = new JwtAuthenticationConverter();
authenticationConverter.setJwtGrantedAuthoritiesConverter(customAuthoritiesConverter);
authenticationConverter.setPrincipalClaimName("email");
return authenticationConverter;
}
static class CustomAuthoritiesConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
public CustomAuthoritiesConverter() {
}
#Override
public Collection<GrantedAuthority> convert(Jwt jwt) {
var roleDto = rbacProxy.getRolesByEmail("user2#test.ma");
var roles = roleDto.getRoles().stream().map(RoleDto::getCode).collect(Collectors.toList());
List<GrantedAuthority> updatedAuthorities = new ArrayList<>();
roles.forEach(role -> updatedAuthorities.add(new SimpleGrantedAuthority(role)));
return updatedAuthorities;
}
}
}

Angular 6 Http Interceptors, request headers not modified

I created an interceptor to add an authorization header to each request sent by the client, here is the code :
import { HttpInterceptor, HttpRequest, HttpHandler, HttpHeaderResponse, HttpSentEvent, HttpProgressEvent, HttpResponse, HttpUserEvent, HttpEvent, HttpHeaders } from "#angular/common/http";
import { Observable } from "rxjs";
import { Injectable } from "#angular/core";
#Injectable()
export class AuthenticationInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log(localStorage.getItem('jwtToken'));
if(localStorage.getItem('jwtToken')){
const request = req.clone({
setHeaders: {
Authorization: `bearer ${localStorage.getItem('jwtToken')}`
}
});
console.log(request.headers.get("Authorization"));
return next.handle(request);
}
return next.handle(req);
}
}
When a request is sent the function intercept is called and the authorization header is correclty set with the token value in the variable "request" as you can see there :
token console screenshot
But the authorization header doesn't appear in the request sent by my browser : network request headers and the backend cannot resolve the token.
Do you know why ?
Here is my spring config:
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public final static String AUTHORIZATION_HEADER = "Authorization";
#Autowired
UserService userService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(getProvider());
}
#Bean
public JwtTokenFilter jwtAuthenticationFilter() {
return new JwtTokenFilter();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/auth/**")
.permitAll()
.anyRequest()
.authenticated();
}
#Bean
public AuthenticationProvider getProvider() {
AppAuthProvider provider = new AppAuthProvider();
provider.setUserDetailsService(userService);
return provider;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
CorsConfig.java
#Configuration
public class CorsConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:4200")
.allowedMethods("*")
.allowedHeaders("*");
}
};
}
}
Your problem resides into backend services. For security reasons by default only some headers are accepted, the others are ignored.
To fix your problem you need to setup custom accepted headers. Authorization header, even if is like a standard for JWT, is considered a custom header.
I can give you an example of my Spring Security configuration:
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
Note the line
config.addAllowedHeader("*");
That means that my REST services accept all possible headers sent by the client.
Obviously it's not a good configuration, you should limit allowed headers and other things to match your needs, as restricted as is possible.
Obviously if you don't use Spring Security you need to find the way to do the same thing with yout language/framework.
This is my SecurityConfig.java It's a bit different from yours.
Try this and let me know
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Autowired
private WLUserDetailsService userDetailsService;
#Value("${jwt.header}")
private String tokenHeader;
#Value("${jwt.route.authentication.path}")
private String authenticationPath;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoderBean());
}
#Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// we don't need CSRF because our token is invulnerable
.csrf().disable()
// TODO adjust CORS management
.cors().and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated();
// Custom JWT based security filter
JwtAuthorizationTokenFilter authenticationTokenFilter = new JwtAuthorizationTokenFilter(userDetailsService(), jwtTokenUtil, tokenHeader);
httpSecurity
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// // disable page caching
// httpSecurity
// .headers()
// .frameOptions().sameOrigin() // required to set for H2 else H2 Console will be blank.
// .cacheControl();
}
#Override
public void configure(WebSecurity web) {
// AuthenticationTokenFilter will ignore the below paths
web
.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath
)
// allow anonymous resource requests
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js"
);
}
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
// config.addExposedHeader("Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
// "Content-Type, Access-Control-Request-Method, Custom-Filter-Header");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

OAuth 2 with spring security and setting the State parameter in the redirect

I am using Spring boot with Spring security, with custom "Filter" Class calling to CIAM server with OAuth 2 authentication. I want to set explicitly or override the default setting so that I could set custom dynamic STATE parameter in the redirect URL that Spring Security prepares under the hood and sends the user to the CIAM server login page. This seamed trivial to me but it turned out to be far from that.
The goal is to add the custom STATE parameter of the OAuth2 redirect link so that after the authentication is finished and the CIAM server redirects me back to my page I take back the STATE parameter which is automatically included in the successful redirect link from the CIAM server.
The Security configuration
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true,
proxyTargetClass = true)
#EnableOAuth2Client
#Order(3)
public class OAuth2LoginWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
CiamOAuth2ClientFilter oAuth2CiamClientFilter;
#Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
return new InMemoryUserDetailsManager();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/**/*.css", "/**/*.png", "/**/*.gif", "/**/*.jpg", "/h2-console/**", "/css/**",
"/img/**", "/font-awesome/**", "/fonts/**", "/js/**", "/signout","/signout/**", "/health");
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/user/**").hasRole("USER")
.antMatchers("/backoffice/**").hasRole("ADMIN")
.antMatchers("/api/**").hasRole("API")
.antMatchers(/*"/", */"/login**", "/webjars/**", "/favicon.*", "/resources/**",
"/auth/**", "/signin/**","css/**","js/**", "/signup/**", "/signout/", "/health", "/awsTest/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login/callback"))
.and()
.addFilterBefore(oAuth2CiamClientFilter.ciamFilter(), BasicAuthenticationFilter.class)
.logout()
.logoutUrl("/signout")
.logoutSuccessUrl("/logout");
}
}
The custom filter class
#Configuration
public class CiamOAuth2ClientFilter {
#Autowired
AuthorizationCodeResourceDetails oauth2CiamResourceDetails;
#Autowired
CiamOAuth2ClientProperties oauth2CiamClientProperties;
#Autowired
OAuth2ClientContext oauth2ClientContext;
#Autowired
CiamPrincipalExtractor ciamPrincipalExtractor;
#Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
registration.addInitParameter("test", "trrrrrrr");
System.out.println("333333333333333333333333");
System.out.println(registration);
return registration;
}
public Filter ciamFilter() {
System.out.println("postaeget");
System.out.println(oauth2CiamClientProperties);
System.out.println(" _-------------------------------: " + oauth2CiamClientProperties.getResource().getUserInfoUri());
UserInfoTokenServices tokenService = new UserInfoTokenServices(oauth2CiamClientProperties.getResource().getUserInfoUri(), oauth2CiamResourceDetails.getClientId());
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(oauth2CiamResourceDetails, oauth2ClientContext);
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter("/login/callback");
tokenService.setRestTemplate(restTemplate);
tokenService.setPrincipalExtractor(ciamPrincipalExtractor);
filter.setRestTemplate(restTemplate);
filter.setTokenServices(tokenService);
return filter;
}
}
Application yml settings file connected with the issue
security:
oauth2:
client:
clientId: ...
clientSecret: ....
accessTokenUri: ...
userAuthorizationUri: ...
useCurrentUri: false
preEstablishedRedirectUri: https://localhost/login/callback
clientAuthenticationScheme: query
authenticationScheme: header
serverLogoutUrl: ..
postLogoutRedirectUri: https://localhost/signout
scope:
- openid
- profile
- email
- offline_access
state: TEST
resource:
userInfoUri: ...
preferTokenInfo: ...
In my case
I configure OAuth2ClientAuthenticationProcessingFilter somewhere in #Configuration:
private Filter ssoFilter() {
OAuth2ClientAuthenticationProcessingFilter facebookFilter = new OAuth2ClientAuthenticationProcessingFilter(API_LOGIN_FACEBOOK);
OAuth2RestTemplate facebookTemplate = new OAuth2RestTemplate(facebook(), oauth2ClientContext);
AuthorizationCodeAccessTokenProvider authorizationCodeAccessTokenProviderWithUrl = new AuthorizationCodeAccessTokenProvider();
authorizationCodeAccessTokenProviderWithUrl.setStateKeyGenerator(new StateKeyGeneratorWithRedirectUrl());
facebookTemplate.setAccessTokenProvider(authorizationCodeAccessTokenProviderWithUrl);
facebookFilter.setRestTemplate(facebookTemplate);
UserInfoTokenServices tokenServices = new CheckedUserInfoTokenServices(
facebookResource().getUserInfoUri(), facebook().getClientId(),
facebookPrincipalExtractor, blogPreAuthenticationChecks(), blogPostAuthenticationChecks());
tokenServices.setAuthoritiesExtractor(new FacebookAuthoritiesExtractor());
tokenServices.setRestTemplate(facebookTemplate);
facebookFilter.setTokenServices(tokenServices);
facebookFilter.setAuthenticationSuccessHandler(new OAuth2AuthenticationSuccessHandler());
return facebookFilter;
}
And you can access to current request in StateKeyGeneratorWithRedirectUrl with:
RequestContextHolder.getRequestAttributes()
so you can extract Referer header for example:
public class StateKeyGeneratorWithRedirectUrl extends DefaultStateKeyGenerator {
private RandomValueStringGenerator generator = new RandomValueStringGenerator();
#Override
public String generateKey(OAuth2ProtectedResourceDetails resource) {
HttpServletRequest currentHttpRequest = getCurrentHttpRequest();
if (currentHttpRequest!=null){
String referer = currentHttpRequest.getHeader("Referer");
if (!StringUtils.isEmpty(referer)){
return generator.generate()+","+referer;
}
}
return generator.generate();
}
private static HttpServletRequest getCurrentHttpRequest(){
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
return ((ServletRequestAttributes)requestAttributes).getRequest();
}
return null;
}
}
Next - read state from callback:
public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
public static final String DEFAULT = "/";
#Override
protected String determineTargetUrl(HttpServletRequest request,
HttpServletResponse response) {
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.query(request.getQueryString())
.build();
MultiValueMap<String, String> queryParams = uriComponents.getQueryParams();
String stateEncoded = queryParams.getFirst("state");
if (stateEncoded == null) {
return DEFAULT;
}
String stateDecoded = URLDecoder.decode(stateEncoded, StandardCharsets.UTF_8);
String[] split = stateDecoded.split(",");
String redirect;
if (split.length != 2){
return DEFAULT;
} else {
return split[1];
}
}
}

Spring security OAuth parsing the response into an object

I'm new to spring.
I have been following http://spring.io/guides/tutorials/spring-boot-oauth2/ using google oauth in place of facebook.
I am able to return the principle as described in the tutorial, which sends to the browser the json returned by the api call and can use this client side.
#RestController
public class UserControllers {
#RequestMapping("/user")
public Principal user(Principal principal) {
return principal;
}
}
But how would I use this data on the server side? Suppose I wanted just to return the email address on the /user route? Or maybe I want to further populate the Principal with information from a database?
Below is the code I use to set up the oauth authentication.
#EnableWebSecurity
#EnableOAuth2Client
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
OAuth2ClientContext oauth2ClientContext;
#Override
protected void configure(HttpSecurity http) throws Exception {
http .csrf().disable()
.logout().logoutSuccessUrl("/").permitAll() //logout logic handled by spring
.and()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**", "/webjars/**", "/user")
.permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))
.and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
}
#Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
protected Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<>();
filters.add(constructFilter("/login/google", google(), googleResource()));
filter.setFilters(filters);
return filter;
}
private Filter constructFilter(String endpoint, OAuth2ProtectedResourceDetails clientDetails, ResourceServerProperties resourceDetails) {
OAuth2ClientAuthenticationProcessingFilter filter = new CustomOauth2AuthFilter(endpoint);
OAuth2RestTemplate template = new OAuth2RestTemplate(clientDetails, oauth2ClientContext);
filter.setRestTemplate(template);
filter.setTokenServices(new UserInfoTokenServices(resourceDetails.getUserInfoUri(), clientDetails.getClientId()));
return filter;
}
/*
/Returns a new AuthorizationCodeResourceDetails object configured with the properties from the application.yml file
*/
#Bean
#ConfigurationProperties("google.client")
OAuth2ProtectedResourceDetails google() {
return new AuthorizationCodeResourceDetails();
}
/*
/Returns a new ResourceServerProperties object configured with the properties from the application.yml file
*/
#Bean
#ConfigurationProperties("google.resource")
ResourceServerProperties googleResource() {
return new ResourceServerProperties();
}
}
Thanks in advance,
Dan

Resources