How to autowire this TokenStore
Solution 1
The error is quite clear, it means, that you don't have a bean of type TokenStore
defined. The default configuration of Spring Security OAuth doesn't expose the token store as a bean, so you have to do it by yourself:
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
Use the appropriate implementation here (can also be JwtTokenStore or RedisTokenStore or your own).
Then create a configuration class which extends AuthorizationServerConfigurerAdapter
, where you configure that token store for Spring Security OAuth, so that it doesn't create a default one again:
@Configuration
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
TokenStore tokenStore;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore);
}
}
Then you should be able to inject that TokenStore bean wherever you want.
Solution 2
I was also facing similar issue in my project. I changed the @autowired annotation to constructor dependency. you can try below code.
private TokenStore tokenStore;
@Autowired
public OAuthController(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}
CodeMed
Updated on June 15, 2022Comments
-
CodeMed almost 2 years
How do I trigger auto-logout of this sample Spring Boot OAuth2 app?
I tried adding the following code from an answer to this other posting into a new controller class in the
demo
package of theauthserver
app:package demo; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.http.HttpStatus; @Controller public class OAuthController { @Autowired private TokenStore tokenStore; @RequestMapping(value = "/oauth/revoke-token", method = RequestMethod.GET) @ResponseStatus(HttpStatus.OK) public void logout(HttpServletRequest request) { String authHeader = request.getHeader("Authorization"); if (authHeader != null) { String tokenValue = authHeader.replace("Bearer", "").trim(); OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue); tokenStore.removeAccessToken(accessToken); } } }
But when I try to launch the app, the debug log gives the following error indicating that it cannot
autowire
the token store:Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.security.oauth2.provider.token.TokenStore demo.OAuthController.tokenStore; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.oauth2.provider.token.TokenStore] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ... 23 more Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.oauth2.provider.token.TokenStore] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545 ) ... 25 more
When the compilation error is resolved, I intend to trigger the logout process from the following code which will be added to the
hello.js
controller of theui
app in the github link above:self.logout = function() { $http.post('http://localhost:9000/oauth/revoke-token', {}).finally(function() { $rootScope.authenticated = false; $location.path("/"); }); }
The full code of the sample app is at the github link above, so what specific changes do I need to make in order to successfully
autowire
thetoken store
and auto-logout the user globally?
ONGOING EFFORTS:
Per @ManoJ's suggestion, I changed the new controller class to become the following:
package demo; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.http.HttpStatus; @Controller public class OAuthController { private TokenStore tokenStore; @Autowired public OAuthController(TokenStore tokenStore) { this.tokenStore = tokenStore; } @RequestMapping(value = "/oauth/revoke-token", method = RequestMethod.GET) @ResponseStatus(HttpStatus.OK) public void logout(HttpServletRequest request) { String authHeader = request.getHeader("Authorization"); if (authHeader != null) { String tokenValue = authHeader.replace("Bearer", "").trim(); OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue); tokenStore.removeAccessToken(accessToken); } } }
However, I am still getting a very similar error message when I try to launch the app at the terminal with
mvn spring-boot:run
, as follows:java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:478) at java.lang.Thread.run(Thread.java:745) Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'OAuthController' defined in file [/home/user/spring_boot_apps/security_tut_remodel/tut-spring-security-and-angular-js/oauth2/authserver/target/classes/demo/OAuthController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.security.oauth2.provider.token.TokenStore]: No qualifying bean of type [org.springframework.security.oauth2.provider.token.TokenStore] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.oauth2.provider.token.TokenStore] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) at demo.AuthserverApplication.main(AuthserverApplication.java:88) ... 6 more Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.oauth2.provider.token.TokenStore] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ... 25 more [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------
Given that this class is the only addition to the sample app in the link in the first line of the
OP
above, all of the code for the entire app is available both online and on your own devbox withgit clone ...
. So what else needs to change in order for autowire of the TokenStore to work properly? -
CodeMed about 8 yearsThank you and +1. I marked this as accepted because you answered the question. However, to avoid overposting clutter, can you please also show how to use tokenStore in a DIFFERENT controller after you autowire it? For example, the following code from the OP throws a compilation error asking what
tokenStore
is unless I put it inside yourAuthorizationServerConfiguration
class:@RequestMapping(value = "/oauth/revoke-token", method = RequestMethod.GET) @ResponseStatus(HttpStatus.OK) public void logout(HttpServletRequest request) { ... tokenStore.readAccessToken(tokenValue);...}
-
CodeMed about 8 yearsThank you and +1 for looking into this problem. However, your suggestion left an error until the other user's suggested code was added to successfully inject the
@Bean
. -
dunni about 8 yearsIf you use it how you did it in your OAuthController, it should be fine. Of course you have to define the field
tokenStore
if you want to use it (and autowire the field or the constructor). -
Parth Solanki over 7 years@dunni Thank you so much. you save my day :)