NameID required in SAML Assertion - spring-security

Trying to integrate with an IdP I am getting a failure that a NameID is not present in the Assertion. I noticed on lines 250-253 of processAuthenticationResponse in org.springframework.security.saml.websso.WebSSOProfileConsumerImpl there is an explicit check for the NameID. I can't find anywhere in the 2.0 spec where a NameID is mandatory. If neither metatdata specifies a NameIDPolicy and the AuthnRequest doesn't specify one, should the check for NameID be optional?

Spring SAML currently requires NameID to be present. I agree that adding a feature which makes it optional is reasonable. Please feel free to open a feature request in Spring SAML Jira.

Related

Using Spring Security SAML with certificate in URL format

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.

Resolving Metadata via ArtifactResolutionService

I am attempting to implement SAML login using Spring Security 5.5.3. Unfortunately, the metadata file looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EntityDescriptor entityID="https://remoteloginsite.org/sso/authentication"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
<IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<ArtifactResolutionService index="0" isDefault="true" Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="https://remoteloginsite.org/sso/ArtifactResolver/metaAlias/authentication"/>
</IDPSSODescriptor>
</EntityDescriptor>
Unfortunately, Spring Security's SAML support bombs when attempting to read this metadata file with the following exception:
Caused by: org.springframework.security.saml2.Saml2Exception: Metadata response is missing verification certificates, necessary for verifying SAML assertions
I'm assuming that this simply means that 5.5.3 doesn't support resolving items such as <SingleLogoutService>,<SingleLoginService>, etc, so if I want to do it, I'll have to reach out to the location URL specified by the <ArtifactResolutionService> myself and use the results to manually build a RelyingPartyRegistration myself.
Question 1: Am I correct in the assumptions I've made about the steps I have to take?
Question 2: Does OpenSaml (version 3) provide any shortcuts that would make this any easier?
Thanks for any help.
Unfortunately, the version of Spring Security we used, 5.5.3, was too NEW to support artifact resolution. SAML support in Spring Security is a work in progress. We ended up not being able to use the 5.6.x releases of Spring Security because the Saml2AuthenticationToken did not implement the Serializable interface.
We manged to configure a RelyingPartyRegistration manually to make the first call to the IdP. Unfortunately, the response contained a SAML artifact ID, requiring us to make a second call. The IDP also turned around and made a GET request to us, which the SAML Authentication Processing Filter did not recognize.
So, we ended up creating a new implementation of the AbstractAuthenticationProcessingFilter specifically to accept URI of that callback. We leveraged the SOAP functionality of OpenSAML 3 to manually create an ArtifactResolve object and sent it via SOAP to the Artifact Resolution Service URL. We received back an ArtifactResponse object, which we manually processed for the information we needed, then passed that into an AuthenticationProvider to correctly tie the whole thing into the Spring Security lifecycle.
I can't really provide much of our code, but I hope this explanation helps someone in the future.

How to implement multiple authentication methods in Spring WebFlux Security?

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.

Spring SAML Extension strips of query string param for Single Sign on Service

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.

Current OAuth 1.0 spec - how does it address the session fixation attack?

I've implemented an OAuth 1.0 provider following this specification, which should be the latest. The specification was amended to address the session fixation attack that was identified in 2009. The thing is, short of having to diff the two specifications I am unsure as to what measures were added/changed in the spec in response to the issue.
Since I implemented the "right" spec I am having a hard time explaining to stakeholders what measures I have taken to ameliorate the risks.
Anyone care to shed some light on the issue for me?
1.0a addresses a very specific attack described here:
Explaining the OAuth Session Fixation Attack
The oauth_callback parameter is now required in the request token generation step. The oauth_callback_accepted response parameter indicated OAuth 1.0a is being used.
The oauth_verifier parameter is generated by the service provider during the authentication/consent phase.
The oauth_verifier must be sent at the access token generation step.
See http://wiki.oauth.net/w/page/12238555/Signed%20Callback%20URLs for more details.

Resources