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.
Related
I'm working on a Spring web application (not Spring Boot) that uses Spring Security 5.3.3, Spring Security OAuth 2.5.0, and configures it like this:
http.authorizeRequests().
antMatchers(permitUrls).
permitAll().
anyRequest().
authenticated().
and().
oauth2ResourceServer().
jwt();
Our clients report occasional 401 responses which we can't find in our application logs, so we assume it's from the Spring Security itself. We would like to log authentication and authorization failures, but I'm confused as to what is the current preferred method to achieve that.
A quick search reveals 4 paths:
custom AuthenticationFailureHandler (seems like this one is only available in FormLoginConfigurer, which isn't our case)
custom AuthenticationEntryPoint (this one is available with JWT, but OAuth2AuthenticationEntryPoint which I was going to extend is deprecated with an unhelpful message). I could try using HttpStatusEntryPoint instead, but I'd like to avoid changing the current behavior of my app, just want to add logging.
custom Filter (probably, not the cleanest path)
AuditApplicationEvents — looks beautiful, but seems like it's for Spring Boot only.
Could anyone provide me with some guidance on this?
I suggest activating the logger of org.springframework.security by changing its log level to DEBUG.
Based on your log tools (log4j2, logback, ...) create a logger in your log configurations with name org.springframework.security and level DEBUG.
I have searched enough but I haven't got a clear answer and thus posting this question.
I have an existing application which uses spring security for authentication.
Current implementation uses a custom implementation of UsernamePasswordAuthenticationFilter for doing this.
Thus the flow is something like below(in very simple terms):
inputrequest>DelegatingFilterProxy>LoginUrlAuthenticationEntryPoint>CustomUsernamePasswordAuthenticationFilter>AuthenticationManager>CustomAuthenticationProvider
Now I have a requirement to implement SSO (since the user is already asusmed to be authenticated) in some scenarios.
The requirement states that if I have a specific request parameter present then I need to automatically authenticate the request without bothering about user/password.
So it is same set of resources and I do not have to authenticate user/password if the specific SSO related request parameter is present.
e.g
suppose a resource \test\bus is a secure resource.
if I come from normal way then we need to check if the user is authenticated or nor and force user to put valid user/password
if I come from SSO channel then I need to show the \test\bus resource as the user is already authenticated.
currently all the access restrictions are put through <http> element
e.g the snippet of security-config.xml is as follows:
Query: What options do I have in this case. I can think of below options:
Pre-authenticate the user before spring security framework kicks in. This will mean creating an authentication token and putting in spring context before spring security filter is called. This can be done through another filter which is called before spring security filter chain. I have tested it and it works.
Create another custom security filter which set-up the authentication token. I am not clear if this is correct approach as not sure when do we create multiple custom security filter
Create another custom authentication provider e.g SSOCustomAuthenticationProvider. This provider will be called in the existing current flow as we can have multiple authentication providers to a authentication manager. The only issue is that in order to achieve this I have to change the request url to authentication filter's target url so that spring security doesn't check for authentication.
to explain more,
let's say request uri is /test/bus, I will write a filter which will intercept the request and change it to /test/startlogin. This is currently my CustomUsernamePasswordAuthenticationFilter's target url i.e
<property name="filterProcessesUrl" value="/test/startlogin"/>
The flow will be
inputrequest>DelegatingFilterProxy>LoginUrlAuthenticationEntryPoint>CustomUsernamePasswordAuthenticationFilter>AuthenticationManager>SSOCustomAuthenticationProvider
I have tested this and this works. Is this a valid approach or a hack.
Is there any other viable option available with me.
Thanks for reading this.
I have an MVC 4 application receiving SAML2 tokens from an initiating IdP. I can see the token as it arrives and I can decrypt it. However, I want to do this with WIF 3.5 and seem to be having problems with SAML Namespaces when I try to use the WSSecurityTokenSerializer as follows:
System.Xml.XmlException was unhandled by user code
HResult=-2146232000
Message=Cannot read the token from the 'Response' element with the 'urn:oasis:names:tc:SAML:2.0:protocol' namespace for BinarySecretSecurityToken, with a '' ValueType. If this element is expected to be valid, ensure that security is configured to consume tokens with the name, namespace and value type specified.
Source=System.ServiceModel
LineNumber=0
LinePosition=0
StackTrace:
at System.ServiceModel.Security.WSSecurityTokenSerializer.ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)
at System.IdentityModel.Selectors.SecurityTokenSerializer.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)
at SamlHandlingTests.SamlTests.TestMethod1() in g:\Projects\mytempesub\Solution\SamlHandlingTests\SamlTests.cs:line 112
InnerException:
I have seen a post here StackOverflow question but the final resolution of doing things directly with XML doesn't suit me because I need to be able to run this up as a standard IdP-Initiated solution.
Therefore I have two questions:
Has anyone ever managed to overcome this error with WIF? (I don't need the WIF Extensions as I am only concerned with handling SAML2 tokens, not protocol.
To use WIF in an IdP-Initiated environment I understand requires no configuration, I have simply set authentication off and I check the incoming token. However, I would prefer to check the token in the full WIF pipeline but this then needs configuration. How can I configure WIF to function in this IdP-Initiated environment?
Many thanks
Brian
If you need to deserialize the token you might consider instead using Saml2SecurityTokenHandler.
I would also ask, does your scenario require you to deserialize the token yourself? WIF integrates well with ASP.NET MVC applications so you might instead rely on the WIF to do this for you. See Eugenio's answer here.
I'm looking for a way to secure a web service whereby the user id is to be got from the request headers.
The ssl handshake is taken care of so I'm not sure if I need to use a subclass of org.springframework.ws.soap.security.AbstractWsSecurityInterceptor
Once the user id is got from the request then I'd like to use the standard spring security to authenticate the user as I am already doing this for spring mvc projects.
Thanks
I have used XwsSecurityInterceptor (one of the implementations of AbstractWsSecurityInterceptor) succesfully for a few projects. I'm not sure if the way of passing the userId is already defined or that you can propose using xws-security instead.
If the way of passing the id is already defined, creating a new implementation of AbstractWsSecurityInterceptor shouldn't be too much trouble. Take a look at the handleRequest method where you can access the soap request and check for the header.
You can simply wire up the new security interceptor in the endpoint mapping to debug it.
I have implemented a SAML Service Provider to support Single Sign On for an ASP.Net web portal, which is a shrink-wrap software configured on clients' sites and must be able to interact with any SAML-compliant Identity Provider.
My Assertion Consumer Service (ACS) page will accept the SAML Response through both GET and POST methods.
As I understand the SAML protocol, the SAML Request ProtocolBinding property specifies which protocols are supported for the response. Currently, my request specifies the HTTP-Redirect binding. However, I would like to declare that I support both HTTP-Redirect (GET) and HTTP-POST (POST). After searching through more SAML documentation than I care to reiterate, I am unable to find the syntax for declaring multiple supported protocol bindings (or whether it is even valid to do so).
While I could make this declaration configurable, my preference would be to declare both bindings so that the Identity Provider will work without additional configuration of my portal.
Below is a sample of my Authentication Request. Please, if anyone knows a way to declare both HTTP-Redirect AND HTTP-POST for the ProtocolBinding, I would greatly appreciate your input!
<?xml version="1.0" encoding="utf-8"?>
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
ID="[AUTHN_ID]"
Version="2.0"
IssueInstant="[ISSUE_INSTANT]"
ProtocolBinding="urn:oasis:names.tc:SAML:2.0:bindings:HTTP-Redirect"
ProviderName="[PROVIDER_NAME]"
AssertionConsumerServiceURL="[ACS_URL]">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
PortalEntityID
</saml:Issuer>
<samlp:NameIDPolicy
AllowCreate="true"
Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" />
</samlp:AuthnRequest>
Thanks in advance to anyone who can help!
The ProtocolBinding attribute on AuthnRequest is used to specify the expected binding to be used by the IdP when sending their SAML Response XML. HTTP-Redirect isn't a valid option to use here, because of the possible length restriction on the URL querystring; a SAML Response, especially if it's signed, can be pretty lengthy. I'll quote from the SAML spec [SAMLProf]:
...the identity provider issues a <Response> message to be delivered by the user agent to the service provider. Either the HTTP POST or HTTP Artifact binding can be used to transfer the message to the service provider through the user agent. The message may indicate an error or will include (at least) an authentication assertion. The HTTP Redirect binding MUST NOT be used, as the response will typically exceed the URL length permitted by most user agents.
After considerable research, it seems that you can only declare one Protocol Binding in a single SAML request.