Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrate Spring Security OAuth2 and Spring Social

I'm working with a Spring Boot + Spring Security OAuth2 application that I believe was inspired by examples from Dave Syer. The application is configured to be an OAuth2 authorization server, with a single public client using the Resource Owner Password Credentials flow. A successful token is configured to be a JWT.

The public Angular client sends a POST request to /oauth/token with a basic auth header containing the client id and secret (this was the easiest way to get the client to authenticate, even though the secret is not private). The body of the request contains username, password, and grant type of "password".

In addition to being an authentication server, the application is a RESTful resource server for users, teams, and organizations.

I'm trying to add an additional SSO authentication flow using Spring Social. I've got Spring Social configured to authenticate through external providers via /auth/[provider]; however, following requests no longer have the SecurityContext correctly set. Possibly, Spring Security OAuth server or client is overriding the SecurityContext?

If I can get the SecurityContext correctly set after the Spring Social flow, I've got a new TokenGranter that allows a new grant type of "social" that would check the SecurityContextHolder for the pre authenticated user.

I'm interested in both a solution to my specific problem with the SecurityContext (I believe it's an issue with Spring OAuth + Social integration), or a different approach for authenticating with external providers and getting a valid JWT from our own auth server.

Thanks!

like image 486
Andrew Ferk Avatar asked Aug 31 '15 14:08

Andrew Ferk


People also ask

How do you integrate OAuth with spring boot?

After “BUILD SUCCESSFUL”, you can find the JAR file under the build/libs directory. The application is started on the Tomcat port 8080. Now hit the POST method URL via POSTMAN to get the OAUTH2 token. Authorization − Basic Auth with your Client Id and Client secret.

Is Spring Security OAuth2 deprecated?

End of Life NoticeThe Spring Security OAuth project has reached end of life and is no longer actively maintained by VMware, Inc. This project has been replaced by the OAuth2 support provided by Spring Security and Spring Authorization Server.

Does Spring Security use OAuth2?

Spring Security handles the Authentication and Spring Security OAuth2 handles the Authorization. To configure and enable the OAuth 2.0 Authorization Server we have to use @EnableAuthorizationServer annotation.

How OAuth2 works with SSO?

OAuth (Open Authorization) is an open standard for token-based authentication and authorization which is used to provide single sign-on (SSO). OAuth allows an end user's account information to be used by third-party services, such as Facebook, without exposing the user's password.


1 Answers

I had a similar problem on a JHipster-generated web application. Finally I decided to go with the SocialAuthenticationFilter option from Spring Social (via the SpringSocialConfigurer). After a successful social login, the server automatically generates and returns the "own" access token via redirection to the client app.

Here's my try:

@Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter implements EnvironmentAware {      //...      @Inject     private AuthorizationServerTokenServices authTokenServices;      @Override     public void configure(HttpSecurity http) throws Exception {          SpringSocialConfigurer socialCfg = new SpringSocialConfigurer();         socialCfg             .addObjectPostProcessor(new ObjectPostProcessor<SocialAuthenticationFilter>() {                 @SuppressWarnings("unchecked")                 public SocialAuthenticationFilter postProcess(SocialAuthenticationFilter filter){                     filter.setAuthenticationSuccessHandler(                             new SocialAuthenticationSuccessHandler(                                     authTokenServices,                                     YOUR_APP_CLIENT_ID                             )                         );                     return filter;                 }             });          http             //... lots of other configuration ...             .apply(socialCfg);     }         } 

And the SocialAuthenticationSuccessHandler class:

public class SocialAuthenticationSuccessHandler implements AuthenticationSuccessHandler {      public static final String REDIRECT_PATH_BASE = "/#/login";     public static final String FIELD_TOKEN = "access_token";     public static final String FIELD_EXPIRATION_SECS = "expires_in";      private final Logger log = LoggerFactory.getLogger(getClass());     private final AuthorizationServerTokenServices authTokenServices;     private final String localClientId;      public SocialAuthenticationSuccessHandler(AuthorizationServerTokenServices authTokenServices, String localClientId){         this.authTokenServices = authTokenServices;         this.localClientId = localClientId;     }      @Override     public void onAuthenticationSuccess(HttpServletRequest request,             HttpServletResponse response, Authentication authentication)                     throws IOException, ServletException {         log.debug("Social user authenticated: " + authentication.getPrincipal() + ", generating and sending local auth");         OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(authentication)); //Automatically checks validity         String redirectUrl = new StringBuilder(REDIRECT_PATH_BASE)             .append("?").append(FIELD_TOKEN).append("=")             .append(encode(oauth2Token.getValue()))             .append("&").append(FIELD_EXPIRATION_SECS).append("=")             .append(oauth2Token.getExpiresIn())             .toString();         log.debug("Sending redirection to " + redirectUrl);         response.sendRedirect(redirectUrl);     }      private OAuth2Authentication convertAuthentication(Authentication authentication) {         OAuth2Request request = new OAuth2Request(null, localClientId, null, true, null,                 null, null, null, null);         return new OAuth2Authentication(request,                 //Other option: new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), "N/A", authorities)                 new PreAuthenticatedAuthenticationToken(authentication.getPrincipal(), "N/A")                 );     }      private String encode(String in){         String res = in;         try {             res = UriUtils.encode(in, GeneralConstants.ENCODING_UTF8);         } catch(UnsupportedEncodingException e){             log.error("ERROR: unsupported encoding: " + GeneralConstants.ENCODING_UTF8, e);         }         return res;     } } 

This way your client app will receive your web app's access token via redirection to /#/login?access_token=my_access_token&expires_in=seconds_to_expiration, as long as you set the corresponding REDIRECT_PATH_BASE in SocialAuthenticationSuccessHandler.

I hope it helps.

like image 95
rbarriuso Avatar answered Sep 30 '22 09:09

rbarriuso