Authentication lifetime with WS-Federation via ADFS and WIF - asp.net

Some background
I work on an ASP.NET MVC web application which implements federated authentication using WIF.
For reasons beyond my control, I am forced to use a proxy STS which, on the one hand, serves as the IdP for my MVC app, but at the same time it implements it's own federated authentication via an ADFS server.
This way, the user authentication process in the MVC application looks like this:
User enters MVC application.
The application redirects the user to the proxy STS for authentication.
The proxy STS redirects the user to the ADFS server for authentication.
The ADFS server authenticates the user and redirects back to the proxy STS.
The proxy STS redirects the user back to the application, with the same authentication info which the ADFS server issued.
The ADFS server is not something I have direct access to (in terms of management), whereas the proxy STS is just a little service (implemented using this tutorial) which I control fully.
The problem (and what I tried to do to solve it)
Using the above setup, I noticed that the users' authentication wears off after about an hour, and then they need to be re-authenticated, so now I'm looking for a way to extend the authentication lifetime.
As of my understanding, it should be enough to extend the lifetime of the security token issued by the proxy STS, which I did. But it didn't solve the problem - the users still needed to be re-authenticated frequently.
So I tried doing the following things hoping it would help:
Setting the persistentCookiesOnPassiveRedirects option to true in the MVC application's ws-federation configuration with a 1-week long expiry time (to make sure that the auth cookie is not being lost due to session expiry).
Setting the HTTP session lifetime in the MVC app to last a week (to make sure that the security token is not being lost on the server side due to session expiry).
Setting the security token lifetime for tokens issued by the proxy STS to 1 week (which I made sure is being applied by examining the security tokens received by the MVC app).
Doing the things described in bullets 1 and 2 on the proxy STS as well.
Setting the IIS auto app-pool recycling time for the MVC app's application pool to be once a week.
None of the above didn't seem to solve the problem, but then I tried:
Setting the security token lifetime for tokens issued by the ADFS server to 8 hours.
As a result, the authentication duration got longer, even as much as 10-11 hours.
The question
What controls the authentication duration with WS-Federation in the above scenario?
Which of the above things that I tried should really be relevant to my issue, and which should not affect it at all (specifically, I would like to understand whether the ADFS token lifetime should really have any effect, and if so - why, or did I just have bad luck with my tests, and it was really something else that might have helped with the issue)?
Thanks in advance!

You have hit a lot of relevant parameters. I will talk about the WIF/.NET part and SAML Tokens only. Not about Pool recycling etc. They are different topics. You will have to take a look at the XML in the SAML messages and Tokens if you really want to control this.
One of the problems is that there are differences between SAML1 and SAML2 Tokens. Besides that some validity timestamps are in the SAML Protocol, which is not used between WIF and an IdP.
Summarized:
It appears that WIF uses Conditions for the SessionToken. That is the only thing available in SAML 1.1. OK there.
SecurityTokenHandler.ValidateToken(token) calls DetectReplayedTokens().
The SecurityTokenHandler.DetectReplayedTokens(SecurityToken) method verifies the validity if the incoming Token (SubjectConfirmationData #NotOnOrAfter). It is not present in SAML 1.1 there WIF uses Conditions#NotOnOrAfter.
This is essentially correct for Replay detection in SAML 2. Somewhat silly (too broad, too long) for SAML1.1.
Applications can (and do) override this behavior in TokenHandler(s) or in events of WSFAM and SesAM. See for instance Vittorio about Sliding Expiration.

Related

shared authentication with cookie and token in identity server

I’ve an MVC application that uses identity server with cookie based authentication.
We created a new spa application that uses identity server authentication through bearer tokens.
Everything works fine, but the user is currently required to log in twice, once in each app.
Is there a solution to share the authentication session? I would prefer to not have to decrypt the cookie from the spa if possible.
Edit:
What I see is that the authentication code flow on the SPA is populating a lot of values on the session storage, which are not picked up by the the MVC (client credentials flow) application.
Am I supposed to reflect those changes manually? I see that both populate a cookie with the security information, but the SPA is just ignoring it.
In the end the reason was due to the difference in casing for the Authentication/authentication endpoint.
The cookies for idsrv and idsrvsession were marked as case sensitive, so we ended up having two different cookies for the session (hence creating 2 different sessions).
Changing one of the two endpoint to match the other solved the issue, although a CR forcing a tolowercase of the parameter has been requested to the library performing the connection to identity server.

How to change session token/cookie format in cookie when navigates to other website?

I have 2 web applications, one is ASP.NET MVC 5 + WIF hosted in IIS, another is a web service based on WCF and self-hosted. Both of them are under same domain (so there are no security issues to change cookie format) and referring to the same STS (in same security realm), so theoretically if one user already authenticated, he should be able to access other entities within same security realm without authentication.
However, these 2 websites are using different session token format. For ASP.NET MVC 5 project, it uses WIF implemented standard security session token and serialized to cookie; for WCF web service, it uses its own token/cookie format.
Then we have a problem.
When user navigates from ASP.NET MVC website to WCF web service, because WCF web service cannot recognize WIF session token (FedAuth and FedAuth1), so it redirects user to STS and login again, that is not the biggest problem, the biggest problem is, after use logged in, and POST raw SAML2 token back to WCF web service, WCF web service creates its own format token and tries to set client cookie, it actually doesn't work, I guess maybe there are already FedAuth and FedAuth1 cookie in header so header cannot accommodate more tokens (4K limit?)? Having thought about this for a while, there are are several solutions come into my mind:
Unifying token format. I need to subclass SecurityTokenHandler (maybe also need to subclass CookieHandler), use the same token format that WCF service uses, so when jumps to WCF web service, it can recognize the session token. That needs to dig deep into FAM and SAM.
Force re-login. I can clear FedAuth and FedAuth1 cookies before navigates to WCF web service, it is acceptable that user needs to login again, this is a short term fix, but how can I capture this navigation away event and clear cookie? The only way I think I can do is before I change window.location.href, use jQuery.cookie to clear cookie, I am not sure if it is the correct way, this is my first question.
Adding a cookie translation layer between ASP.NET and WCF, use WIF session token in ASP.NET website, and when jumps to WCF web service, change the token format. But for this solution I don't know how to capture the jump action and how can I get raw SAML2 token? May be I can save it in WSFederationAuthenticationModule_SecurityTokenReceived event handler? But how to deal with multi tokens from multi users and multi sessions?
Are there other better suggestions?

asp.net SSO and SAML from WebApi simply because that is all the client has

I have inherited this and am stuck with this approach. I am just trying to figure out if it will in fact work.
The project involves your standard asp.net web api application with android and ios clients. The trick is with the authentication. The application is for a 3rd party, and the only way that the user can be authenticated from the outside world is by using their IDP. The 3rd party does not care what happens after the user is authenticated.
All I have to go by is the architecture diagram that the former team members created. The diagram has 3 layers. User/Mobile Device, SAML SP Web APP and Client IDP. The important part of the flow is as follows:
Mobile App calls SAML SP Web App with the IDP user name and password.
SAML Web App calls the IDP login using the user's credentials
User Authenticated ? Responds to SAML SP Web App with success and SAML Assertion/Token
SAML SP Web App responds to mobile App with approved message
Once the user is authenticated through the IDP, the plan was then to issue a bearer token to the mobile device.
Unless things have changed a lot since I last had to play with SAML (2011), it seems I am missing a client browser to redirect from the SP to the IDP and then redirect back to the SP when a valid SAMl assertion is created.
Am I missing something here, such as a way to emulate a browser to allow for these redirects and plugging in the correct user name and password, or is there a way to call the IDP directly from the SP and have it issue a response directly back to the SP? Or am I just reading the diagram wrong or inheriting some very bad assumptions? I'm in the awkward position where I don't want to go back to the client and revisit a process that was supposedly decided upon at the start of the year unless I absolutely have to.
Things don't change a lot with SAML, so your knowledge from 2011 is still definitely valid.
I'm also missing the browser redirect step. It is a quite common misunderstanding that the SP can send username/password to the Idp and get an assertion back, but that is not supported by the SAML WebSSO Profile (which is the one that's actually used).
Using SAML2 for a mobile application is hard, there's no good support in the SAML2 protocol for redirecting back to the client. A common way to work around it is to use OpenID Connect. I've been involved in setups where the mobile client authenticates to IdentityServer3 via OpenID Connect. Then IdentityServer3 acts as a SAML2 SP (through the Kentor.AuthServices middleware) to the upstream SAML2 Idp.
I understand that you are in a delicate situation but I think that you have to go back and ask how it is supposed to work. Specifically you should ask where the user is supposed to enter credentials and how the communication between the SP and Idp is supposed to work.

Combine STS and relying party into same website

I'm working on an MVC project and I'd like to abstract authentication out completely using WIF. By default, without any additional configuration, this app needs to be it's own STS in additional to also being a relying party. Has anyone done that and have any suggestions?
I tried to think of exactly the same mechanism some time ago and I failed.
My reasoning was that to be an RP, the application has to get a signed SAML token issued by an STS. Upon receiving the token, the federation cookie is created.
But to be the STS, the application should have a login page and a mechanism to persist the login session so that users do not have to login again. Then it should react to wsignin1.0 requests and issue SAML tokens.
This leads to a contradiction in my opinion. The application should have a federation cookie (to maintain users sessions as an STS) before it issues the SAML token but in the same time it can create a federation cookie (as an RP) just after it receives the SAML token.
Of course, you could possibly maintain two cookies, a federation cookie for the RP part and a forms cookie (probably) for the STS part but it sounds impractical and against the idea of abstracting the authentication.
In a short way: this is not easily possible in my opinion. However, I would be glad to hear other ideas from someone.

Membership / Authorization over a REST service

I'm investigating creating a WCF REST service for an existing asp.net application to be consumed by various clients including Windows Phone 7, Android, iPhone apps etc.
Creating a simple WCF REST service and consuming it from the above platforms is not a problem and works really well. What I am struggling to get my head around is authorization.
The asp.net application uses the Membership provider to provide authentication and authorization and I'm comfortable in using that API from the REST service.
How do I secure my REST service so that the first call has to be to authenticate (passing the username and password) and following calls know who is 'logged in'. I'm guessing the authenticate method will have to pass back some sort of token to be used in subsequent calls identifying the caller. Is this secure enough as the whole site / service is over SSL?
Any suggestions welcome.
The more restful authentication scheme is to use HTTP Authentication, e.g. Basic or Digest. Since your service is over SSL, Basic should be sufficient. The authentification tokens (login/password) are sent with every request, so that the service can be stateless. Every client library that I'm aware of can deal with basic authentication.
In general the token approach is better then just sending username+password (Basic Authentication) in each request. The problem is to implement it correctly: while Basic Authentication is very easy to implement, and actually it's already implemented by most application and web servers, the token is something you'll need to implement yourself - it must be encrypted, so clients won't understand it, so you'll need some keys management, it also must have some expiration date and may be you'll want some revoke functionality.
In addition, it will make client's life harder: instead of just attaching basic authentication header to each request, client must first go to some authentication point, receive a valid taken and then use the token on the requests. If the token expires, the client will need to go to the authentication point again.
So if you have time and knowledge, and your clients are smart, it's better to use the token approach. Otherwise with SSL, basic authentication should be sufficient.
I've seen an example in the latest Windows Azure toolkit for WP7 that might be helpful for you. It basically uses the Membership Provider, logs in a person (the first time the person installs the app) and then generates a Ticket. It then Encrypts this ticket and sends it back as a TOKEN which is then stored on the phone in the isolated storage. The expiration of the ticket is set to int.MaxValue so that the token remains good for a long period of time.
Now, this token is passed over to the Web Services in the Authorization Header where it is decrypted, the identity of the user is verified and then the web service call is made.
Hoping this helps. I am trying to solve a similar scenario and trust me, there isn't much out there that points us in the right direction...which is a pretty sad state of affairs if you ask me.

Resources