How to tie OAuth authentication with Spring Security
Asked Answered
L

2

8

I have a Grails 2.5.3 app that currently uses spring security plugin for authentication. Users login using a username/pwd.

I have updated the app now to support OAuth authentication (Using ScribeJava). Users can click a link that redirects them to OAuth providers page and upon successfully entering the credentials they are redirected back to my application. However, I have not been able to tie this functionality with spring security plugin so that when the users are redirected back to my app (after successful login from OAuth), I can actually see that they are logged in and continue to use all my spring security goodies like <sec:ifLoggedIn>.

Does anyone know of a way to do this or have an example I can take a look at?

Here is how I authenticate a user using OAuth:

//called when user clicks "login using oauth"
def authenticate() {
    OAuthService service = new ServiceBuilder()
                              .apiKey(grailsApplication.config.my.sso.clientid)
                              .apiSecret(grailsApplication.config.my.sso.clientsecret)
                              .build(MyApi.instance());
    String url =  service.getAuthorizationUrl();
    return redirect(url: url)
}

//called when oauth provider redirects to my application
def authorization_code() {
    def code = params.code
    OAuthService service = new ServiceBuilder()
                              .apiKey(grailsApplication.config.my.sso.clientid)
                              .apiSecret(grailsApplication.config.my.sso.clientsecret)
                              .build(MyApi.instance());
    println code                          
    OAuth2AccessToken accessToken = service.getAccessToken(code);
    String userProfileUrl = grailsApplication.config.my.sso.authdomain+"/userinfo"
    final OAuthRequest request = new OAuthRequest(Verb.GET, userProfileUrl);
    service.signRequest(accessToken, request);
    final Response response = service.execute(request);
    println(response.getCode());
    println(response.getBody());        
    render (text: code)
}
Lemaster answered 12/3, 2017 at 19:23 Comment(1)
does any of the below answer helped you ?Giorgio
D
1

Whenever you authenticate via OAuth, the remote server return you a unique id (some numeric value) each time. You can use that id to verify the user in your end and authenticate the user using springsecurity.reauthenticate() method.

Steps to do that :

  1. When user connect (authenticate first time) with service provider. Service provider send you that unique id. Save that unique id in user table.
  2. And when user login via that service provider. Again service provider sends that unique id. Check if that unique id exists in your system, and if user exists with that unique id then use springsecurity.reauthenticate(userInstance) method to authenticate the user. And now you can use spring security features.

check out link: http://www.jellyfishtechnologies.com/grails-2-2-0-integration-with-facebook-using-grails-oauth-plugin/

Desjardins answered 17/3, 2017 at 7:52 Comment(0)
G
0

Assuming you got the user details from Oauth provider you just need to set the security context of that particular user

Just get the user details by parsing the JSON like

def oauthResponse = JSON.parse(response?.getBody())
Map data = [
                    id          : oauthResponse.id,
                    email       : oauthResponse.email,
                    name        : oauthResponse.name,
                    first_name  : oauthResponse.given_name,
                    last_name   : oauthResponse.family_name,
                    gender      : oauthResponse.gender,
                    link        : oauthResponse.link
            ]

Well in our case we used the email id as the user name.

So when we get the user data just check if user is already registered with system or not like below

//load the user details service bean
def userDetailsService

//check if user is already registered on our system
User user = User.findByEmail(data?.email)
if (user) {

    //If user exists load his context
    userDetails = userDetailsService.loadUserByUsername(data?.email)
} else {

    //create the new user
    //Assign the role to it

    //load his context as below
   userDetails = userDetailsService.loadUserByUsername(data?.email)
}

After user registered successfully we just need to load his context like below

def password

//setting spring security context
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(userDetails, password == null ? userDetails.getPassword() : password, userDetails.getAuthorities()))

Once spring security context is loaded you can redirect user to your landing page.

Now oauth user will be access resources like the any other user with same role.

Giorgio answered 17/3, 2017 at 9:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.