I am trying to use the SAML adaptor provided by Spring Security (https://docs.spring.io/spring-security/reference/servlet/saml2/index.html). The library takes in credentials by Saml2X509Credential, which requires certificate of X509Certificate type. However for the project I am working on, the cert provided to me is an endpoint URL. I am wondering what is the workaround for this?
In addition to this, in the project I need to obtain some user information (such as user email) back from the SAML response. But it seems that the provided UserDetailsService doesn't have a way to grab information other than
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
I am wondering is there any way to customize this?
I had done lots of research but didn't find useful info.I am really new to security and saml, sorry if these questions repeated.
Related
I'd like to provide two ways to authenticate in my application, one is basic auth (users), and the other is some kind of token based (technical users). I understand that I need a custom ReactiveAuthenticationManager but I can't find clues on the big picture. (Actually, there are a very few insights for MVC, and none for WebFlux.)
1) How do I populate the Authentication's name and credentials in the token based approach? If I configure Spring Security to use httpBasic it's already populated. Some kind of filter needed?
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
Since i am decent at Webflux and i have worked a lot with oauth2 i'll try and answer some of your questions.
1) How do I populate the Authentication's name and credentials in the
token based approach? If I configure Spring Security to use httpBasic
it's already populated. Some kind of filter needed?
A token never contains credentials. A token is something you get issued after an authentication has been done. So usually you authenticate against an issuing service. After you have authenticated yourself against that service you will be issued a token.
If its an oauth2 token the token itself is just a random string. It contains no data about the user itself. When this token is sent (using the appropriate header) to a service using spring security. Spring security has a token filter that will basically check that the token is valid, usually by sending the token to the issuer and asking "is this token valid?".
If using a jwt, its different, the jwt must contain some information like issuer, scopes, subject etc. etc. but its basically the same thing, there is a built in filter that will validate the jwt by sending it to the issuer (or using a jwk that the service fetches from the issuer so it can verify the integrity of the jwt without doing an extra request).
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
You don't You usually define multiple SecurityWebFilterChains for different url paths. I have not done this in Webflux Spring Security, but thats how you do it in regular Spring Applications, and i don't see any difference here. Unless you are doing something crazy custom.
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
The answer here is probably no. You see Spring security 4 had very bad support for oauth2 and especially JWT. So people got accustomed to writing their own JWT parsers. When spring Security 5 came, Spring implemented a jwt filter that you can configure and use built in. But there are a lot of outdated Spring Security tutorials out there and foremost there are a lot of developers that don't read the official documentation.
They mostly google tutorials and get the wrong information and then work on that.
But easy explained:
SecurityContextRepository
If you have session based authentication (server establishes a session with a client) it will store the SecurityContext (session) in ThreadLocal during a request. But as soon as the request ends, the session will go lost unless we store it somewhere. The SecurityContextPersistenceFilter will use the SecurityContextRepository to extract the session from ThreadLocal and store it, most common is to store it in the HttpSession.
AuthenticationManager
Override this if you want to do a custom authentication process. Example if you want to validate something, call a custom LDAP, database, etc etc. It\s here you perform you authentication. But remember, most standard logins (like ldap, sql-servers, basic login etc.) already have prebuilt configurable managers implemented, when you select what login type like .httpBasic() you will get a pre-implemented AuthenticationManager.
UserDetailsManager
You override this when you want create a custom UserDetails object (also usually called Principal) In the UserDetailsManager you do you database lookup and fetch the user and then build and return a UserDetails object.
Those two interfaces are the most regular custom implementations, and are used if you need to to basic authentication/session based authentication.
If you wish to do token, you have to think about, who is the token issuer? usually the issuer is separate and all services just get tokens and validate them against the issuer.
I hope this explains some of the questions. I have written this on the bus so some things are probably wrong and not 100% correct etc. etc.
I am trying to add a basic authentication security layer over a REST service that I developed using Spring boot 4.3.
I have essentially did two main things:
Implement UserDetailsService interface to provide user details. Here I read from a text file the usernames and the encoded (via Bcrypt) passwords.
I declare a bean as follows in my #EnableWebSecurity annotated security configuration class:
#Bean
public BCryptPasswordEncoder getPasswordEncoder () {
return new BCryptPasswordEncoder();
}
to return the specific password encoder.
I am testing the authentication using rest clients both ARC (for Chrome) and REST Client of Firefox.
The issue is as follows:
When I enter my credentials for the first time and upon successful authentication, the response is 200 OK. This is true for a bunch of users. In other words, as long as I supply correct pair of credentials I get a 200 response.
But, after a single request with incorrect credentials the authentication process breaks down. Sometimes I get 200 and other times a 401 even for correct credentials. Other users authentication is affected as well, at this point of time.
There is a curious log that appears at step 2:
WARN 6813 BCryptPasswordEncoder : Empty encoded password
To elaborate a bit on the hashing of the passwords, I ran the Bcrypt password encoder utility and encoded a bunch of passwords and saved them manually in a text file for the corresponding user names.
I am unsure where the issue lies: whether the clients caching the credentials or the Spring security context caching the incorrect principal or the user details service breaking down (no such exception in the logs though).
Any help is appreciated. If you need any further specific information, please do let me know.
This question is related to this one, but I decided to separate it.
I have signingKey and encryptionKey settings in my grails spring saml config. What is their purpose? I read the spring-security-saml doc and grails saml plugin doc, but it's still a little bit unclear. Could anyone explain their practical usage?
You can think of them as:
signingKey = outbound requests
encryptionKey = inbound data:
i.e. the key you will use to sign outbound requests (e.g. AuthnRequest) vs. the key that your integration partners will use to encrypt assertions that are destined for you.
In the SAML metadata standard they are allowed to be the same value or you can specify different keys for each:
2.4.1.1 The element provides information about the cryptographic key(s) that an entity uses to sign data or receive encrypted keys
use [Optional] Optional attribute specifying the purpose of the key being described. Values are drawn from the KeyTypes enumeration, and consist of the values encryption and signing
I have stored (and encoded) an email password. I have used PasswordEncoder (Spring security).
passwordEncoder.encode(password);
Now I need to decode it in order to use it in javax mail. (the password is used to connect to the email provider(yahoo, gmail, etc).
Is there a way to decode this password?
Thanks in advance.
PasswordEncoder interface support only encoding and matching which is the best way to deal with password as others too have suggested. You can use StandardPBEStringEncryptor provided by Jasypt library as this library had transparent integration with Spring Security. Else you can roll out your own using Java Cryptography Extension's Password Based Encryption (PBE) however before trying what you want to achieve with regards to password encryption you must definitely read this.
Spring SAML Extension seem to disregard the query string param configured in IDP xml. Here is the configuration
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://<provier host>/saml/?query1=xxx&query2=yyy"/>
1) When the SSO request gets redirected, SAML extension seem to strip anything after ? and send only SAMLRequest query string param.
2) Also I wanted modify query string param value based on some configuration so that I can hit environment specific endpoints for testing and development
Is there a way to intercept the redirection request before the redirection to satisfy the above needs?
The query parameters are removed by the underlaying OpenSAML library in class org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder. You can extend this class, override method buildRedirectURL and add parameters as you need to the constructed URL. Your implementation would then need to be added to bean org.springframework.security.saml.processor.HTTPRedirectDeflateBinding using its constructor which accepts instances of MessageDecoder and MessageEncoder.
Hit this exact issue with the new Google Apps SAML IDP Federated SSO.
Vladimír's suggestion above helped me solve the problem.
Here is the exact error I was getting to enable others to find the solution.
400. That’s an error.
Invalid Request, no idpId in request URL, check if SSO URL is configured properly on SP side. That’s all we know.