Spring security oauth2.0 restful and Form login config - spring

I have a app that could login with from or by oauth2 alos.
But I met some troubles.
What I met:
When I visit http://127.0.0.1/, it truns to /login page what is right.
When I visit http://127.0.0.1/api/hellos, it also truns to /login page what is exactly wrong. What I want is I can access /api/hellos by using oauth2.
Here is my Security Configuration:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private SpringDataMyBatisUserDetailsService userDetailsService;
#Override
#Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(this.userDetailsService)
.passwordEncoder(Manager.PASSWORD_ENCODER);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
}
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
#Autowired
private TokenStore tokenStore;
#Autowired
private SpringDataMyBatisClientDetailsService clientDetailsService;
#Autowired
public AuthorizationServerConfig(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
/**
* Defines the security constraints on the token endpoints /oauth/token_key and /oauth/check_token
* Client credentials are required to access the endpoints
*
* #param oauthServer
* #throws Exception
*/
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
/**
* Defines the authorization and token endpoints and the token services
*
* #param endpoints
* #throws Exception
*/
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(this.authenticationManager)
.tokenEnhancer(tokenEnhancer())
.tokenStore(tokenStore);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.withClientDetails(clientDetailsService);
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
}
#Order(1)
#Configuration
public class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/index.html", "/index.css", "/common.js", "/index.js", "/api/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout()
.logoutSuccessUrl("/")
.and().exceptionHandling().accessDeniedPage("/error/403");
}
}
#Configuration
#EnableResourceServer
#Order(2)
public class AuthorizationResourceConfig extends ResourceServerConfigurerAdapter {
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Autowired
private AuthenticationSuccessHandler successHandler;
#Autowired
private AuthenticationFailureHandler failureHandler;
#Autowired
private TokenStore tokenStore;
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.stateless(true)
.tokenStore(tokenStore);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.and()
.anonymous().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().httpBasic()
.and()
.exceptionHandling()
.accessDeniedHandler(new OAuth2AccessDeniedHandler())
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated();
}
}
}
I have tried some ways where I searched from google.But none can help me.
So, I really want someone can help me, I will be appreciated for you.
In addition, the most helpful info I have searched is this.

u use this ".antMatchers("/api/**").fullyAuthenticated(); " ,, in this case will require a "LOG IN " for all actions /api/.... ,, if u dont Want"log in" form for "127.0.0.1/api/hellos "u must to use only /api/ without stars

Related

Spring security oauth2 always returning 403

I have a Spring boot app serving Rest endpoints which I'm securing using Spring security and Oauth2.
I want to secure all my endpoints except the endpoints used to authenticate, to create an account or some info stuff.
The security configuration is like this :
#Configuration
#EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private MongoTokenStore tokenStore;
#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);
clients.inMemory().withClient("app").secret("password")
.accessTokenValiditySeconds(30000).authorizedGrantTypes("password", "refresh_token")
.refreshTokenValiditySeconds(300000000)
.scopes("read");
}
#Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager)
.pathMapping("/oauth/confirm_access", "/access_confirmation");
}
#Bean
public TokenStore tokenStore() {
return this.tokenStore;
}
}
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserRepository userRepository;
#Autowired
private SecurityContextService securityContextService;
#Autowired
private MongoTemplate mongoTemplate;
#Bean
public MongoUserDetailsManager mongoUserDetailsManager() throws Exception {
return new MongoUserDetailsManager(userRepository, securityContextService, authenticationManagerBean(), mongoTemplate);
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManagerBean())
.userDetailsService(mongoUserDetailsManager());
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/login", "/oauth/authorize", "/oauth/token", "/server/version", "/clients/register").permitAll()
.and().csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.disable();
}
}
I can access to token endpoint to get my access_token, but I want to access to other secured endpoints using this access_token (by adding the Authorization:Bearer {access_toke} to the header), I always get HTTP 403.
Did I miss something? I'm not supposed as authorized if I add the Authorization header?
My Controllers are only annotated with these #RestController, #CrossOrigin
and #RequestMapping("/url")
There are 2 types of security configurations in case of OAuth security(as far as urls security is concerned) in Spring.
1. Basic Security Configuration
This class should implement WebSecurityConfigurerAdapter. It will handle all those requests coming without "Bearer" token type(urls that shouldn't be oauth protected).
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserRepository userRepository;
#Autowired
private SecurityContextService securityContextService;
#Autowired
private MongoTemplate mongoTemplate;
#Bean
public MongoUserDetailsManager mongoUserDetailsManager() throws Exception {
return new MongoUserDetailsManager(userRepository, securityContextService, authenticationManagerBean(), mongoTemplate);
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManagerBean())
.userDetailsService(mongoUserDetailsManager());
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/login", "/oauth/authorize", "/oauth/token", "/server/version", "/clients/register").permitAll()
.and().csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.disable();
}
}
2. Resource Server Configuration(OAuth Specific)
This class is responsible for handling all those requests coming with authorization header of type Bearer. It should be extended from ResourceServerConfigurerAdapter class. Here you should mention all those urls with security configurations that you like to be oauth protected.
#Configuration
#EnableResourceServer
public class OAuthResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/resources-to-be-protected/**").and().authorizeRequests()
.antMatchers("/resources-to-be-protected/**").access("#oauth2.isClient()");
}
}

Spring Security using Oauth | Overriding HttpSecurity

I am Implementing Spring Security using Oauth following these websystique , baeldung,What I found WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter both provides control over HttpSecurity,and filterchain adds them in order 0 and 3 respectively.
So I am overriding configure of any of the above ConfigurerAdapter but only one at a time.
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.requestMatchers().antMatchers("/api/**").and()
.authorizeRequests()
.antMatchers("/api/ads").permitAll()
.antMatchers("/api/admin").hasAuthority(RoleConstant.ADMIN.getRole())
.antMatchers("/api/user").hasAuthority(RoleConstant.USER.getRole())
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
What I observe in case of WebSecurityConfigurerAdapter I am able to access unauthorized resources ie I am able to access /api/user after being authenticated even with token having authority ADMIN.Why so?
Note : I am not overriding HttpSecurity of ResourceServerConfigurerAdapter.
References : There are similar resources available here. Resource1 , Resource2.
Also I want to know,I must have to override both configure(HttpSecurity http) or any of the class is sufficient?If yes,which one is recommended?
ResourceServer :
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.requestMatchers().antMatchers("/api/**").and()
.authorizeRequests()
.antMatchers("/api/ads").permitAll()
.antMatchers("/api/admin").hasAuthority(RoleConstant.ADMIN.getRole())
.antMatchers("/api/user").hasAuthority(RoleConstant.USER.getRole())
.antMatchers("/api/readProperty").access("hasRole('ADMIN')")
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
SpringSecurityConfig :
#Configuration
#EnableWebSecurity
#ComponentScan(basePackages = {"com.ttnd.mvc_mod.services","com.ttnd.mvc_mod.repository","com.ttnd.mvc_mod.config","com.ttnd.mvc_mod.custom"})
#Import({SpringORMHibernateSupportConfig.class})
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
private CustomAuthenticationProvider authProvider;
/* #Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.requestMatchers().antMatchers("/**").and()
.authorizeRequests()
.antMatchers("/oauth/token","/api/ads").permitAll()
.antMatchers("/api/admin").hasAuthority(RoleConstant.ADMIN.getRole())
.antMatchers("/api/user").hasAuthority(RoleConstant.USER.getRole())
.antMatchers("/api/readProperty").access("hasRole('ADMIN')")
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());//.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint);
}
*/
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//auth.userDetailsService(customUserDetailsService);
auth.authenticationProvider(authProvider);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#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;
}
}

How to use WebSecurity adapter with Spring-Security-OAuth2

I am trying to achieve authentication system using OAuth2 as well as simple Spring Security(Web Security adapter). But as I am trying to configure, I am not able to use both the services together. As per configuration file code shared below, But It will work either OAuth2 or simple auth using spring security(Web Security adapter). I want both the authentication system should work based on URL identification.
Thanks in advance!
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, proxyTargetClass = true)
public class ConfigurationClass {
// Its working as simple auth spring security
#EnableWebSecurity
#Configuration
#Order(1)
protected static class StatelessAuthenticationSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private TokenAuthenticationService tokenAuthenticationService;
#Autowired
private OtpManage OtpManage;
#Autowired
private RoleRepository RoleRepository;
public StatelessAuthenticationSecurityConfig() {
super(true);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// allow anonymous resource requests
.antMatchers("/").permitAll()
// allow anonymous POSTs to login
.antMatchers(HttpMethod.POST, "/user/registration").permitAll()
.antMatchers(HttpMethod.POST, "/user/changepassword").permitAll()
.antMatchers(HttpMethod.POST, "/user/resetpassword").permitAll()
// .antMatchers(HttpMethod.POST,
// "/api/otpResetPassword").permitAll()
.antMatchers(HttpMethod.POST, "/user/saveusergroup").permitAll()
.antMatchers(HttpMethod.POST, "/user/bugreport").permitAll()
.antMatchers(HttpMethod.POST, "/user/createtoken").permitAll()
// .anyRequest().authenticated().and()
.anyRequest().hasAnyRole("USER","SYSTEM_ADMIN","ADMIN").and()
// custom JSON based authentication by POST of
// {"username":"<name>","password":"<password>"} which sets the
// token header upon authentication
.addFilterBefore(new StatelessLoginFilter("/api/login", tokenAuthenticationService, userDetailsService,
authenticationManager(), OtpManage), UsernamePasswordAuthenticationFilter.class)
// custom Token based authentication based on the header
// previously given to the client
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService),
UsernamePasswordAuthenticationFilter.class);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected UserDetailsService userDetailsService() {
return userDetailsService;
}
}
// Its not working, But if I removed #Order(1) annotation from StatelessAuthenticationSecurityConfig class then this one will work as default
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
#Autowired
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
#Override
public void configure(HttpSecurity http) throws Exception {
System.out.println("#EnableResourceServer");
http
.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint)
.and()
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler(customLogoutSuccessHandler)
.and()
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
.disable()
.headers()
.frameOptions().disable().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/hello/").permitAll()
.antMatchers("/secure/**").authenticated();
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware {
private static final String ENV_OAUTH = "authentication.oauth.";
private static final String PROP_CLIENTID = "clientid";
private static final String PROP_SECRET = "secret";
private static final String PROP_TOKEN_VALIDITY_SECONDS = "tokenValidityInSeconds";
private RelaxedPropertyResolver propertyResolver;
#Autowired
private DataSource dataSource;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
System.out.println("#AuthorizationServerConfigurerAdapter");
clients
.inMemory()
.withClient(propertyResolver.getProperty(PROP_CLIENTID))
.scopes("read", "write")
.authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
.authorizedGrantTypes("password", "refresh_token")
.secret(propertyResolver.getProperty(PROP_SECRET))
.accessTokenValiditySeconds(propertyResolver.getProperty(PROP_TOKEN_VALIDITY_SECONDS, Integer.class, 1800));
}
#Override
public void setEnvironment(Environment environment) {
this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH);
}
}
}
Update:
I have made few changes to my code with #EnableOAuth2Client, #Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) and I have achieved what exactly I want to do. But now the issue is I am not able call to post url: "/api/login" with user credentials. I am getting error as url not found. as per my code in WebSecurityConfig class, I have added filter in configure(HttpSecurity http) method for loginFilter class which extends AbstractAuthenticationProcessingFilter. But this filter which is mapped with "/api/login" url not working at all. Why this one filter is not working I don`t understand. Someone could you help me regarding the same.
#WebSecurityConfigClass
/**
* Implementation of HttpSecurity configure method
* Implementation custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
* #author Santosh
*
*/
#EnableOAuth2Client
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled = true, proxyTargetClass = true)
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private TokenAuthenticationService tokenAuthenticationService;
#Autowired
private MessageSource messages;
#Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
#Autowired
private RESTAuthenticationSuccessHandler restAuthenticationSuccessHandler;
#Autowired
private RESTAuthenticationFailureHandler restAuthenticationFailureHandler;
#Autowired
private CustomAccessDeniedHandler accessDeniedHandler;
public WebSecurityConfig() {
super(true);
}
/*#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
auth.inMemoryAuthentication().withUser("testUser").password("testUser").roles("USER");
}
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
// setup security
http
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.authorizeRequests()
.anyRequest()
.fullyAuthenticated()
.and().httpBasic();
http
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.anonymous().and()
.servletApi().and()
.headers().and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.and()
.authorizeRequests()
.anyRequest().hasAnyRole("USER").and()
//all other request need to be authenticated
// custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
.addFilterBefore(new LoginFilter("/api/login", tokenAuthenticationService, userDetailsService, authenticationManager(), restAuthenticationSuccessHandler, restAuthenticationFailureHandler), UsernamePasswordAuthenticationFilter.class)
// custom Token based authentication based on the header previously given to the client
.addFilterBefore(new ApplicationFilter (tokenAuthenticationService, messages), UsernamePasswordAuthenticationFilter.class);
}
// To allow Pre-flight [OPTIONS] request from browser
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
web.ignoring()//allow anonymous GETs to API
.antMatchers(HttpMethod.GET, "/api/status/**");
}
#Bean
public RequestContextListener requestContextListener(){
return new RequestContextListener();
}
#Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
#Bean
public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint(){
return new CustomBasicAuthenticationEntryPoint();
}
#Bean(name="authenticationManagerBean")
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
#OAuth2ServerConfiguration
#Configuration
public class OAuth2ServerConfiguration {
private static final String RESOURCE_ID = "restservice";
private static final String ROLE_ADMIN = "ADMIN";
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private CustomOAuth2AccessDeniedHandler accessDeniedHandler;
#Autowired
private RESTOAuth2AuthenticationEntryPoint restAuthenticationEntryPoint;
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/hello").permitAll()
.antMatchers("/users/current/**","/oauth/token","/oauth/authorize","/oauth/refresh_token").permitAll()
.antMatchers("/api/greeting").authenticated().and().exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(restAuthenticationEntryPoint);
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private DataSource dataSource;
#Autowired
private TokenStore tokenStore;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
// #Autowired
// private UserApprovalHandler userApprovalHandler;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(this.tokenStore).authenticationManager(this.authenticationManager)
.userDetailsService(userDetailsService);
// .userApprovalHandler(userApprovalHandler)
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// jdbc(dataSource)
clients.inMemory().withClient("clientapp").authorizedGrantTypes("password", "refresh_token")
.authorities("USER").scopes("read", "write").resourceIds(RESOURCE_ID).secret("123456")
.accessTokenValiditySeconds(20)// Access token is only valid
// for 2 minutes.
.refreshTokenValiditySeconds(1200);// Refresh token is only
// valid for 10
// minutes.;
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(this.tokenStore);
return tokenServices;
}
}
}
On your WebSecurityAdapter you want to build requestMatchers to determine on which requests that instance of HttpSecurity will invoke.
For example :
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/secure/path", "/more/secure/path");
// Rest of your configuration.
}

Get AccessToken when Login in from OAuth2 LoginFrom

I'm using spring OAuth2 loginForm and access_token way to authenticate. But when I login in, I can not get access to resource server which needs access_token authorization.
How can I get access_token when I login in?
Should I create access_token by myself manually?
What I config with spring security is:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private SpringDataMyBatisUserDetailsService userDetailsService;
#Override
#Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(this.userDetailsService)
.passwordEncoder(Manager.PASSWORD_ENCODER);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(
"/druid/**",
"/images/**"
);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
}
#Order(1)
#Configuration
#EnableAuthorizationServer
public static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
#Autowired
private TokenStore tokenStore;
#Autowired
private SpringDataMyBatisClientDetailsService clientDetailsService;
#Autowired
public AuthorizationServerConfig(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
/**
* Defines the security constraints on the token endpoints /oauth/token_key and /oauth/check_token
* Client credentials are required to access the endpoints
*
* #param oauthServer
* #throws Exception
*/
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
// .passwordEncoder(Client.PASSWORD_ENCODER)
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
/**
* Defines the authorization and token endpoints and the token services
*
* #param endpoints
* #throws Exception
*/
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(this.authenticationManager)
.tokenEnhancer(tokenEnhancer())
.tokenStore(tokenStore);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.withClientDetails(clientDetailsService);
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
}
#Order(3)
#Configuration
#EnableResourceServer
public static class ApiResources extends ResourceServerConfigurerAdapter {
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Autowired
private AuthenticationSuccessHandler successHandler;
#Autowired
private AuthenticationFailureHandler failureHandler;
#Autowired
private TokenStore tokenStore;
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.tokenStore(tokenStore);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(successHandler)
.failureHandler(failureHandler)
.and()
.logout();
}
}
#Order(4)
#Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/authention/login")
.defaultSuccessUrl("/", true)
.failureUrl("/authention/login?error")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/authention/login?success")
.and()
.sessionManagement()
.sessionFixation().migrateSession();
}
}
#Bean
public static AuthenticationSuccessHandler myAuthenticationSuccessHandler() {
return new SavedRequestAwareAuthenticationSuccessHandler();
}
#Bean
public static AuthenticationFailureHandler myAuthenticationFailureHandler() {
return new SavedRequestAwareAuthenticationFailureHandler();
}
}
When you configure spring-oauth in your app you can access REST APIs to get the tokens, revoke tokens etc.
See this link For basic oauth configuration for a spring boot application. And also go through the API reference
Sample OAuth2AuthorizationServerConfig :
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("hello")
.authorizedGrantTypes("password", "refresh_token")
.authorities("ROLE_APP")
.scopes("read", "write")
.secret("secret");
}
}
And the SecurityConfig class:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#ComponentScan(basePackages = {"com.test.config"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable();
http
.authorizeRequests()
.anyRequest().access("#oauth2.hasScope('read')")
.and()
.exceptionHandling()
.authenticationEntryPoint(oauthAuthenticationEntryPoint())
.accessDeniedHandler(oAuth2AccessDeniedHandler());
http
.formLogin()
.loginPage("/login")
.failureUrl("/")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login")
.permitAll();
}
}
After you configure your application. You can access the REST API as below.
For getting the token you need to access this URL:
localhost:8080/oauth/token?grant_type=password&client_id=hello&client_secret=secret&username=admin&password=password
This will authenticate the user if it is successful then the token is generated as shown below:
{
"access_token": "0307d70f-e3da-40f4-804b-f3a8aba4d8a8",
"token_type": "bearer",
"refresh_token": "daf21f97-f425-4245-8e47-19e4c87000e8",
"expires_in": 119,
"scope": "read write"
}
After getting this token you can access the REST APIs of your application just by passing this token. For example, if you have a URL "/hello" then
put a request appending the token which you obtained through above step.
"http://localhost:8080/hello?access_token=0307d70f-e3da-40f4-804b-f3a8aba4d8a8"

Spring OAuth2 additional permision

I need to add additional restriction to authenticate users. My User model has a field 'active'. It is false, when User registers, but not activate his account with hash from mail. Now, even if User is not active he gets access_token from Oauth.
How should I configure this?
I was thinking about SpringSecurityInterceptor, but I'm not sure about confusing Spring Security with OAuth2.
This is my SpringOAuth2.0 configuration:
#Configuration
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
private static final String RESOURCE_ID = "restservice";
#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
.requestMatcher(new OrRequestMatcher(
new AntPathRequestMatcher("/rest/**")
))
.authorizeRequests()
.anyRequest().access("#oauth2.hasScope('read')");
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends
AuthorizationServerConfigurerAdapter {
private TokenStore tokenStore = new InMemoryTokenStore();
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Autowired
UserDetailsService userDetailsService;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.tokenStore(this.tokenStore)
.authenticationManager(this.authenticationManager)
.userDetailsService(userDetailsService)
.pathMapping("/oauth/token", "/rest/oauth/token");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("clientapp")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("USER")
.scopes("read", "write", "trust")
.resourceIds(RESOURCE_ID)
.secret("123456");
}
}
}
And also Spring security
#Configuration
#Order(2147483640)
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
#Autowired
UserDetailsService userDetailsService;
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/user/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("email")
.passwordParameter("password")
.defaultSuccessUrl("/user/")
.successHandler(successHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.rememberMe()
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(86400)
.and()
.csrf().disable();
}
#Bean
public AuthenticationSuccessHandler successHandler() {
return new UserLoginSuccessHandler();
}
#Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
tokenRepositoryImpl.setDataSource(dataSource);
return tokenRepositoryImpl;
}
#Bean
public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
}
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Any advice would be helpful.
If I understand you correctly, you don't want your authorization server to grant an access token for a user that is not activated?
You could let your UserDetailsService.loadUserByUsername throw a UsernameNotFoundException if the user exists, but is not activated.

Resources