In a Spring Boot application, I have an OAuth2 Authorization/Resource servers. Based on this and Spring Security, I have secured my Spring MVC REST API endpoints.
In addition to this, I'd like to add authentication to my REST endpoints based on 3rd party OAuth providers like Twitter, Facebook, Google.
In my application I have two entities - User
and SocialUser
. SocialUser
represents user profile in social networks. User
can have 0-* associated SocialUsers
. Right now I can authenticate a user in Twitter and after that I'm creating two records in my database - User and SocialUser. SocialUser contains access/refresh tokens issued by Twitter and some other profile information from this social network.
Right now I don't know how to link this User created from social network with my existing authentication\authorization flow. For this user I'd like to create my own(by my own OAuth2 authorization server) accessToken and provide it to the client.
Also, this user doesn't have username, password and email in his User
entity. And also I don't know how to manually create my own access Token and send it to the client for future API calls.
I found some example:
@Inject
private TokenEndpoint tokenEndpoint;
public String createAccessToken(User user) {
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("client_id", "appid");
parameters.put("client_secret", "myOAuthSecret");
parameters.put("grant_type", "password");
parameters.put("password", user.getPassword());
parameters.put("scope", "read write");
parameters.put("username", user.getUsername());
// principal ??
return tokenEndpoint.getAccessToken(principal, parameters);
}
but I don't know how to create Principal
based on my User
entity and also I'm not sure that this is a correct way to go.
So, the main question is - how to manually generate this new token through my own OAuth server for this new user?
Please advise me how can it be correctly implemented. Thanks.
UPDATED:
I have added ProviderSignInController
to my application and able right now to perform full OAuth dance with Twitter. Also, I have implemented my own Neo4jConnectionRepository
and Neo4jUsersConnectionRepository
because I use Neo4j as a primary database.
@Bean
public ProviderSignInController providerSignInController() {
return new ProviderSignInController(socialAuthenticationServiceLocator, usersConnectionRepository, new SignInAdapter() {
@Override
public String signIn(String userId, Connection<?> connection, NativeWebRequest request) {
System.out.println("User ID: " + userId + " social display name: " + connection.getDisplayName());
return null;
}
});
}
So far, everything works good.
The one question is - how to authenticate/authorize User
through my own OAuth2 Authorization server in the SignInAdapter.signIn
method ?
I think I need to create OAuth2Authentication
object for this user and put it into Security context.. Am I right ? If so, could you please show me an example how can this be implemented ?
Since Spring Security doesn't provide Authorization Server support, migrating a Spring Security OAuth Authorization Server is out of scope for this document.
So what you want to achieve is : when clients redirect users to your authorization server (authorization code or implicit grant) in order to obtain a token, the user can log-in using his favorite social network.
If I understand correctly, you have rolled your own implementation of single sign on (SSO) with Twitter (ProviderSignInController
), and now you're left wondering how to generate a token when Twitter responds "OK".
I think you took the problem by the wrong end : Instead of building your Twitter client and generating a token programmatically, the idea is to integrate social SSO inside the flow of spring-security-oauth2, which in reality is how to integrate social SSO in Spring Security.
In the end, it's about how your authorization server secures the AuthorizationEndpoint : /oauth/authorize
.
Since your authorization server works, you already have a configuration class extending WebSecurityConfigurerAdapter
that handles the security for /oauth/authorize
with formLogin
. That's where you need to integrate social stuff.
Instead of using the Spring Security built-in form authentication mechanism, you will have to plug-in your own security that either allows the user to login with a form, or starts SSO with other providers.
Spring Security is made of a bunch of abstractions, but it really just comes down to populating the SecurityContext
with an Authentication
object for each request.
Once the authentication process is complete, the user will continue to /oauth/authorize
, consent to the client accessing some scopes, and the token will be delivered as it's usually done, without you having to generate tokens programmatically.
I have done that using SAML (Spring Security SAML extension), but in your case you should dig in the Spring Social projects, which seem to support all the major social networks out of the box.
The good news is that you already have a bunch of tools available, the "bad news" is that you will have to understand how they work to a certain degree in order to plug them together.
This tutorial shows how to achieve exactly that (if I understood the problem correctly) : having an auth server issuing your own oauth2 tokens based on external oauth2 authentication. The corresponding code is available here.
The gist of it is that you use @EnableOAuth2Client
in addition to @EnableAuthorizationServer
and insert an OAuth2ClientAuthenticationProcessingFilter
filter before spring security default ones.
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