Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated Client code does not have springSecurityService autowired #18

Open
2 of 4 tasks
paulito415 opened this issue Aug 13, 2019 · 0 comments
Open
2 of 4 tasks

Comments

@paulito415
Copy link

paulito415 commented Aug 13, 2019

Taken from Slack (grails-community at grails.slack.com).

I'm getting a weird problem with using the Spring Security OAuth2 Provider plugin org.grails.plugins:spring-security-oauth2-provider:3.2.1 in my grails 3.3.6 app. The Client class that is generated has a transient springSecurityService that is used for checking for ?.passwordEncoder and then subsequently invoking .encodePassword on the clientSecret member. But I'm not sure how any kind of injection is done on this transient springSecurityService during the life-cycle of the app. Specifically in my BootStrap, where I create a Client, I laced everything with println calls and learned that my clientSecret has not been encoded because springSecurityService has never been non-null. I noticed in the documentation that they don't actually instantiate the Client with any clientSecret set, so I am a bit confused.

My question is, is it wrong of me to try to instantiate a Client in BootStrap with the clientSecret passed in? Or is there something else in my setup that I'm missing?

@davebrown replied on Slack asking about Spring Security Core dependency and offering a workaround to injection

protected void encodePassword() {
      SpringSecurityService service = springSecurityService ?: grails.util.Holders.applicationContext.getBean('springSecurityService') as SpringSecurityService

      password = service?.encodePassword(password) ?: password
    }

I responded saying that the Spring Security Core dependency is implicit so nothing needs to be explicitly specified.

Also that his code does indeed fix the problem so basically the issue is isolated to just one where springSecurityService wasn't being autowired.

I started digging again. This time I found my solution / explanation in the last line of an issue raised for something slightly different from my problem.

Apparently, the latest GORM has disabled the autowiring of domain classes (like my generated Client class). The simple solution is to override that default behavior by adding:

static mapping = {
   autowire true
}

into Client. But alas, since Client is generated by s2-init-oauth-provider, that's why I'm filing a bug here. Or perhaps the authors of this plugin meant for this Client code to be used in a different way? Maybe that's why in the example code for the BootStrap for Client Registration the clientSecret was omitted in the construction of the Client instance?

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. Start with a Grails 3.3.6 project (or any 3.3.x for that matter) with the rest-api profile
  2. Install Spring Security OAuth2 Provider by adding compile 'org.grails.plugins:spring-security-oauth2-provider:3.2.1' into build.gradle
  3. From the documentation run grails s2-init-oauth2-provider com.yourapp Client AuthorizationCode AccessToken RefreshToken to generate the classes.
  4. Add Client Registration in BootStrap to create an instance of a Client in the init method
    Client myClient = Client.findByClientId('my-client')
    if (!myClient)
    {
      myClient = new Client(clientId: 'my-client',
                            clientSecret: 'my-secret',
                            authorizedGrantTypes: ['authorization_code',
                                                   'refresh_token',
                                                   'implicit',
                                                   'password',
                                                   'client_credentials'],
                            authorities: ['ROLE_CLIENT'],
                            scopes: ['read', 'write'],
                            redirectUris: ['http://myredirect.com'])
      myClient = myClient.save(failOnError: true, flush: true)
      log.debug "Saved my client ${myClient.clientId}"
    }
  1. Run s2-quickstart com.yourapp User Role to create User domain entities
  2. Add User / Role creation code in BootStrap
    User user = User.findByUsername("myuser")
    if (!user)
    {
      User.withTransaction {
        shopper = new User(username: "myuser", password: "mypass").save(flush: true, failOnError: true)
        Role role = Role.findOrSaveWhere(authority: "ROLE_USER")
        UserRole.create(user, role, true)
      }
    }
  1. Run the app
  2. Try authenticating with OAuth2 by making a POST to http://localhost:8080/oauth/token with the following form fields:
  • client_id: my-client
  • client_secret: my-secret
  • username: myuser
  • password: mypass
  • scope: read
  • grant_type: password

Expected Behavior

The authentication should succeed and I should be getting an access token for the myuser user.

Actual Behavior

I get an invalid client credentials error.

Upon inspection in my database, I realized that although my User password is encoded, my Client's clientSecret is not (i.e. it's plain text). This led me to investigate the code within the Client.encodeClientSecret method and realizing that springSecurityService is never non-null.

Environment Information

  • Operating System: Windows / CygWin
  • GORM Version: 3.5
  • Grails Version (if using Grails): 3.3.6
  • JDK Version: 1.8.0_211

Example Application

  • TODO: link to github repository with example that reproduces the issue
chenmins pushed a commit to chenmins/grails-spring-security-oauth2-provider that referenced this issue Oct 10, 2022
…der/issues/18

the latest GORM has disabled the autowiring of domain classes (like my generated Client class). The simple solution is to override that default behavior by adding:

static mapping = {
   autowire true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant