SAML TOKEN LIFE TIME best practices - spring-security

what should be the saml token life time for SSO app.
are there any best practices for this ?
do we need to maintain application session equal to saml token lifetime ?

The SAML "token" lifetime is typically very short.
SAML messages including the response and assertion typically have an IssueInstant which states when the message was created.
In addition the Assertion typically has Conditions that include an NotBefore and NotOnOrAfter datetime and an AudienceRestriction. This basically states how long the Audience should trust that Assertion. The trust for the assertion has nothing to do with how long you keep the session active. Similar to any authentication method the user was authenticated at that specific Instant. The user account may have been disabled seconds later.
The Service Provider (Application) needs to decide how long it will keep that session active before prompting for the use to log in again. It is a risk based decision based on the security needs of the Application in question.
<Conditions NotBefore="2022-08-20T02:45:48.365Z"
NotOnOrAfter="2022-08-20T03:50:48.365Z">
<AudienceRestriction>
<Audience>https://netsaml2-testapp.local</Audience>
</AudienceRestriction>
</Conditions>
The example above give you a little more than an hour to trust the assertion. That may be a valid session length but I have also seen 5 minutes which might not be a appropriate session length. The condition is more aboout dealing with Clock Skew between the SAML parties than anything else.
The Assertion says that the user Authenticated successfully not how long you should keep the session active

Related

Google Calendar API v3 - Persistent Authorization with Code

Im wondering if anyone has any answers to this. If one follows the quickstart here:
https://developers.google.com/calendar/api/quickstart/go
we can get authorization from a user that allows us to do things with their calendar.
It seems the HTTP Client given back from the config handles calling the refresh token and keeping the client up to date.
First, as a side-question, does anyone know how long this is allowed to persist? I read in a doc somewhere that for unpublished apps/projects its 7 days, but it didn't specify a timeline otherwise. Is it indefinite or will this expire at some point (ie the refresh token runs out after 30 days). And is this avoidable at all?
now, the real question - if you take the service down entirely, ie for an update, and restart it, is there any way to opick up the authorization again? In the tutorial its writing a code to disk and reading as needed. In my case I just hold reference to the things I need in the application, so obviously when the service went down id have to reauthorize. I then tried writing the code to disk on a persistent volume and re-reading from that, but it doesnt get authorized - I guess because the new instance of the service has a new instance of the oauth config, and it wont accept the old code perhaps?
In any case, im wondering if anyone knows of a way to make this persist through ssytem restarts, or if the only real option here is to move the calendar service client to a small microservice on the side that we do not restart, and contact it from elsewhere as needed.
Thanks in advance!
The refresh token expiration is documented here. As you've noted, tokens expire in 7 days for projects in "Testing" status. Refresh tokens for projects in production last indefinitely, but there are some scenarios where they may get invalidated (user revokes access, token has not been used in 6 months, the account has over 50 live tokens, etc.). It's not mentioned but if you change your OAuth scopes you'll probably need to reauthorize as well.
This means that as long as you keep your refresh tokens and none of the invalidation conditions are met, you should be able to keep using them to get new access tokens even if your service goes down temporarily. But as mentioned in the documentation, you should anticipate the possibility that the token stops working and redirect the user to authorize again.
My guess is that in your case the refresh token stopped working for some reason (maybe the 7 days limit) and the application just tried to use the same expired token. The Quickstarts in Google's documentation usually handle the creation of the token file and how to reuse it, but they don't include the part where you have an invalid token and need to reauthorize.
References:
Google's OAuth2 Overview
OAuth2 for Web Apps

Doorkeeper refresh token and concurrency

In the current implementation of doorkeeper, When the access_token is refreshed doorkeeper also sends a new refresh_token.This is a valid implementation but it becomes problematic when there are concurrent apis calls from my client side (ios, android) calling to refresh the access token at the same time. This means that there will be at least 1 thread ending up with expired tokens that it cant refresh.
Anyone has solution for this race condition?
We've solved this before (not with doorkeeper) a couple of different ways.
Request Queue:
On our mobile apps we've implemented a request queue, and just before a request is made we check if the token needs to be refreshed then we pause the queue, refresh the token, then unpause again. No changes to the server required in this case
This has tradeoffs (you need to sync your request threads etc), but is pretty reliable at stopping the refresh contention without needing to modify the server.
Refresh jitter and JWT:
Since we are using JWT (where the access_token expiry is written into the token and not revoked at the server end), you can add a random number of "jitter seconds" to the refresh expiry each time you check. This decreases the likelihood of two requests trying to refresh at the same time. I used this in an AngularJS app that would get all confused with several tabs open. There was a random chance one tab would refresh before the rest, while the rest could continue to use their existing access_token until the new one was returned and updated.
This would probably also work without JWT if you can manage to get your access_tokens to stay valid when their corresponding refresh token is used, which would allow the 'other' requests to continue to use their 'old' token until the next time.
It's not entirely foolproof, but reduced the likelihood enough we were happy with it.
Expiry buffers for tokens:
The last way was when a refresh was executed, don't actually expire the token for another few seconds later so any 'concurrent' threads just get the new token returned. This was easy enough when I'd written the server component from scratch, but might not be so easy with doorkeeper. I think you'd get more milage from the other two approaches.

CAS and Spring-Security: regularly check if a ticket has expired

I have a CAS-Server and a Client configured via Spring-Security. Single Sign On and Single Logout are working fine so far.
I'm still facing an issue with session timeout. As I understand the ticket expiration policy is not affected by idleness of the secured CAS client side session. So a client must actively revalidate a ticket to see if it has expired and is not being posted the expiration event by the CAS server as it is the case when a single logout is performed.
To force my spring secured client to regularly check for the expiration of the ticket I might set the session timeout to a low value like a minute or so. But that has the drawback of all my session data to be removed. Not very user friendly.
Is there a way to tell spring-security to regularly check if a ticket is still valid without destroying the user session first?
I would be pretty confident on the Javascript solution as it's just a simple check to force local logout. Though, it needs to customize your CAS server, that you cannot do.
You have the solution of having a shorter session on application side to force regular re-authentication, but this means that you will invalidate often your application session and recreate it.
A better solution can be based on the gateway parameter of the CAS protocol : using this parameter will not produce a service ticket if you are not SSO authenticated. So you could have :
an application filter which, every 5 minutes, saves the current url, triggers a CAS round-trip with gateway=true and a specific service : http://myserver/myapp/checkCasSession
a specific url : /checkCasSession : if it receives a service ticket, everything is ok, the CAS session is still valid, it just restores the original url. If there is no service ticket, the local session must end and a local logout is triggered.
I think there is no such way. Spring Security and Spring Security Cas are implemented as a set of Servlet API filters / listeners. So Spring Security Cas works only during some Http request / Session event processing. I do not view any dependency on some scheduling library for spring-security-cas.jar.
It's not an easy problem you can address out of the box with Spring Security. You need to work on both sides : client and server. I would :
create a controller on CAS server side which returns a JSON indicating if the CASTGC has expired or not
every 5 minutes (for example) and each time an application page is displayed, add some javascript to call this specific CAS controller and if the CAS session has ended, ends also the application session.
You need to call the CAS server from front channel as the CAS session is held by the CASTGC cookie.
You have two sessions : the application one with its idle timeout and the CAS one with idle / hard timeouts. After having accessed the application through CAS login, the application session lives on its own and can last more than the CAS session. It's generally not a problem. What use case do you want to handle ?

Shared session timeout in a EAI + sso scenario

While using a SSO to integrate between disparate "web applications", the user might switch back and forth between these applications. As the user navigates between these applications, a local session gets created on each of the applications in addition to a session created at the Identity Provider that is used for sso.
So, the issue is when applications have different session timeouts, leading to a broken user experience. Session timeout occurs in one application while the user is working on another application. When navigating back into the application the user had visited previously, an error occurs. This is confusing to the user, since they are not aware that they are working on different applications.
One way to avoid the problem is to have a "global session" object that every application has access to. While the user is accessing any protected resource, the application checks if the global session exists and updates its timestamp before processing the request. The local sessions will never expire (or have a very long timeout). However, when the user logs out, global session object is evicted and the sign out happens on all the applications.
This seems to be a bit heavy handed due to:
Global session object becomes single point of failure
The performance to make a "out of process" check for the global
session object and update the timestamp on access of every
protected request
Any other thoughts on how to make this work?
When navigating back into the application the user had
visited previously, an error occurs.
I don't think that would be an error. The application will redirect the request to SSO provider and as the user is already have a valid SSO session it will be a successful SSO operation and the application can re establish a new/expired session.

Handling login functionality for native app connecting to web service

After extensive research, I have not been able to find a clear answer to my question. Firstly, can anyone tell me the basic logic of handling "login functionality" for a native iphone app connecting to a web service? For instance, the facebook app ask for a username and password immediately after launch, and from there you have full access to your account in all successive views of the app. Each time you post something etc, you do not have to re-login... Can someone please explain this process to me? Is it done through cookies or sessions? is Keychain involved?
I have a semi-working app right now but I'm almost positive I could be doing it better and more securely. Here is what I'm doing:
1) Set up a local server with a database of users (username and password columns and other tables etc.) using mysql. Wrote a simple web-service that takes in POST data and queries the database to check that the username exists... and if it does, that the passwords are equal. Using sha1 hashing. Echo true or false accordingly.
2) My app has an initial login screen with a 2 textfields (1 for username and 1 for password) and a button that calls the login method. My login method does the following:
init an *NSURL with a string (the url of my web service: #"http://webservice.com/login.php")
init an *ASIFormDataRequst with that url
set the post value with the password and email text in the text fields
set the delegate to itself
call startAsycronous on the request
implemented the requestFininshed method to retrieve the "true" or "false" echo-ed from the webservice
depending on the response, move forward to the next view, else, make an alert telling the user to retry
So, my questions are:
1) Is this secure for sending passwords? (via ASIHTTPRequest and the POST method?)
2) In the succeeding views, the user should be able to interact with their account (like posting messages and status's and pictures on the Facebook) How do I persist the user's logged in status so that every time the user interacts with the database, I can ensure that the user is still logged in and that it's the same user? For instance, the only way I can think of doing this is if I store a cookie on the users device with the username and password, and then every successive interaction with the web service / database, it does an authentication with the cookie values (username and password).
There has got to be a better way of doing this? Maybe sessions or cookies? or by using keychain??
Thanks for the help guys, and sorry for the long question!
Here are my thoughts based on what I know:
1) Is this secure for sending passwords? (via ASIHTTPRequest and the POST method?)
You need to make sure you are sending this information via https (SSL) and not a plain Http. The reason is, you don't have control over where the user wireless access point is. For all you know, the user could connect to open access point that is belong to a particular hacker. Having it transmitted will enable him to sniff the packet and get the required information to access the WebService even though the password is hashed. Having it send via https would ensure that the packet is encrypted with strong key. Even if a hacker manage to sniff the packet out, it will take him a long time before he/she is able to decrypt the message.
In the succeeding views, the user should be able to interact with their account (like posting > messages and status's and pictures on the Facebook) How do I persist the user's logged in status > so that every time the user interacts with the database, I can ensure that the user is still logged in
and that it's the same user?
One commonly employed method to do this is to get the session token after the user logged in. That is, you create a random generated ID that you return upon successful login. You would then map this token with the user id in the backend and it is associated with a session time out. You refresh this time out every time the user connects to a webservice and time it out after certain period to avoid breach of security. You would then persist the session token in your device and then used that for subsequent call. As long the session is alive then the user is logged in. As the token is associated with a specific user, you also ensure the identity of the caller.
To prevent someone else using other people token is the reason why you need SSL to secure the channel and prevent sniffing. Assuming that you have secured your connection channels, the only way to get the token is
to verify the identity via login
The phone is stolen by hackers who could take the token by inspecting the local storage.
The mapping is necessary so you could validate the token is a real token that has been associated with the user via login activity. Furthermore,for number 2, you can offer remote wipe out feature that basically kills the mapping and making that token invalid.
Another very important part of this token is the token cannot be guessable and have to be random cryptographically (see Randomness Recommendations for Security). If the token is only based on pseudo randomness, a clever hacker might be able to guess its algorithm and can guess its next/previous token and has a possibility of obtaining any valid token in the table.
There are many algorithm to generate this token. For example, Java Programming Language provides a SecureRandom class in order to provide cryptographically randomness and .NET has similar secure RandomGenerator class.
If you want to look at the algorithm OATH has proposed Time-Based One-Time Password Algorithm (TOTP) which is an extension of HOTP. Most of the languages/platforms would have the cryptographically strong random generator that you could leverage immediately though without you having to write it yourself.
Depending on your service implementation/platform, you might want to ask SO for a suitable class/module for cryptographically random generator such as the one asked here "How do you generate cryptographically secure random numbers with php"

Resources