In my application I am using multiple authentication handlers like application DB, LDAP and SAML. Now after successful authentication I am using CustomAuthenticationSuccessHandler.java which extends SimpleUrlAuthenticationSuccessHandler class which will be called after successful authentication. My question is how to get information about which handler has a successful authentication. I need this information because if it is an external user (LDAP, SAML) then I have to write a logic to replicate the user in application DB.
My configuation in configure global method:
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
auth
.ldapAuthentication()
.ldapAuthoritiesPopulator(ldapAuthoritiesPopulator)
.userDnPatterns("uid={0},ou=people")
.userDetailsContextMapper(ldapUserDetailsContextMapper)
.contextSource(getLDAPContextSource());`
You can set the info to authentication detail when do authenticated, or you can use different Authentication instances, e.g UsernamePasswordAuthenticationToken for DB and LDAP(maybe need to create a new Authentication to separate them), SAMLAuthenticationToken for SAML.
Related
Given a hypothetical application which uses Spring Session to store session information and:
There are more than one way of initiating a session and authenticating, i.e. different endpoints that can be hit depending on how the user is "logging in".
All of the endpoints a user can use for authentication result in a session attribute called "authenticated" being set to true.
Is it possible to configure Spring Security to determine whether a request is authenticated based on the presence and truthiness of that session variable?
The security filter chain might look something like this
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http.cors()
.authorizeHttpRequests(
requests -> {
requests.antMatchers("/auth/login").permitAll();
requests.antMatchers("/auth/sso-login").permitAll();
requests.antMatchers("/auth/developer-login").permitAll();
requests.anyRequest().authenticated();
})
.build();
}
The idea would be that so long as a user has hit any of the login endpoints correctly, the application flags the session as authenticated, allowing the user to access other endpoints as an authenticated user.
Or is there a more integrated solution that allows the application to designate a particular session as authenticated, not using traditional mechanisms like BasicAuth? Specifically in the case of a developer utility being able to mock a login as a mocked user without providing credentials. Simply hitting the endpoint (in the environments where it is available) triggering a fully authenticated session as far as Spring Security is concerned.
I have application with Spring security. It's REST api for Angular SPA. It uses session and cookie mechanism. Now I want to access this api from mobile application (Nativescript). I spent some time searching for best way to authenticate mobile app user. In the most cases oauth2 and jwt tokens are advised. So I've done reasearch on this and decided to add additional (seperate) authentication only for mobile application. So Angular app still will be using session with path api/... and mobile app will be using token mechanism with path /api/mobile/... (underneath it will be the same api but with different prefix).
I've decided to use OAuth2 and its Spring integration. I've read documentation and I'm consfused. Why they always mention about authentication provider (Google, Github, Facebook)? I don't want to force my users to login via other service. I want to allow them login with credentials they already registered with in my application. How this social login even related with oAuth authorization server? All examples they've provided use some other services.
I've also tried to add my authorization server in my existing app. I've successfully retrieved token. But now I don't understand all this relationships. There is authorization server that keeps client id and client server. But why /auth/token endpoint needs another authentication? So mobile app needs to provide 3 different credentials - user credentials, client id and secret and token endpoint credentials.
Did I miss something? I know that OAuth is only specification and Spring is implementation of it. But I'm under impression that Spring overcomplicates this. And do I need oauth at all since I have only 1 type of resource?
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.inMemory()
.withClient(clientId)
.secret(passwordEncoder.encode(clientSecret))
.authorizedGrantTypes("refresh_token", "authorization_code", "password", "implicit")
.scopes(scopeRead, scopeWrite)
.resourceIds(resourceIds);
}
}
Our app is currently set up with OAuth OpenID connect authentication with an external (third-party) server. The requirement is to use user details service that loads the user from LDAP (along with the authorities/roles) to complete the authentication. So authentication.getPrincipal() should be returning the custom UserDetails object we use that gets generated by querying LDAP using the username obtained from the Open ID authentication.
I have tried the following:
Followed Similar Issue but it seems like in the answer it's setting up the server-side and it doesn't work either
Tried adding custom UserDetailsService in WebSecurityConfig
#Configuration
public class OAuth2Config extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2Login().and().userDetailsService(myCustomUserDetailsService());
}
}
where myCustomUserDetailsService() handles the call to LDAP and fetches the user details info, including the authorities.
I'm not too familiar with the spring oauth2 framework, correct me if I'm wrong: I'm guessing I need to implement my own user info endpoint to make a call to LDAP, and not the user info endpoint provided to me by the OpenID service?
You could add a new filter in the security filter chain right after that one. The second filter could retrieve the principal/name from authentication and query for users.
Like a two steps authentication
Not as clean as I hoped, but I registered an application listener on InteractiveAuthenticationSuccessEvent and manually updated the authentication after login (similar post's answer https://stackoverflow.com/a/10747856/11204609)
If anyone has better suggestions?
UPDATE: The identity provider agreed to include LDAP info in their claims so I can directly obtain via the token without having to do a call-back (still an on-going discussion at the moment). That being said, having a auth success callback app listener is only way I could solve the problem.
I've built a REST Service using Spring Boot and Spring Security for authentication. I'm pretty new to both Spring Boot and Spring Security. I've made one authentication module in one JAR file. The front end client sends a request with username and password to the authentication module. The authentication module then authenticates the user's details against a DB. A JWT is created and then sent back to the client if the authentication is successful. The username and role is coded into the JWT. The JWT is then used to verify the user when resources are requested from the other REST Service endpoints that are built in separate JAR files. There are a few things I'm not sure about.
In Spring Security is there one authentication object created for each user so that several users can be authenticated at the same time or is one authentication done each time and only one user can be logged in?
How long is the authentication object in valid? Should I "logout"/remove the authentication successful when the JWT has been created in the authentication module or will it take care of it itself when the request is done? For the resource endpoints (not the authentication endpoint) is there a way to set authentication successful in the authentication object once I've verified the JWT? Similarly can I set the role in the authentication object once the JWT has been verified?
I've based my code on this example https://auth0.com/blog/securing-spring-boot-with-jwts/. I've split it into different JARs for authentication and verification of the JWT (I'm doing verification in resource endpoint). I've also added JDBC authentication instead of in memory authentication.
In Spring Security is there one authentication object created for each
user so that several users can be authenticated at the same time or is
one authentication done each time and only one user can be logged in?
Of course multiple users can be authenticated at the same time!
How long is the authentication object in valid? Should I
"logout"/remove the authentication successful when the JWT has been
created in the authentication module or will it take care of it itself
when the request is done?
You write your service is REST, and if you want to stay "puritan" REST you should configure the authentication to be stateless, which means that the Authentication object is removed when the request has been processed. This does not affect the validity of the JWT token, you can set an expiry of JWT token if you want.
How to make REST stateless with "Java config":
#Configuration
public static class RestHttpConfig extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// and the rest of security config after this
For the resource endpoints (not the authentication endpoint) is there
a way to set authentication successful in the authentication object
once I've verified the JWT? Similarly can I set the role in the
authentication object once the JWT has been verified?
I use code similar to below after verification of the token:
Collection<? extends GrantedAuthority> authorities = Collections.singleton(new SimpleGrantedAuthority("ROLE_JWT"));
Authentication authentication = new PreAuthenticatedAuthenticationToken(subject, token, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
By constructing the authentication object with at least one role (authority), it is marked as "successful" (authenticated).
I have a spring project that uses spring-oauth2 and spring-security for authentication using an LDAP auth provider.
In controllers I can access the current principal's UserDetails using the #AuthenticationPrincipal annotation.
However, when I hit the endpoint with a client_credential token the #AuthenticationPrincipal is a String which is the OAuth client id. I understand that there's no notion of user when you authenticate with client_credentials, but I would like to have my Principal be a richer datatype. How does spring decide to set my principal as a String and can I override that behavior?
From the Oauth2 specs
The client credentials (or other forms of client authentication) can
be used as an authorization grant when the authorization scope is
limited to the protected resources under the control of the client,
or to protected resources previously arranged with the authorization
server. Client credentials are used as an authorization grant
typically when the client is acting on its own behalf (the client is
also the resource owner) or is requesting access to protected
resources based on an authorization previously arranged with the
authorization server.
because client can also be a resource owner, therefore spring will create authentication based on your client information.
I assume that you have setup org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter which is used to create authentication for the client.
You can create your own custom org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService or create your own org.springframework.security.authentication.AuthenticationProvider to override how the authentication object is created, but I prefer to use org.springframework.security.oauth2.provider.token.TokenEnhancer to add additional information to the token generated.