Own Spring OAuth2 server together with 3rdparty OAuth providers
Asked Answered
R

2

21

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 ?

Review answered 19/4, 2015 at 18:50 Comment(8)
If I understand correctly : You have an authorization server that delivers your own tokens, some resource servers that are secured with these tokens. Your authorization server authenticates your users against its own user database, and you want to add Single Sign On (SSO) to authenticate your users with 3rd parties ?Myrnamyrobalan
Yes, you are correct. 3rd parties are for example Google, Facebook, Yahoo OAuth providersReview
See https://mcmap.net/q/297231/-integrate-spring-security-oauth2-and-spring-socialGielgud
I have the same requirement. Did you get this working? Can you provide more details how? I wonder what you do exactly in the SignInAdapter?Oratorian
I'm moved away from own OAuth2 server to JWTReview
hi can you provide me any sample example source (like github link) for the single sign on (facebook, google) with your auth mechanism (oauth/jwt) that you did. why did you moved away from own OAuth2 server to jwt?Needless
I think here you can find an example for Integration of Spring Security OAuth2 and Spring Social #32314321Review
@Review May I ask what you meant with I'm moved away from own OAuth2 server to JWT ? Did you move away from OAuth ?Chaconne
M
9

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.

Marathon answered 22/10, 2015 at 9:23 Comment(1)
hi, is there any example project on github or anywhere else on this?Needless
P
0

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.

Pangolin answered 7/3, 2018 at 23:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.