0
votes

I've been trying to implement Facebook OAuth from here: http://alvarosanchez.github.io/grails-spring-security-rest/latest/docs/index.html#_delegating_authentication_to_oauth_providers

I'm able to integrate OAuth and get the access token from Facebook but I'm facing problem implementing a custom OAuthUserDetailsService. I've created a custom service:

FacebookOauthUserDetails.groovy

class FacebookOauthUserDetailsService implements OauthUserDetailsService{

@Delegate
UserDetailsService userDetailsService
UserDetailsChecker preAuthenticationChecks

@Override
OauthUser loadUserByUserProfile(CommonProfile userProfile, Collection<GrantedAuthority> defaultRoles) throws UsernameNotFoundException {
    UserDetails userDetails
    OauthUser oauthUser
    println("adss")
    try {
        println("Trying to fetch user details for user profile: ${userProfile}")
        userDetails = userDetailsService.loadUserByUsername(userProfile.id)
        log.debug("Checking user details with ${preAuthenticationChecks.class.name}")
        preAuthenticationChecks?.check(userDetails)
        Collection<GrantedAuthority> allRoles = userDetails.authorities + defaultRoles
        oauthUser = new OauthUser(userDetails.username, userDetails.password, allRoles, userProfile)
    } catch (UsernameNotFoundException unfe) {
        println("User not found. Creating a new one with default roles: ${defaultRoles}")
        oauthUser = new OauthUser(userProfile.id, 'N/A', defaultRoles, userProfile)
    }

    return oauthUser
}
}

the official documentation mentions that in order to override the default behavior one needs to define it in resources.groovy with bean name oauthUserDetailsService.This is how my resources.groovy file looks like:

resources.groovy:

import hungr.FacebookOauthUserDetailsService
import hungr.UserPasswordEncoderListener

beans =
{
    userPasswordEncoderListener(UserPasswordEncoderListener)
    oauthUserDetailsService(FacebookOauthUserDetailsService)
}

I've tried to refer to this doc here on how to define a bean : https://docs.grails.org/latest/guide/spring.html but it didn't work out for me either. What am I doing wrong?

1
'userDetailsService' may not injected properly/ not resolving, are you using grails3? - Nitin Dhomse
Yes I'm using grails 3. - Aditya Gurjar
Did you find the null issue and why your service is not getting injected? - Nitin Dhomse

1 Answers

0
votes

GrailsUserDetailsService is the interface basically reside in theorg.springframework.security.core.userdetails package. You can implement the loadUserByUsername method of above service (interface) in your service (class) and write a code (implementation) to get your desired data / userdetails, you can get the user details as object/list/map whatever format you want, you can find data there by GORM finder method by the given username and return that data. Below is sample example,

Service code:

class Your_service_name implements GrailsUserDetailsService {

      Map loadUserByUsername(String username) throws UsernameNotFoundException {
        Map userDetails = [:]
        User.withTransaction { status ->

        User user = User.findByUsername(username, ["readOnly": true])
        if (!user) throw new UsernameNotFoundException('User not found', username)
        // you can also return the whole user object here instead of map keep method return type as UserDetails  and return user object, you also return the user roles along with other details in Map.
        userDetails["username"] = user.username
        userDetails["emailAddress"] = user.emailAddress
        userDetails["userFullName"] = user.userFullName
        return userDetails
   }
}

Now, you can inject the above service in your controller and call the method as below,

class YourController{
  Your_service_name myService // injected above created service which contains the loadUserByUsername method implementation

  def getUserDetails(){
    Map userdetails = myService.loadUserByUsername("username_to_find")
    println userdetails
  }
}

Your resources.groovy will be as follows,

beans = {
    userDetailsService(Your_service_name)
}

Note : Clean and restart your application after this change.