Include AuthnContextDeclRef in the AuthnRequest - spring-saml

We have a requirement to support more than one login page for multiple SPs.
One login page will be a default, and the others will be Service Provider specific, so for instance:
SP1 will have a default configuration, and authn request will resolve to the default login page maintained in the IDP.
SP2 will ask for a login page B in the authn request, which the IDP must oblige.
Ordinarily this should be configurable at the IDP end, warranting no changes to the SPs, however this "feautre" is not supported in our IDP.
Thus our IDP support folks have recommended we include
<samlp:RequestedAuthnContext Comparison="exact">
<saml:AuthnContextDeclRef>blah/blah/blah</saml:AuthnContextDeclRef>
</samlp:RequestedAuthnContext>
In the authn request.
Spring SAML does provide us with an option of configuring the Comparison attribute via WebSSOProfileOptions ; however I'm struggling with AuthnContextDeclRef.
One solution which I have tested successfully is to extend the WebSSOProfileImpl class and override the buildAuthnContext method, however I'm wondering if there is a better solution.
Thanks in advance.

You can extend class WebSSOProfileImpl and override method buildAuthnContext, where you can programatically add the AuthnContextDeclRef elements you need.
You can also open a feature request, or contact commercial support of Spring SAML.

Related

How to validate SM_USER header in Spring Security preauthentication for siteminder

I 'm trying to create a secure spring rest api using pre-authentication security for siteminder.
I 've tried a solution where I 'm getting SM_USER and when I tested it in postman by adding new header SM_USER with random value it seems to work fine.
If you don't provide header I'm getting an error org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException: SM_USER header not found in request which is valid.
But how can I be sure that this is secure? if someone knows the URL of my rest api could call this without problem. Should I check something else in spring or only siteminder offers user authentication?
The front-end SiteMinder web agent is the guaranty that the session is valid - you must make sure via server/network configuration that your application cannot be accessed directly without first passing through the SiteMinder web agent.
Also, SiteMinder asserts multiple headers. SM_USER should not be used alone because it can be asserted by the web agent in some circumstances when the user does not actually have a valid session. Instead, you should first look for the existence (non-blank) of SM_SERVERSESSIONID, which only exists if the session is valid.
Lastly, I generally try to avoid SM_USER at all - because SM_USER is actually not a user attribute at all, but rather is "the login identifier used for authentication". If SiteMinder authenticates users via federation (e.g. SAML) or x509 authentication, SM_USER will be rather different than if a login form was used. Instead, its better in SiteMinder to set a "universal id" that is a user attribute, and appears in the headers as SM_UNIVERSALID. Your SiteMinder administrators will know how to do this (and may already have - look to see if you have a SM_UNIVERSALID header available already).
One other caution, in some SiteMinder configurations, the underscore will not be in the header name (use of the underscore is called "legacy" header mode in SiteMinder), so you might want to make your app configurable with respect to the header names, e.g. SMSERVERSESSIONID, SMUSER, SMUNIVERSALID etc.
If you want to programmatically re-validate a session, you can use the SiteMinder Agent API or REST API, or look at my company's product "SSO/Rest" which provides a comprehensive set of uniform REST interfaces to SiteMinder and also other SSO providers (http://www.idfconnect.com).
HTH!
-Richard

Can SAMLCredential.getRemoteEntityID() be trusted?

I'm implementing Spring SAML in an app which is configured with multiple identity providers. My IdP metadata configuration has multiple ExtendedMetadataDelegate with an HTTPMetadataProvider and alias for each IdP. The app chooses which provider to use by extending SAMLContextProvider in a similar way to this.
When an IdP sends authorisation my app needs to know which IdP it came from (different providers have different security authorisations). I'm doing this as the docs suggest and using a custom SAMLUserDetailsService and the SAMLCredential.getRemoteEntityID() to determine which IdP made the request.
My question is, can I rely on the remoteEntityID to identify the provider? What if one IdP provider updates their metadata to include a different entityID or even "forged" entityID which was identical to another provider? Wouldn't it be better to use the peer alias as defined by us?
I'm new to SAML so it's very likely my understanding of some basic concept is incorrect, I just want to make sure I'm not opening a security hole with this configuration.
This is a good question. I didn't know the answer so I tried it out.
I have in my test environment an instance of MS ADFS and and SpringSAML project with a Service Provider and Identity Provider configured (for ADFS). In my custom SAMLUserDetailsService I use SAMLCredential.getRemoteEntityID() to determine which IDP the request came from.
I performed a successful login, then changed the name of the ADFS EntityID, then tried to login again. This resulted in a AuthNResponse;SUCCESS;127.0.0.1 message in the logs, but an error in the browser. I ran through it again with debug enabled in the UserDetailService and found that the request is failing somewhere before it gets to the UserDetailService, however, I'm not seeing any error messages in the logs.
To answer your question, (and perhaps someone else can answer more definitively), SpringSAML handles this scenario appropriately in that it errors out. It does not in that there is no error message in the logs. I assume this is because it's a somewhat unusual scenario to happen, or just a bug.
As far as forging another Identity Provider's Entity ID, the SAML requests are signed and therefore anyone trying to forge and IDPs message would also have to have access to their private key.
Lastly, the alias is not in the request, thus it cannot be used to differentiate between IDPs.

Keep PingFederate IDP session alive from SP

We're implementing a web SSO solution using PingFederate, with a 3rd party product that includes SAML2 out of the box.
However we're trying to work through the question of how to stop the IDP session timing out if the user is still actively using the SP.
The 3rd party product supports requesting an empty resource on the IDP side, with the intention that this URL would result in the IDP session being extended.
I can't see anything in PingFederate that supports anything like this. Does anybody know how this is generally resolved? Is there a way to extend the PingFederate session e.g. API call, HTTP POST to an endpoint, whatever?
Or does the SP need to construct a new authenticate request? If so, does this result in a new SAML response / token being issued with a new NotOnOrAfter date?
Unfortunately, this isn't a use case that SAML 2.0 covers and any solution that fits within the SAML 2.0 spec will probably be custom to an individual product. Additionally, is no way to have the SP extend the session at PingFed (IDP) except to do another round-trip for SSO.
Typically customers handle this by making the session at the IDP long-lived so that user's are not prompted to login again when switching between SPs.
If you control both the IDP and the SP, then I'd recommend looking at using PingAccess in conjunction with PingFederate. You can still Federate into the application via PingFed but PingAccess will allow you to manage the sessions across applications.

Spring Security Using X.509 Authentication and Periodically Updating Authorization UserDetails

I used Spring and Apache CXF to create a REST webservices application. I'm using x.509 certificates to authenticate the users, and then a custom authorization service to get all of the user groups and details. I've implemented a custom UserDetailsService that extracts the user information and populates a UserDetails object. Part of the process of populating this object involves a request to the corporate authorization service. The authorization service is unfortunately a proprietary system, but at least they provide a Java API. The authorization service, among other things, returns a list of groups that the user belongs to.
I'm still in the development stage, but my observations so far seem to indicate that the UserDetailsService is called once upon initial connection. Then each request uses a cached authorization object.
So my question and potential problem are this... Corporate policy states that applications are only allowed to cache the users authorization details for a set period of time. So, how long does Spring keep these UserDetails objects cached before refreshing them? And, how can I control this cache time to make sure I comply with policy?
There was a ticket submitted for something similar to this request:
https://jira.springsource.org/browse/SEC-898
The advice in the ticket is to create your own filter than periodically sets the Authentication.setAuthenticated property to false, forcing a look up of the user. You might be able to achieve the same by setting a smaller session timeout

How to design authentication and authorization system for REST backend / Ajax front End Application

I am starting a new project where we are planing to build a restful back end and an AJAX font end. I am approaching the problem by focusing on Identifying all the resources that I have and what the various HTTP verbs will do them, their URI and the JSON representations of those resources.
I am looking for the best design for securing the backend. Here is the list of designs I have considered. I am looking for alternative designs not listed below, and pros, cons recommendations. The system will be implemented with Spring 3.0 and possibly Spring Security 3.0, SSL will be used for many parts of the system but not for all of them, so some requests may come on SSL and some might not.
Option 1: Use the HTTP session
Show a standard login screen, create a server side session and let tomcat send back a jsessionid cookie and have the ajax client include the JSESSIONID cookie on every XHR request. This options just feels like it's the wrong approach for the following reasons.
The connection becomes statefull which is against the rules of REST
I want to be able to split the bakcend into multiple seperate WAR files which means i could have multiple HTTP sessions on the backend, if that is the case then this approach does not work. While I don't need the ability to split the backend into multiple apps today, I would prefer a design that allows for that possibility.
Option 2: Find an open source Java based security library that does this
Other than Spring security I have not found any other Java libraries, any recommendations are highly appreciated.
Option 3: Try to use an existing protocol like OAuth
In my very brief look at OAuth it seems that it is designed for authentication across sites where each site has it's own user database. In this system i want a global user database shared across all the backend ajax services.
Option 4: Use SAML and Shiboleth
This options seems over kill and hugely complex to setup and maintain.
Option 5: Send the username and password with every request
This requires that user sends their username and password with every request, which means that the front end AJAX app must store the username and password as a JavaScript object and if the user navigates away from the page then back the username/password combo will be gone and the user might be forced to log in again. I don't want the front end to try and put the username and password into cookie as that would comprise security.
Option 6: Implement my own authentication / Authorization protocol
Create a REST service that users can present their username/password combination to and then get back and security token, which they must send back to the service with every request. The security token would be digitally signed by the service and would have an expiry time. The token would be only good for most operations high security operations would require a new login screen as port of confirming the operation.
Problem with this approach is I have to invent yet another security protocol which seems like a total waste of time.
I am sure I am not the only person up against this problem, I hope the stack overflow community can point to some options and tools that I have not found yet.
Take a look at Apache Shiro. It is an authentication system that has a session management feature that can be used to share sessions across applications. This may be the easiest thing to do.
Or you could use Spring Security (or Shiro) with a Remember Me cookie that is shared across the webapps (as long as they are in the same HTTP domain). The remember me cookie would be analogous to your token in option 6. You can set the expiration on the cookie that so it is short lived like a session cookie or long lived like a regular remember me.
You might also want to take a look at Jasig CAS - Single Sign-On for the Web. It has a REST API and a protocol (Proxy Tickets) that allows services to proxy user AuthN to backend services like you described in option 6. http://www.jasig.org/cas
Briefly...the application that serves up the AJAX client is protected with Spring Security (supports CAS out of the box) and gets a Proxy Granting Ticket that you embed in the AJAX client. The AJAX client uses the PGT to get Proxy Tickets for your REST services...protected with Spring Security too. The REST services get an authenticated userId without every touching primary credentials.
Alternative, you could keep the PGT on the server and use AJAX calls to retrieve Proxy Tickets that are then used by the AJAX client to call you REST services.
As I understood you are going to secure a rest application, to preface you must know that a security provider consisd of three concepts (3A):
-Authentication
-Authorization
-Auditing
to implement these three together you must provide bunch of tools such as :
-SSO provider
-Session Store
-Open Id pattern
-user credentials integration
....
I have used ACL(Spring ACL) to provide authorization services and oauth2 for authentication.
there is one channel to connect these two together and its scopes(oauth2 scopes) but the problem is scopes are not flexible(pure strings) enough to implement authorization modules such as role_voter, cache_strategy, black_list or,Role_base strategy, exceptional permissions, white_list... (but you can use #EnableGlobalMethodSecurity)
In my case I used authorization server as a resource for oauth2 authentication server(take a look at http://projects.spring.io/spring-security-oauth/docs/oauth2.html), then I considered two spots to check authorization, the first I issued ACL to front-end and forced programmer to design her page dynamically up to ACL concept, the second is in back-end on service layer(BLL) using Aspect when one rest is going to be called. I sent the service key as an actee to check if current user has enough access control to do that. and for auditing you must monitor all requests I mean you must use an listener in your gateway or broker...

Resources