spring security Authentication and resource server seprated check_token is not sending authorization header (outh2 jwt spring boot, zuul) - spring-boot

problem
resource server making request for check_token its not passing authorization token which is implemented by spring security. how we can pass authorization token for /check_token endpoint?
I am using zuul as api gateway and all request go through zuul only.
i created auth server which is authentication server (spring cloud project)
and code is given below for authorization and i register authenticationManager with webSecurityConfigurationAdapter
code is given below
AuthorizationServerConfig.java
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
#Autowired
private AuthenticationManager authenticationManager;
#Value("${config.oauth2.tokenTimeout}")
private int expiration;
#Value("${config.oauth2.privateKey}")
private String privateKey;
#Value("${config.oauth2.publicKey}")
private String publicKey;
#Autowired
private ClientDetailsService clientDetailsService;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("client")
.secret(passwordEncoder().encode("secret"))
.authorizedGrantTypes("client_credentials", "password", "refresh_token", "authorization_code")
.scopes("read", "write", "trust")
.accessTokenValiditySeconds(expiration)
.refreshTokenValiditySeconds(expiration);
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(privateKey);
return converter;
}
#Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Value("${filters.cors.allowed.origin}")
private String allowedOriginUrlForCordFilter;
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin(allowedOriginUrlForCordFilter);
//config.addAllowedOrigin("http://localhost:8080/");
config.addAllowedHeader("*");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setClientDetailsService(clientDetailsService);
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenEnhancer(accessTokenConverter());
return defaultTokenServices;
}
/**
* Defines the authorization and token endpoints and the token services
* #param endpoints
* #throws Exception
*/
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
.tokenStore(tokenStore())
.tokenServices(tokenServices())
.accessTokenConverter(accessTokenConverter());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
}
resource server another spring cloud project which is basically our business services
and for further communication i need authorization token this code is implement by using filter i implemented.
ResourceServerConfiguration.java
#Configuration
#EnableResourceServer
#EnableWebSecurity(debug = true)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
// private static final Logger LOGGER =
// Logger.getLogger(ResourceServerConfiguration.class);
#Value("${config.oauth2.publicKey}")
private String publicKey;
#Value("${config.oauth2.privateKey}")
private String privateKey;
#Value("${config.oauth2.resource.id}")
private String resourceId;
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable().anonymous().disable().authorizeRequests()
// .antMatchers(HttpMethod.OPTIONS).permitAll()
// .antMatchers("/oauth/**").authenticated()
.antMatchers("/register/**").authenticated();
}
// #Override
// public void configure(ResourceServerSecurityConfigurer resources) {
// resources.resourceId(resourceId).tokenServices(tokenServices()).tokenStore(tokenStore());
// }
// #Bean
// #Primary
// public DefaultTokenServices tokenServices() {
// DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
// defaultTokenServices.setTokenStore(tokenStore());
// defaultTokenServices.setSupportRefreshToken(true);
// defaultTokenServices.setTokenEnhancer(accessTokenConverter());
// return defaultTokenServices;
// }
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(privateKey);
return converter;
}
#Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Primary
#Bean
public RemoteTokenServices tokenServices() {
final RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setCheckTokenEndpointUrl("http://localhost:8765/auth/oauth/check_token/");
tokenService.setClientId("client");
tokenService.setClientSecret("secret");
//tokenService.setTokenName("");
// tokenService.setTokenStore(tokenStore());
// tokenService.setSupportRefreshToken(true);
tokenService.setAccessTokenConverter(accessTokenConverter());
return tokenService;
}
}
now issue is when resource server making request for check_token there i am anable to pass authorization token.

Related

How to verify signature utilizing accessTokenConverter?

I need to verify signature at resource server. I am signing JWT with private key at auth.server and It is signed OK, but I cannot find a way, how to verify it using accessTokenConverter. In my previous project, I did not use JDBC, so I was using jwtTokenStore and It worked without a problem, but I cannot verify that signature with JDBCTokenStore. How to do that? So code at authorization server works, I need to verify it at resource server... .setVerifiedKey(publicKey) should be working, but I need to configure it with JDBCTokenStore...
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private TokenStore tokenStore;
// #Autowired
// private JwtAccessTokenConverter accessTokenConverter;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsService userCustomService;
#Autowired
private JdbcTemplate jdbcTemplate;
#Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.jdbc(jdbcTemplate.getDataSource());
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore)
.reuseRefreshTokens(false)
.accessTokenConverter(accessTokenConverter())
.authenticationManager(authenticationManager)
.userDetailsService(userCustomService);
;
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter(){
#Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
if(authentication.getOAuth2Request().getGrantType().equalsIgnoreCase("password")) {
final Map<String, Object> additionalInfo = new HashMap<String, Object>();
additionalInfo.put("organization", "NEJAKA INFORMACE");
((DefaultOAuth2AccessToken) accessToken)
.setAdditionalInformation(additionalInfo);
}
accessToken = super.enhance(accessToken, authentication);
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(new HashMap<>());
return accessToken;
}
};
KeyStoreKeyFactory keyStoreKeyFactory =
new KeyStoreKeyFactory(new ClassPathResource("test.jks"), "password".toCharArray());
converter.setKeyPair(keyStoreKeyFactory.getKeyPair("test"));
return converter;
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");
}
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired
private ResourceServerTokenServices tokenServices;
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenServices(tokenServices); }
#Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.authorizeRequests()
.antMatchers("/documents/**").authenticated()
.antMatchers("/users/**").authenticated()
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Bean
public JwtAccessTokenConverter accessTokenConverterr() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
}
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// private String signingKey = "MaYzkSjmkzPC57L";
#Autowired
private UserDetailsService userCustomService;
#Autowired
private JdbcTemplate jdbcTemplate;
private PasswordEncoder encoder;
public SecurityConfig(){
this.encoder = new BCryptPasswordEncoder();
}
#Bean
#Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userCustomService).passwordEncoder(encoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.
STATELESS)
.and()
.httpBasic()
.and()
.csrf()
.disable();
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(jdbcTemplate.getDataSource());
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
}

Spring Security Authentication Server with multiple authentication providers for client_credentials

I am trying to setup an authentication server using Spring Security authentication and need to have multiple authentication providers for client_credentials.
I have done quite a bit of searching and have yet to find how to configure spring security to add my custom authentication provider to the client credentials authentication provider list. Every approach I found results in the same 2 providers for the client credentials authentication. The anonymous and the dao authentication providers.
I would appreciate any help in figuring out how to configure the the spring security authentication server for multiple client credential authentication providers.
AuthorizationServerConfig
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter
{
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(passwordEncoder())
.allowFormAuthenticationForClients();
}
#Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("sampleClientId").authorizedGrantTypes("implicit")
.scopes("read", "write", "foo", "bar")
.autoApprove(false)
.accessTokenValiditySeconds(3600)
.redirectUris("http://localhost:8083/")
.and()
.withClient("fooClientIdPassword")
.secret(passwordEncoder().encode("secret"))
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("foo", "read", "write")
.accessTokenValiditySeconds(3600) // 1 hour
.refreshTokenValiditySeconds(2592000) // 30 days
.redirectUris("xxx")
.and()
.withClient("barClientIdPassword")
.secret(passwordEncoder().encode("secret"))
.authorizedGrantTypes("client_credentials", "refresh_token")
.scopes("bar", "read", "write")
.resourceIds("kip-apis")
.accessTokenValiditySeconds(3600) // 1 hour
.refreshTokenValiditySeconds(2592000) // 30 days
.and()
.withClient("testImplicitClientId")
.autoApprove(true)
.authorizedGrantTypes("implicit")
.scopes("read", "write", "foo", "bar")
.redirectUris("xxx");
}
#Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain
.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.authenticationManager(authenticationManager)
.tokenServices(tokenServices())
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain);
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenEnhancer(accessTokenConverter());
return defaultTokenServices;
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
WebSecurityConfig:
#Configuration
#EnableWebSecurity( debug = true ) // turn off the default configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder passwordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().disable() // disable form authentication
.anonymous().disable() // disable anonymous user
.authorizeRequests().anyRequest().denyAll(); // denying all access
}
#Autowired
public void globalUserDetails(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("john").password(passwordEncoder.encode("123")).roles("USER").and()
.withUser("tom").password(passwordEncoder.encode("111")).roles("ADMIN").and()
.withUser("user1").password(passwordEncoder.encode("pass")).roles("USER").and()
.withUser("admin").password(passwordEncoder.encode("nimda")).roles("ADMIN");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
I have tried a few options for trying to add an additional authentication provider for the client credentials grant. Such as in the WebSecurityConfig ...
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(customDaoAuthenticationProvider);
}
It didn't work and when stepping through the authentication for client_credentials I didn't see the custom one added to the provider list, just the anonymous and dao authentication providers.
I was able to finally get the configuration of the spring security authentication server to a point where we can add multiple providers for client_credentials.
#Configuration
#EnableAuthorizationServer
public class AuthenticationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.addTokenEndpointAuthenticationFilter(clientCredentialsTokenEndpointFilter());
}
#Bean
protected ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() {
ClientCredentialsTokenEndpointFilter cctef = new CustomClientCredentialsTokenEndpointFilter();
cctef.setAuthenticationManager(clientAuthenticationManager());
return cctef;
}
#Bean
protected ProviderManager clientAuthenticationManager() {
return new ProviderManager(Arrays.asList(authProvider()));
}
#Bean
protected DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new CustomDaoAuthenticationProvider();
authProvider.setUserDetailsService(clientDetailsUserService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Bean
protected BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
protected UserDetailsService clientDetailsUserService() {
return new ClientDetailsUserDetailsService(clientDetailsService());
}
#Bean
protected ClientDetailsService clientDetailsService() {
return new ClientDetailsService() {
#Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
BaseClientDetails details = new BaseClientDetails();
details.setClientId("barClientIdPassword");
details.setClientSecret(passwordEncoder().encode("secret"));
details.setAuthorizedGrantTypes(Arrays.asList("client_credentials"));
details.setScope(Arrays.asList("read", "trust"));
details.setResourceIds(Arrays.asList("kip-apis"));
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_CLIENT"));
details.setAuthorities(authorities);
details.setAccessTokenValiditySeconds(3600); //1hr
details.setRegisteredRedirectUri(null);
return details;
}
};
}
#Bean
public AuthenticationEntryPoint oauthAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint aep = new OAuth2AuthenticationEntryPoint();
aep.setRealmName("theRealm");
return aep;
}
#Bean
public AuthenticationEntryPoint clientAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint aep = new OAuth2AuthenticationEntryPoint();
aep.setRealmName("theRealm/client");
return aep;
}
#Bean
public AccessDeniedHandler oauthAccessDeniedHandler() {
return new OAuth2AccessDeniedHandler();
}
}
In the clientAuthenticationManager we can now add our providers to the provider manager list.
I am not sure the is the completely correct method to get this working, but it does seem to allow us to do what we wanted.

Load JWT signature key from a dynamic base

I deployed an Authorization Server using AuthorizationServerConfigurerAdapter and the users and clients are configured from the implementation of the UserDetailsService and ClientDetailsService services that gather the required information in the database.
#Configuration
#EnableAuthorizationServer
public class OAuth2JwtAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private AppClientDetailsService clientDetailsService;
#Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService);
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
#Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.reuseRefreshTokens(false)
.userDetailsService(userDetailsService)
.authenticationManager(authenticationManager);
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
The Authorization Server is working properly, but I would like the signature key set in the accessTokenConverter () method to be loaded dynamically, when I receive the request for a new Token, I would access the database and modify the Signing Key at this point and return the JWT Token with this new modified signature, it is currently only being configured the moment the application is started.
You can define an #Autowired JwtAccessTokenConverter property and modify its key at any point
#Autowired
public JwtAccessTokenConverter tokenConverter;
public void setSigningKey(String key) {
tokenConverter.setSigningKey(key);
}

spirng boot 2 jwt oauth2 + angular 5 can't get the JWT

I'm new working with spring boot and spring security and I'm trying to implement oauth2 to generate a JWT and used this token in an angular5 application, my situation is that after implementation I can get the token if a use postman or curl but when I use my web client in angular I can't get the token.
this is what I did.
My login method is angular
login(username: string, password: string ) {
const params: HttpParams = new HttpParams();
const headers: Headers = new Headers();
params.set('username', 'GDELOSSANTOS');
params.set('password', 'ADMIN');
params.set('client_id', 'ADMIN');
params.set('client_secret', 'ADMIN');
params.set('grant_type', 'password');
params.set('scope', '*');
headers.set('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(Constante.BACKEND_TOKEN_REQUEST, {headers}, {params} ).subscribe
(res => this.setSession);
}
My authorization server
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private static final Logger logger = LogManager.getLogger(AuthorizationServerConfig.class);
#Value("${security.oauth2.resource.id}")
private String resourceId;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
logger.traceEntry();
clients
.inMemory()
.withClient(ConstanteUtil.Seguridad.CLIEN_ID)
.secret(Seguridad.CLIENT_SECRET)
.authorizedGrantTypes(Seguridad.GRANT_TYPE_PASSWORD, Seguridad.AUTHORIZATION_CODE, Seguridad.REFRESH_TOKEN, Seguridad.IMPLICIT )
.authorities(UsusarioRoles.ROLE_ADMIN, UsusarioRoles.ROLE_USER)
.resourceIds(resourceId)
.scopes(Seguridad.SCOPE_READ, Seguridad.SCOPE_WRITE, Seguridad.TRUST)
.accessTokenValiditySeconds(Seguridad.ACCESS_TOKEN_VALIDITY_SECONDS).
refreshTokenValiditySeconds(Seguridad.FREFRESH_TOKEN_VALIDITY_SECONDS);
logger.info("Configuracion " + clients);
logger.traceExit();
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
#Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.authenticationManager(authenticationManager);
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
}
My Resource Server
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final Logger logger = LogManager.getLogger(AuthorizationServerConfig.class);
#Value("${security.oauth2.resource.id}")
private String resourceId;
#Override
public void configure(final HttpSecurity http) throws Exception {
logger.traceEntry("Entrada configure");
// #formatter:off
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests().anyRequest().permitAll();
logger.info("Ejecucion de metodo " + http);
// #formatter:on
}
#Override
public void configure(final ResourceServerSecurityConfigurer config) {
config.resourceId(resourceId).stateless(true); }
}
The WebSecurity
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LogManager.getLogger(WebSecurityConfig.class);
#Autowired
#Resource(name = "UsuarioService")
private UserDetailsService userDetailsService;
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
logger.traceEntry("globalUserDetails", auth);
auth.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
logger.traceExit("globalUserDetails", auth);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
logger.traceEntry();
logger.info("ejecutando configuracion " + http);
http.cors().disable()
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/login", "/logout.do").permitAll()
.antMatchers("/**").authenticated()
.and().formLogin().loginPage("/login").permitAll()
.and().httpBasic();
logger.info("se ejecuto configuracion " + http);
}
#Bean
public BCryptPasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
#Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/auth/token").allowedOrigins("http://localhost:9000");
}
};
}
}
The implementation of loadUserDetail of UserDetailService
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
logger.traceEntry("Iniciando loadUserByUsername");
/Here we are using dummy data, you need to load user data from
database or other third party application/
try {
Usuario usuario = findAllUsuarioRoleByName(username);
logger.info("Se encontro el usaurio " + usuario);
UserBuilder builder = null;
if (usuario != null) {
List<String> roles = new ArrayList<>();
Collection<UsuarioRole> usuarioRoleByUsuarioName = usuarioRoleRepository.findAllUsuarioRoleByUsuarioName(usuario.getNombreUsuario());
logger.info("Roles encontrados " + usuarioRoleByUsuarioName.size());
for(UsuarioRole usuarioRole : usuarioRoleByUsuarioName) {
roles.add(usuarioRole.getRole().getNombreRole());
}
String[] rolesArray = new String[roles.size()];
rolesArray = roles.toArray(rolesArray);
builder = org.springframework.security.core.userdetails.User.withUsername(username);
builder.password(new BCryptPasswordEncoder().encode(usuario.getClaveUsuario()));
for (String string : rolesArray) {
logger.debug("**** " + string);
}
builder.roles(rolesArray);
} else {
throw new UsernameNotFoundException("User not found.");
}
return builder.build();
}finally {
logger.traceExit("Finalizando loadUserByUsername");
}
}
Make the following adjustments to your angular code.
Pass client_id and client_secret through Authorization header.
Serialize the object before post (you can reference this answer).
login(username: string, password: string ) {
let body = {
username: 'GDELOSSANTOS',
password: 'ADMIN',
grant_type: 'password'
};
// Serialize body object
let bodySerialized = 'grant_type=password&password=ADMIN&username=GDELOSSANTOS';
let headers = new HttpHeaders()
.set('Content-Type', 'application/x-www-form-urlencoded')
.set('Authorization', 'Basic ' + btoa("ADMIN:ADMIN"));
return this.http.post(Constante.BACKEND_TOKEN_REQUEST,
bodySerialized,
{
headers: headers
}).subscribe(res => this.setSession);
}

Can spring have multiple ConfigurerAdapter?

I need to add OAuth2 security using an ldap authentication.
I have first implemented ldap authenication and add a WebSecurityConfigurerAdapter instance.
#Configuration
#EnableWebSecurity
#Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.contextSource().url("ldaps://master:636/dc=domain,dc=com")
.managerDn("cn=readonly,dc=domain,dc=com").managerPassword("123456")
.and()
.userSearchFilter("(uid={0})");
}
}
I need to add OAuth2 resource server adapter ResourceServerConfigurerAdapter
#Configuration
#Import({ DatabaseConfig.class })
#EnableResourceServer
#Order(1)
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired DatabaseConfig databaseConfig;
#Override
public void configure(final HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests()
.anyRequest().authenticated();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
// converter.setSigningKey("123");
final Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(databaseConfig.dataSource());
}
It seems like WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter conflicting when both configured.
I am playing with both configure() method but I can only get an access login through ldap using http://localhost:8080/login on my Rest API, and couldn't using my angular client using oauth http://localhost:8081/login
I have the following error when trying to access the resource:
Failed to find refresh token for token eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJqb2huIiwic2NvcGUiOlsiZm9vIiwicmVhZCIsIndyaXRlIl0sIm9yZ2FuaXphdGlvbiI6ImpvaG5vRnZiIiwiYXRpIjoiNDcyZTJiNDYtZjgxZS00NGJiLWEwNDMtMGYwZmRjMDMzY2U1IiwiZXhwIjoxNDc2NTQ5NjYzLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiN2UwNzRkZDktOWI0ZC00MTU0LWJjMzktMDlkY2U4Y2UyZTg2IiwiY2xpZW50X2lkIjoiZm9vQ2xpZW50SWRQYXNzd29yZCJ9.fuarTPL1O00Yg6b3BPibwux1ZtlmrHaPCJkgjsJni_51B3NEHkdB9kqbABK3IkMWMlZdqY8xfR-zMpY9SxFkpRFDfyvosgLcsTZ...
Handling error: InvalidGrantException, Invalid refresh token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVC...
I have the same issue. May be my solution is not graceful, but it works for me.
I had tried OAuth2ResourceServerConfig which extends WebSecurityConfig and implements ResourceServerConfigurer.
Your OAuth2ResourceServerConfig must be like this
#Configuration
#Import({ DatabaseConfig.class })
#EnableResourceServer
#Order(1)
public class OAuth2ResourceServerConfig extends WebSecurityConfig implements ResourceServerConfigurer {
#Autowired DatabaseConfig databaseConfig;
#Override
public void configure(final HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests()
.anyRequest().authenticated();
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
// converter.setSigningKey("123");
final Resource resource = new ClassPathResource("public.txt");
String publicKey = null;
try {
publicKey = IOUtils.toString(resource.getInputStream());
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey);
return converter;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(databaseConfig.dataSource());
}
According this post, I think you can use the previous version by adding this to you config(yml or properties):
security:
oauth2:
resource:
filter-order: 3
And I tried adding #Order annotation to my source server config as you did, and get the same issue. So, I think #Order annotation doesn't take effect to ResourceServerConfigurerAdapter, but it works fine with WebSecurityConfig. I don't know is it a bug or intended.

Resources