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!
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With