I have a web service that I have built on top of Spring. I am currently authenticating using Spring Security as follows:
#Configuration
#EnableGlobalMethodSecurity(securedEnabled=true)
#EnableWebSecurity
public class ServerSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private Properties properties;
private static final String ALL_URI = "/v1/**";
private static final String HEALTH_URI = "/v1/healthCheck";
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(getFilter(), BasicAuthenticationFilter.class);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests()
.antMatchers(HEALTH_URI).permitAll()
.anyRequest().authenticated();
http.csrf().disable();
}
private AuthenticationFilter getFilter() {
return new AuthenticationFilter( properties.getKey());
}
}
My AuthenticationFilter class extends AbstractAuthenticationProcessingFilter and performs the actual authentication. If I want to add Authorization to my security, would I just make those checks in the attemptAuthentication method apart of the AuthenticationFilter? Or is there a better way to do it? The way I understand it is that Authorization and Authentication should be done independently. You first authenticate, and then you verify the permissions. So, I would assume there would be a better approach to do authorization within Spring Security rather than just adding it to the attemptAuthentication method.
You need a AuthenticationProvider to do authenticate, implement the AuthenticationProvider and override the authentication and supports methods, and then inject to the AuthenticationManager.
attemptAuthentication method in filter is usually to get authentication(e.g. UsernamePasswordFilter gets username and password from request, and then builds a UsernamePasswordAuthenticationToken to AuthenticationManager ),
supports method tests the AuthenticationProvider whether can be used to do authenticate.(e.g DaoAuthenticationProvider supports UsernamePasswordAuthenticationToken)
authenticate method is used to do authenticate(e.g DaoAuthenticationProvider gets the real password by username and then compare to the user input), this method should return an Authentication that is already authenticated(e.g UsernamePasswordAuthenticationToken), and this authentication should contains the user authorities(this can be used to hasRole('xxx')), or use detail and so on.
After attemptAuthentication successful, the Authentication will set into SecurityContextHolder. and then you can use the hasRole('xx'), or something else.
Related
Moin!
I use Spring Security 5 with Kerberos for the SSO authentication in my project.
In the WebSecurityConfig I register two AuthenticationProvider
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(msfUserDetailsService).passwordEncoder(passwordEncoder());
assertThatUnlimitedCryptographyEnabled();
// Two providers
auth.authenticationProvider(kerberosAuthenticationProvider());
auth.authenticationProvider(kerberosServiceAuthenticationProvider());
}
This seems to be the way its done as seen in these two examples:
https://docs.spring.io/spring-security-kerberos/docs/current/reference/html/ssk-spnego.html
https://www.ebayinc.com/stories/blogs/tech/customizing-spring-security-with-multiple-authentications/
However I don't see why I need both of them. During authentication the KerberosServiceAuthenticationProvider is the one that is validating Kerberos tickets (see JavaDoc)
However what is the KerberosAuthenticationProvider for? The JavaDoc in this case just says
AuthenticationProvider for kerberos.
As you said: KerberosServiceAuthenticationProvider is used to validate tickets in SSO authentication, whereas KerberosAuthenticationProvider is used for form based authentications, which are usually used as a fallback when SSO is not supported on client side (e.g. browsers on linux systems). This type of authentication is handled by UsernamePasswordAuthenticationFilter which is applied in WebSecurityConfigurerAdapter:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
...
.formLogin()
...
}
...
}
If you do not use form login then you can omit this provider as pointed in comments.
Whats are the difference between these classes? I know that WebSecurityConfigurerAdapter is used to customize "security" on our apps.
Whats I've done:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
CustomUserDetailsService customUserDetailsService;
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
But i don't understand the meaning of AuthorizationServerConfigurerAdapter.
I read a couple of articles but I don't get it.
One thing first. OAuth 2 is an authorization framework. It allows an application (client) to obtain limited access to a HTTP service on behalf of a resource owner (user). OAuth 2 is not an authentication protocol.
AuthorizationServerConfigurerAdapter is used to configure how the OAuth authorization server works.
Here are some aspects which can be configured:
supported grant types (e.g. authorization code grant)
authorization code service, to store authorization codes
token store, to store access and refresh tokens (e.g. JwtTokenStore)
client details service, which holds the client configurations
...
WebSecurityConfigurerAdapter is used to configure how the OAuth authorization server is secured.
Or in other words, how the user has to authenticate to grant a client access to his resources.
This can be:
form authentication
authentication via an identity provider (Facebook Login)
...
(I have intentionally omitted some details to keep the answer as simple as possible.)
Example authorization server configuration with an in-memory token store:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore());
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
...
}
Example security configuration with form login:
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/oauth/authorize").authenticated()
.and()
.formLogin();
}
...
}
if you want to use a third party authenticater, this means at the same time OAuth, then you must use AuthorizationServerConfigurerAdapter with WebSecurityConfigurerAdapter at OAuth serverside. If not so, WebSecurityConfigurerAdapter is enough for ordinary authentication
I'm trying to implement a simple spring boot project. I got several REST-Endpoints which I've to secure differently. One has to be secured by Basic Auth, another one with OAuth and one with a custom security implementation.
REST-Endpoints:
/basic/auth
/application/secure (oauth)
/application/secure2 (own implementation)
From tutorials, I know I've to set the order of the security adapters. My first intention was to set the order in steps of ten (e.g. #Order(10), #Order(20)) in case I need to add other security filters in between. By doing so I investigated the following behavior:
If I add the basic auth filter with #Order(10) and an OAuth filter with #Order(20) only the OAuth filter works.
If I add the basic auth filter with #Order(1) or #Order(2) and an OAuth filter with #Order(4) both filters works.
If I add a filter to #Order(3) I receive an error which says, that order 3 is already in use and cannot be configured twice.
So there is a default spring security adapter (or whatever) which has the default order 3. I thought I disable every default spring security behavior by adding #EnableWebSecurity. After I did not find an answer by google my questions would be:
Am I doing the right things?
What is this security adapter with order 3 by spring?
Does the default security adapter block my basic auth implementation?
WebSecurityConfig:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Order(10)
#Configuration
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {
#Value("${security.user.password}")
private String password;
#Value("${security.user.name}")
private String username;
private static final String ROLE_ADMIN = "ADMIN";
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(username).password(password).roles(ROLE_ADMIN);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.requestMatchers().antMatchers("/basic/**", "/") //
.and().authorizeRequests().anyRequest().authenticated() //
.and().httpBasic();
}
}
#Order(20)
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class Oauth2ServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
System.out.println("Filter called");
// #formatter:off
http.csrf().disable();
http.authorizeRequests().antMatchers("/application/**").authenticated()
// .antMatchers(GET, "/application/secure").authenticated()
.anyRequest().authenticated();
// #formatter:on
}
// offline token validator
}
This is an old question, but if anyone is still wondering what the issue is, here are my observations:
#EnableResourceServer imports ResourceServerConfiguration, which has an order of 3.
There are ways that may allow you to add more than 2 filters before the order 3 resource server configurer, for instance
by giving some of them negative order values (Although I don't suppose negative values would be any special, one would need to take into account other implicit web security configurers -- for instance the one with order 0 -- enabled by default. This however means there is a possibility of collision between filters in different versions of the framework as new features are introduced);
by adding them as resource configurers (The ResourceServerConfiguration class does not add any request matchers, but enforces a fallback to anyRequest().authenticated() if the user has not configured anything).
For a better understanding on how paths are matched in the configured request matchers, you can take a quick glance at Ant path patterns.
I was working on security layer in my Spring Boot project and faced with the following problem:
SecurityContextHolder.getContext().getAuthentication()
This code returns:
String "anonymousUser" for Anonymous user
UserDetails object for authenticated user
So, I want to configure this code to return UserDetails for both cases. How can I do it?
As I guess, I need to implement custom AnonymousAuthenticationFilter. Am I correct?
As I guess, I need to implement custom AnonymousAuthenticationFilter.
Am I correct?
There is a simpler approach and that's the anonymous() method of the HttpSecurity DSL. Just use that block to set your desired principal:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// other configuration methods
#Override
protected void configure(HttpSecurity http) throws Exception {
UserDetails anonymousUserDetails = // your custom UserDetails for anonymous case
http
// other configurations
.anonymous()
.principal(anonymousUserDetails);
}
}
Using a Null Object Pattern-ish approach may be a good idea for that custom implemention for anonymous user.
How can I pass request specific information to an AuthenticationProvider from a Filter without creating a custom Authentication ?
The AuthenticationProvider signature is as below:
interface AuthenticationProvider {
Authentication authenticate(Authentication authentication);
}
I'm thinking something similar to the static SecurityContextHolder.getContext().getAuthentication() but with request specific information.
Background
The reason I want it is because I want to implement a switching authentication provider that delegates in runtime to another AuthenticationProvider
public class SwitchingAuthenticationProvider implements AuthenticationProvider {
private AuthenticationProvider[] authProviders = // ...
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return authProvider[GetCurrentContext.getIndex()].authenticate(authentication);
}
}
You can provide your own implementation of AuthenticationEntryPoint which have access to HttpServletRequest. In AuthenticationEntryPoint implementation put all attribute that you need in your switching AuthenticationProvider, in RequestContextHolder as given below
RequestContextHolder.currentRequestAttributes().setAttribute(attributeName, attibuteValue, scope);
At the end you can retrieve these attribute in your authentication provider as given below
RequestContextHolder.currentRequestAttributes().getAttribute(attributeName,scope);