简体   繁体   中英

Spring OAuth2 custom grant type autowiring a class returns null

I have a problem with Spring Security OAuth2. There is a kiosk system where all the kiosks need to authorize with a central OAuth2 provider during launch. There are two stores for credentials -- one for actual users (eg technicians) and another one for kiosks. The collection for kiosks store kiosk profile information, which is essentially serial numbers of all the devices used in a kiosk (bill acceptor, cash dispenser, thermal printer etc).

So, here is the flow that I am trying to achieve.

  • Kiosk sends its profile information to /oauth/token with grant_type=kiosk
  • If profile exists, OAuth2 gives the token and everything is great
  • If profile does not exist, the kiosk profile is added to the kiosks collection with state "off" and OAuth2 gives 401 Unauthorized

Now, I have created a new grant type for kiosk authorization. But I need a way to access my Kiosk Profile Data Mapper, which is a Spring service. So, in my class I add the following:

class KioskTokenGranter extends AbstractTokenGranter {
    @Autowire
    KioskProfileService kioskProfile;

    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
          // request parsing stuff
          kioskProfile.findByAttributes(...);
    }
}

The snipper above gives me a NullPointerException that kioskProfile does not exist. If I do the same thing in AuthorizationServerConfigurerAdapter, autowire works. So, my question is how to Autowire a service inside TokenGranter.

It appears you're just running into the plain old problem where the objects you are instantiating aren't controlled by Spring. You haven't annotated your class as a @Component or anything like that (not that I would recommend you do in this case). Spring isn't aware of your @Autowire annotation.

For another example of someone's implementation of AbstractTokenGranter, take OBOTokenGranter.java .

 public class OBOTokenGranter extends AbstractTokenGranter {

    ...

    private UserDetailsService uds;

    public OBOTokenGranter(UserDetailsService uds, AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
        OAuth2RequestFactory requestFactory) {
       super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);

       this.uds = uds;
   }

   ...
 }

Note that UserDetailsService uds is being passed in via the constructor instead of autowired in. You can see the usaged of OBOTokenGranter in OBOTokenGenerator.java , which is a @RestController and has the UserDetailService autowired into it, so that it can be used in construction of the Granter.

 @RestController
 public class OBOTokenGenerator {

 ...

    @Autowired
    private UserDetailsService uds;

 ...
    @RequestMapping("/obo/{user}")
    public ResponseEntity<OAuth2AccessToken> getOBOToken(Principal principal, @PathVariable("user") String user) {

 ...

        OBOTokenGranter granter = new OBOTokenGranter(uds, tokenServices, clientDetailsService, requestFactory);

 ...
 }

So the question remaining is: does your code follow this pattern of usage? Do you have a Controller/Service/Component/etc that constructs the KioskTokenGranter ?

KioskTokenGranter needs to be annotated with @Component . Also make sure that Component scanning is enabled for the package that KioskTokenGranter is in.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM