No AuthenticationProvider found on refresh token - Spring OAuth2 java config - java

I have a Spring Boot project in which I've configured a Spring OAuth2 authentication process which partially works. I can authenticate OK but when I'm trying to get a refresh token I get an exception.
OAuth configuration:
#Configuration
public class OAuth2ServerConfiguration {
private static final String RESOURCE_ID = "xxx";
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/**").authenticated();
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Value("${clientDetailsService.clientName}")
private String clientName;
#Value("${clientDetailsService.clientSecret}")
private String clientSecret;
#Autowired
#Qualifier("authenticationManager")
private AuthenticationManager authenticationManager;
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
#Qualifier("tokenServices")
private AuthorizationServerTokenServices tokenServices;
#Autowired
#Qualifier("codeServices")
private AuthorizationCodeServices codeServices;
#Autowired
#Qualifier("requestFactory")
private OAuth2RequestFactory requestFactory;
#Autowired
#Qualifier("tokenGranter")
private TokenGranter tokenGranter;
private final TokenStore tokenStore = new InMemoryTokenStore();
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.setClientDetailsService(clientDetailsService);
endpoints.tokenServices(tokenServices)
.tokenStore(tokenStore)
.authorizationCodeServices(codeServices)
.authenticationManager(authenticationManager)
.requestFactory(requestFactory)
.tokenGranter(tokenGranter);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
#Bean(name = "tokenGranter")
#Primary
public TokenGranter tokenGranter() {
final List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();
tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, codeServices, clientDetailsService, requestFactory));
tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetailsService, requestFactory));
tokenGranters.add(new ImplicitTokenGranter(tokenServices, clientDetailsService, requestFactory));
tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory));
tokenGranters.add(new CustomTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory));
return new CompositeTokenGranter(tokenGranters);
}
#Bean
#Primary
public ClientDetailsService clientDetailsService(){
final InMemoryClientDetailsServiceBuilder builder = new InMemoryClientDetailsServiceBuilder();
builder.withClient(clientName)
.authorizedGrantTypes("password", "refresh_token")
.authorities("USER")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret(clientSecret);
try {
return builder.build();
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
#Bean(name = "tokenServices")
#Primary
public AuthorizationServerTokenServices tokenServices() {
final DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setClientDetailsService(clientDetailsService);
tokenServices.setTokenStore(tokenStore);
tokenServices.setAuthenticationManager(authenticationManager);
return tokenServices;
}
#Bean(name = "requestFactory")
#Primary
public OAuth2RequestFactory requestFactory() {
return new DefaultOAuth2RequestFactory(clientDetailsService);
}
#Bean(name = "codeServices")
#Primary
public AuthorizationCodeServices authorizationCodeServices() {
return new InMemoryAuthorizationCodeServices();
}
}
I also have some custom components defined, like a custom Token Granter, custom authentication provider etc. I'll post them if necessary.
As I said, authentication flow works OK. When I POST to /oauth/token I get a token and a refresh token, but when I then try to exchange my refresh token for a new token (by POSTing http://localhost:8080/oauth/token with grant_type=refresh_token and refresh_token=my refresh token) I get an exception:
No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
Where do I set the authentication provider? How do I get Spring to use my custom authentication provider for refresh tokens also?

I fixed this by explicitly defining a PreAuthenticationProvider:
#Component("preAuthProvider")
public class CustomPreAuthProvider extends PreAuthenticatedAuthenticationProvider {
#Autowired
private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> userService;
public CustomPreAuthProvider(){
super();
}
#PostConstruct
public void init(){
super.setPreAuthenticatedUserDetailsService(userService);
}
}
and then a custom userservice:
#Service
public class CustomPreAuthUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
#Override
public final UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) {
...
}
}
and adding this provider to the oauth2 config:
#Autowired
private AuthenticationProvider authenticationProvider;
#Autowired
#Qualifier("preAuthProvider")
private AuthenticationProvider preAuthProvider;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider).authenticationProvider(preAuthProvider);
}

As an alternative way to Jesper's answer, if you want to reuse your current UserDetailsService for this purpose, you can just do it the same way as Spring does it with their DefaultTokenServices:
#Bean
public CustomTokenServices tokenServices() {
CustomTokenServices tokenServices = new CustomTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setReuseRefreshToken(false);
tokenServices.setClientDetailsService(clientDetailsService);
tokenServices.setAuthenticationManager(createPreAuthProvider());
return tokenServices;
}
private ProviderManager createPreAuthProvider() {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(userDetailsService));
return new ProviderManager(Arrays.asList(provider));
}
UserDetailsService is autowired into this #Configuration class.

I can not be disagree with Jesper's answer, but in my case, that same error has been fixed removing:
tokenServices.setAuthenticationManager(authenticationManager)
from tokenService()

Related

Custom authentication provider not working

I am trying to have a custom authentication provider where I would like to have a keycloak as an authenticator.
Have created just a simple class for authentication provider but its not being called.
#Component
public class CustomKeycloakAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication auth)
throws AuthenticationException {
String username = auth.getName();
String password = auth.getCredentials()
.toString();
if ("externaluser".equals(username) && "pass".equals(password)) {
return new UsernamePasswordAuthenticationToken
(username, password, Collections.emptyList());
} else {
throw new
BadCredentialsException("External system authentication failed");
}
}
#Override
public boolean supports(Class<?> auth) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(auth));
}
}
Here is my WebConfig class:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
//#EnableMyHttpSession
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
private AccessDecisionManager accessDecisionManager;
#Autowired
private CustomKeycloakAuthenticationProvider keycloakAuthenticationProvider;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().accessDecisionManager(accessDecisionManager)
// .antMatchers("/oauth/token", "/*.html", "/js/**", "/images/**",
// "/styles/**").permitAll().
.antMatchers("/service/*").fullyAuthenticated()
// .antMatchers("/reports/*").fullyAuthenticated()
.anyRequest().permitAll().and().httpBasic().and().csrf().disable();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Override
#Bean(name = "authenticationManagerBean")
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
#Bean
public AffirmativeBased accessDecisionManager() {
List<AccessDecisionVoter<?>> accessDecisionVoters = new ArrayList<>();
accessDecisionVoters.add(new ScopeVoter());
accessDecisionVoters.add(new RoleVoter());
accessDecisionVoters.add(new AuthenticatedVoter());
AffirmativeBased accessDecisionManager = new AffirmativeBased(accessDecisionVoters);
return accessDecisionManager;
}
I also have a Authorization Server:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(AuthorizationServerConfiguration.class);
//private static String REALM="MY_OAUTH_REALM";
#Autowired
private DataSource dateSource;
#Autowired
private UserApprovalHandler userApprovalHandler;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Autowired
private CustomClientBuilder customClientBuilder;
#Autowired
private TokenStore tokenStore;
#Autowired
public UserService userService;
#Autowired
private CustomClientService customClientService;
#Autowired
private AccessRightsService accessRightService;
private MyTokenServices tokenServices = null;
#Bean
#Primary
public MyTokenServices tokenServices() {
if(tokenServices != null) return tokenServices;
tokenServices = new MyTokenServices();
tokenServices.setTokenStore(tokenStore);
tokenServices.setClientDetailsService(customClientService);
tokenServices.setAuthenticationManager(authenticationManager);
tokenServices.userService = userService;
tokenServices.accessRightService = accessRightService;
return tokenServices;
}
#Bean
#Primary
public TokenStore tokenStore( #Value("${oauth2Token.store.type}") String tokenStoreType) {
TokenStore tokenStore = null;
log.info("Token store is type " + tokenStoreType);
if(tokenStoreType.toLowerCase().equals("jdbc")){
tokenStore = new JdbcTokenStore(dateSource);
}else {
tokenStore = new InMemoryTokenStore();
}
log.info("Token store is " + tokenStore);
return tokenStore;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.setBuilder(customClientBuilder);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore)
.tokenServices(tokenServices())
.userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager).addInterceptor(new HandlerInterceptorAdapter() {
#Override
public boolean preHandle(HttpServletRequest hsr, HttpServletResponse rs, Object o) throws Exception {
rs.setHeader("Access-Control-Allow-Origin", "*");
rs.setHeader("Access-Control-Allow-Methods", "*");
rs.setHeader("Access-Control-Max-Age", "3600");
rs.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
log.info(hsr.getMethod());
if(hsr.getMethod().equals("OPTIONS")){
rs.setStatus(200); // hard fix for options
}
return true;
}
});
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
}
When I try to do a login in the providers there are only 2 of them:
I have tried to put #Autowired to protected void configure(AuthenticationManagerBuilder auth) { but it didn't helped
Don't know if there is something in configuration that I am missing so it doesn't add the 3rd authentication provider.
With Spring Security keyclaock can be configured with a class that derive of KeycloakWebSecurityConfigurerAdapter
#Configuration
#EnableWebSecurity
#KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
(https://www.keycloak.org/docs/latest/securing_apps/)
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-security-adapter</artifactId>
<version>20.0.2</version>
</dependency>
I think you don't need to create your own AuthenticationProvider keycloak give you an implementation KeycloakAuthenticationProvider
Update OK (but why ?) :
So I think you don't need to override that method
#Override
protected void configure(AuthenticationManagerBuilder auth)
Create another one like this
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(keycloakAuthenticationProvider());
}

Oauth 2.0 error when moving from Spring boot version 1.5.7 to 2.0, was working fine on 1.5.7.RELEASE

I had Oauth implemented in Spring Boot 1.5.7 but when I switched to 2 it showed me error "java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null".
From some research, I found that this may be an issue about password storage and password encoding.
What I've tried - I tried encoding the client secret in the authorization server file but that doesn't do anything and the error remains.
I've also tried saving the password with {bcrypt} as a prefix as spring security 5 looks for ann {id} during the password search.
I'm not able to fetch the access token and the above error doesn't go. Can someone help me figure this out? I've read and implemented almost everything and it doesn't seem to work.
Update: I was able to solve the above error by saving the password with {bcrypt} format. Similarly applying passwordEncoder in other required places.
Issue: I'm now facing an error with bad credentials. I've debugged and figured that its not getting the username we're trying to pass in the api and receiving null parameter. The flow reaches the userDetailservice but with an epmty parameter. I've attached my UserDetailsService along with this.
SecurityConfig.java
#Configuration
#EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private CustomPasswordEncoder customPasswordEncoder;
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(customPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
#Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
AuthorizationServerConfig.java
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static String REALM = "api-security";
#Value("${app.oauth.client-id}")
private String CLIENT_ID;
#Value("${app.oauth.client-secret}")
private String CLIENT_SECRET;
#Value("${app.oauth.access-token-validity}")
private int accessTokenValidity;
#Value("${app.oauth.refresh-token-validity}")
private int refreshTokenValidity;
#Autowired
#Qualifier("tokenStore")
private TokenStoreService tokenStore;
#Autowired
private UserApprovalHandler userApprovalHandler;
#Autowired
private BCryptPasswordEncoder passwordEncoder;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient(CLIENT_ID)
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_ADMIN").scopes("read", "write", "trust").secret(passwordEncoder.encode(CLIENT_SECRET))
.accessTokenValiditySeconds(accessTokenValidity).refreshTokenValiditySeconds(refreshTokenValidity);
System.out.println(passwordEncoder.encode(CLIENT_SECRET));
System.out.println(CLIENT_SECRET);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.realm(REALM + "/client");
}
}
UserDetailsService.java
#Configuration
#EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
#Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
// #Bean
// #Override
// public UserDetailsService userDetailsServiceBean() throws Exception {
// return super.userDetailsServiceBean();
// }
// #Bean
// public UserDetailsService userDetailsService() {
// return super.userDetailsService();
// }
}
For whoever finds this useful, I was able to solve this by the following points:
If you clear your access token collection or table, you'll be able to get the access toke once but that's it. Every request you do after that will go with "500 error - Internal server error".
This happens because spring boot wasn't able to understand the access token from the DB when making other requests, for which you can use "org.springframework.util.SerializationUtils" package. You can search about this, it serializes and deserializes the access tokens and refresh token when requests are made.

Spring boot 1.5.10 : implementing implicit grant

I am trying to implement Oauth2 with spring boot with the configurations as below
Securty configuration:
#Configuration
#EnableWebSecurity(debug = true)
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
auth.userDetailsService(userDetailsService);
}
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
return daoAuthenticationProvider;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(11);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().anonymous().disable().authorizeRequests()
.antMatchers("/oauth2/login","/logout").permitAll()
.anyRequest().authenticated()
.and().formLogin().loginPage("/oauth2/login").loginProcessingUrl("/login").permitAll();
}
}
Authorization configuration
#Configuration
#EnableAuthorizationServer
public class AuthServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private TokenStore tokenStore;
#Autowired
private ClientDetailsService clientDetailsService;
#Bean
public TokenStore tokenStore(DataSource dataSource){
return new JdbcTokenStore(dataSource);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer()));
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore)
.tokenEnhancer(enhancerChain)
.tokenGranter(new CompositeTokenGranter(getCustomizedTokenGranters()))
.tokenServices(tokenServices())
.approvalStoreDisabled();
}
#Bean
#Primary
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenEnhancer(tokenEnhancer());
tokenServices.setTokenStore(tokenStore);
tokenServices.setClientDetailsService(clientDetailsService);
return tokenServices;
}
#Bean
public TokenEnhancer tokenEnhancer(){
return (accessToken, authentication) -> {
if(!"client_credentials".equalsIgnoreCase(authentication.getOAuth2Request().getRequestParameters().get(OAuth2Utils.GRANT_TYPE)))
{
ExtendedUser principal = (ExtendedUser) authentication.getPrincipal();
Map<String, Object> additionalInfo = Maps.newHashMap();
additionalInfo.put("user_id", principal.getUserId());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
}
return accessToken;
};
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("permitAll()")
.tokenKeyAccess("permitAll()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
#Bean
public ClientDetailsService clientDetailsService(DataSource dataSource){
return new CachedClientDetailsService(dataSource);
}
private List<TokenGranter> getCustomizedTokenGranters() {
AuthorizationServerTokenServices tokenServices = tokenServices();
ClientDetailsService clientDetails = clientDetailsService;
OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetails);
RefreshTokenGranter refreshTokenGranter = new RefreshTokenGranter(tokenServices, clientDetails, requestFactory);
ImplicitTokenGranter implicit = new ImplicitTokenGranter(tokenServices, clientDetails, requestFactory);
ClientCredentialsTokenGranter clientCredentialsTokenGranter = new ClientCredentialsTokenGranter(tokenServices, clientDetails, requestFactory);
clientCredentialsTokenGranter.setAllowRefresh(true);//custom config, see AuthorizationServerEndpointsConfigurer.getDefaultTokenGranters
List<TokenGranter> tokenGranters = Lists.newArrayList();
tokenGranters.add(refreshTokenGranter);
tokenGranters.add(implicit);
tokenGranters.add(clientCredentialsTokenGranter);
if (authenticationManager != null) {
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices, clientDetails, requestFactory));
}
return tokenGranters;
}
}
Resource server configuration :
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/**").authenticated();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("identity-service");
}
#Bean
public ResourceServerTokenServices resourceServerTokenServices(TokenStore tokenStore){
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(tokenStore);
return tokenServices;
}
}
application.properties
security.oauth2.resource.filter-order = 3
the resource server is on the same authorization server (Same Application), and I am trying to implement the Implicit grant (Password grant working just fine)
when I am trying to login in to complete the implicit grant (oauth/authorize endpoint need authentication) I am getting /login 404 ?
spring boot: 1.5.10,
spring security Oauth2: 2.0.14
Finally, i managed to make it work
Security Configuration :
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/**").and().csrf().disable().authorizeRequests()
.antMatchers("/oauth2/login","/logout").permitAll()
.antMatchers("/oauth/authorize").authenticated()
.and().formLogin().loginPage("/oauth2/login").loginProcessingUrl("/login").permitAll();
}
Resources Server Configuration
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/api/**").and().anonymous().disable().authorizeRequests()
.anyRequest().authenticated();
}
I had to enable the anonymous in spring security and specify mapping URI matcher for both spring security and resource server
Resource server on /api/**
,Spring security on /**
and for taking care of the ordering (on version 1.5.10)
application.properties
security.oauth2.resource.filter-order = 3

Redirect AfterLogin With Facebook

I using ConnectionSignUp and SignInAdapter to do login function for website. I also use spring security.But I do not know how to finish loading the current page after logging in.
After login, the website will reload the form page : localhost:9090/#=
ConnectionSignUp.java
public class FacebookSignInAdapter implements SignInAdapter {
#Autowired
UsersRepository usersService;
#Override
public String signIn(String localUserId, Connection<?> connection, NativeWebRequest request) {
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken(connection.getKey(),
null, Arrays.asList(new SimpleGrantedAuthority("ROLE_FACEBOOK"))));
return null;
}}
FacebookConnectionSignup.java
public class FacebookConnectionSignup implements ConnectionSignUp {
#Autowired
UsersService usersService;
#Autowired
RolesService rolesService;
#Override
public String execute(Connection<?> connection) {
Users user = null;
try {
user = usersService.findByUserName(connection.getKey().toString());
if(user == null ) {
user = new Users();
user.setUserName(connection.getKey().toString());
user.setPassword(randomAlphabetic(8));
user.setEmail(connection.getKey()+"#gmail.com");
user.setFirstName(connection.getDisplayName());
user.setAvatar(connection.getImageUrl());
user.setStatus("active");
user.setCreatedDate(new Date());
user.setLoggedInDate(new Date());
user.setIsOnline((byte) 1);
HashSet<Roles> roleses = new HashSet<>();
roleses.add(rolesService.findByName("ROLE_FACEBOOK"));
user.setRoleses(roleses);
usersService.saveorupdate(user);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return user.getUserName();
}}
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler;
#Autowired
private AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler;
#Autowired
private ConnectionFactoryLocator connectionFactoryLocator;
#Autowired
private UsersConnectionRepository usersConnectionRepository;
#Autowired
private FacebookConnectionSignup facebookConnectionSignup;
#Autowired
private UserDetailsService userDetailsService;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/home", "/").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.and().formLogin().loginPage("/403").loginProcessingUrl("/login").usernameParameter("userName").passwordParameter("password")
.failureHandler(ajaxAuthenticationFailureHandler).successHandler(ajaxAuthenticationSuccessHandler)
.and().logout().logoutSuccessUrl("/")
.and().rememberMe().and()
.exceptionHandling().accessDeniedPage("/403");
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
#Bean
public ProviderSignInController providerSignInController() {
((InMemoryUsersConnectionRepository) usersConnectionRepository).setConnectionSignUp(facebookConnectionSignup);
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository,
new FacebookSignInAdapter());
}}
Now I want to finish loading the current page after logging in.
Hope everyone will help.
Thank you very much.

Spring Cloud OAuth2Authentication returns NullPointerException

I'm slowly moving into understanding Spring Cloud Security. I've created an authorization service and it works when authorizing and returning a token, but doesn't return any current user details when using that token, when getting these from OAuth2Authentication. This two lines return an NPE:
userInfo.put("user", user.getUserAuthentication().getPrincipal());
userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
OAuth2Authentication user isn't instantiated and is null, while I understood that it should be by default instantiated by Spring Security. Maybe I am missing some configuration beans? Thanks in advance!
Application.class
#SpringBootApplication
#RestController
#EnableResourceServer
#EnableAuthorizationServer
public class AuthorizationServiceApplication {
#RequestMapping(value = {"/user"}, produces = "application/json")
public Map <String, Object> user (OAuth2Authentication user) {
Map <String, Object> userInfo = new HashMap <>();
userInfo.put("user", user.getUserAuthentication().getPrincipal());
userInfo.put("authorities", AuthorityUtils.authorityListToSet(user.getUserAuthentication().getAuthorities()));
return userInfo;
}
public static void main (String[] args) {
SpringApplication.run(AuthorizationServiceApplication.class, args);
}
}
OAuth2Config.class
#Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Value("${token.secret}")
private String secret;
private AuthenticationManager authenticationManager;
private UserDetailsService userDetailsService;
public OAuth2Config (AuthenticationManager authenticationManager, UserDetailsService userDetailsService) {
this.authenticationManager = authenticationManager;
this.userDetailsService = userDetailsService;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("eagleeye")
.secret(secret)
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
WebSecurityConfigurer.class
#Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
#Override
#Bean
public AuthenticationManager authenticationManagerBean () throws Exception {
return super.authenticationManagerBean();
}
#Override
#Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
// TODO: implemented DB stuff
#Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.inMemoryAuthentication()
.withUser("deniss").password("deniss1").roles("USER")
.and()
.withUser("oksana").password("oksana").roles("USER, ADMIN");
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setSessionAttributeName("_csrf");
return repository;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(csrfTokenRepository());
}
}
In the end I got it working like this:
Application.class
#SpringBootApplication
#RestController
#EnableResourceServer
public class AuthorizationServiceApplication {
private final Logger log = LoggerFactory.getLogger(this.getClass());
#RequestMapping("/user")
public Principal user(Principal user) {
log.info("User information display for User: " + user.getName());
return user;
}
#Bean
UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("deniss").password("deniss").roles("USER").build());
return manager;
}
public static void main (String[] args) {
SpringApplication.run(AuthorizationServiceApplication.class, args);
}
}
OAuth2Config.java
#Configuration
#EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
//TODO: refactor to recieve this info from config server
#Value("${token.secret}")
private String secret;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("eagleeye")
.secret(secret)
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
}
}
SecurityConfigurer.class
#Configuration
#EnableGlobalAuthentication
public class SecurityConfigurer extends GlobalAuthenticationConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
// TODO: implemented DB stuff
#Override
public void init(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(this.userDetailsService);
}
}
I met the same problem, it seems a bug of new version. I changed Spring Boot 1.5.9.RELEASEļ¼ŒSpring Cloud Edgware.RELEASE backed to Spring Boot 1.4.4.RELEASEļ¼ŒSpring Cloud Camden.SR5, the problem disappeared.
Set security.oauth2.resource.filter-order=3 configuration property to restore the ordering used in previous versions. See enter link description here for more details.

Categories

Resources