I have started maintain a number of websites that are all authenticated using openam SSO. However when one of our users sets a persistant cookie (DProPCookie) it doesn't always work.
Repro scenario is:
Login to openam, setting the persistant cookie
Restart browser (to clear session cookies)
Go to site A, user is logged in automatically because of persistant cookie
Go to site B, user is presented a login page (they should be automatically logged in).
After step 3, if I delete the iPlanetDirectoryPro cookie from my browser I can login to site B fine (using the persistant cookie). It seems that the iPlanetDirectoryPro cookie generated from Site A when the DProPCookie is set doesn't work on Site B.
Note that I have tried with various permutations of Site A and B and the scenario is the same in each case.
I'm quite new to openam so any hints as to how to debug this would be great or if I'm missing something obviously going wrong please do let me know.
Thanks in advance.
EDIT:
I have subsequently discovered that the iPlanetDirectoryPro cookie returned when authenticating using the DProPCookie isn't working. So thus has nothing to do with cross domain.
Login to openam, setting the persistant cookie
Restart browser (to clear session cookies)
Go to site A, user is logged in automatically because of persistant cookie
Delete all cookies except iPlanetDirectoryPro cookie
Refresh page - asked to login
If I repeat the test but with the iPlanetDirectoryPro cookie generated by a normal login then when I refresh the page, I automatically get authenticated. (I have changed the title of the question to reflect this).
FURTHER EDIT:
Turned up debugging - am seeing this exception in the logs:
IdName is :null
amAuth:11/28/2012 05:11:25:750 PM GMT: Thread[TP-Processor2,5,main]
orgName is :xxx
amAuth:11/28/2012 05:11:25:750 PM GMT: Thread[TP-Processor2,5,main]
AuthD.getIdentity() from IdUtils Name: null Org: xxx
amAuth:11/28/2012 05:11:25:750 PM GMT: Thread[TP-Processor2,5,main]
AuthD.getIdentity: Got IdRepoException while getting Identity from IdUtils: Illegal universal identifier null.
amAuth:11/28/2012 05:11:25:750 PM GMT: Thread[TP-Processor2,5,main]
isLockedOut:Exception :
java.lang.NullPointerException
at com.sun.identity.idm.server.IdCachedServicesImpl.search(IdCachedServicesImpl.java:585)
at com.sun.identity.idm.AMIdentityRepository.searchIdentities(AMIdentityRepository.java:296)
at com.sun.identity.authentication.service.AuthD.getIdentity(AuthD.java:1453)
at com.sun.identity.authentication.service.AMAccountLockout.isMemoryLockout(AMAccountLockout.java:297)
at com.sun.identity.authentication.service.AMAccountLockout.isLockedOut(AMAccountLockout.java:281)
at com.sun.identity.authentication.service.AMAccountLockout.isLockedOut(AMAccountLockout.java:264)
at com.sun.identity.authentication.service.AMLoginContext.processPCookieMode(AMLoginContext.java:1919)
at com.sun.identity.authentication.service.AMLoginContext.processIndexType(AMLoginContext.java:1846)
A quick scan through the openam code - it appears that we are not getting a username here in AMAccountLockout.java:264:
public boolean isLockedOut() {
// has this user been locked out.
String userDN = loginState.getUserToken();
return isLockedOut(userDN);
}
Persistent Cookie mode has changed in OpenAM ... DProCookie is actually not used anymore.
Posssibly you're running 'restricted token mode' AKA 'cookie anti-hijack mode' and CDCServlet does not issue a proper authentication assertion
Could be that you are running into https://bugster.forgerock.org/jira/browse/OPENAM-1002 ?
Also it could be a problem with your cookie domains, maybe site B redirects to a different domain where DProPCookie is not visible?
Ultimately we discovered that the problem was that the SSO cookie generated by the persistant cookie had no authention modules - and therefore the authentication level was set to Integer.MIN_VALUE;.
In our situation we made a slightly hacky fix to force this to be 0 instead, which fixes up the problem.
I presume the correct thing to do would be to either have a seperate authentication module for persistant cookie logins or to store the authenticating module in the SSO cookie generated by the Persistant cookie.
Related
I have a web application with singe factor authorization and now have implemented two-factor authorization. I am using the Microsoft Identity for the log-in. The problem is - so far we have used a cookie to remember the user while providing the username and password. Say that as 'signglefactorcookie'. Now on the authenticator application authorization page(TFA), I have added another cookie for the remember me option. Say that as 'twofactorcookie'. Now how can I make my client request for both cookies when I use the below code?
// Check whether there is a valid session or persistent cookie
if(this.User.Identity.IsAuthenticated){
// Move to a landing page
}
Problem scenario
Now the problem is, if I log in to the single-factor authentication page with the correct user name and password and land at the two-factor authentication page.
Open a new tab and try to access the home page getting success since there is a single factor cookie that is recognized which makes the user authorized.
How can I make it in a standard way?
I have a solution for an authentication system without using refresh token. Please tell me where are the vulnerabilities of this method.
I assume the following:
Client and Server are on the same domain.
Client is a browser that support HttpOnly cookie.
Client is using a Single Page Application.
The steps are:
User login by making a request to /api/auth with the credentials.
Server authenticate the user and send back a Set-Cookie Header with an HttpOnly cookie containing a JWT.
Client receive and set the HttpOnly cookie. Client also set in Local Storage a variable logged: true.
After sometime User reopen the browser. The Single Page Application check if the variable logged in Local Storage is == true. If so check if it still has the HttpOnly cookie by making a request to /api/check-cookie.
Server respond with true if it find the HttpOnly cookie and it is valid. Otherwise false.
Client, if receive false from /api/check-cookie, will prompt the user with the login.
With this approach the JWT can have a long expiration date and there is no need to keep track of refresh tokens.
Am I missing something?
I like your thinking and had similar ideas, particularly with setting a local storage variable to reflect the state as logged in so I could check that before making a pointless server call to refresh a token that potentially doesn't exist, however, I'm still using the refresh token.
I believe the crux of your issues will be when the user updates on the server side, it won't be reflected on the client side until the user re-authenticates with a new long-lasting, singular token as opposed to when the short-lived access token refreshes, setting the user again with the updated data.
I have got forms authentication working in my website. But one thing I don't understand. I had a test website and a production website, both using identical database and code. When I logged into the test site, then try to go to the production one, I still need to login. Why?
I thought the login mechanism is this:
After user password is checked fine, the server insert a FormsAuthenticationTicket cookie into client's browser.
When browser attempt to go to a page that requires login, the server checks that cookie. If it is there, then it sends that page.
If my test site has placed that cookie into the browser, now that browser goes to the production site, how did the production site know "I didn't place this cookie and therefore I still require you to login"?
I found out. Because the authentication cookie is only visible to the website that inserted it. A cookie inserted by "www.mysite.com" is invisible to "www.othersite.com".
I am currently using httponly cookie based authentication to authenticate users through a website. On top of this I am creating a react native app which also has to authenticate users, ideally through the same endpoint. At this point users are able to log in through the app and the cookie is correctly send on each subsequent request using credentials: 'include' (fetch). However, if the app is restarted, the cookie does not persist.
So far my searching has led me to the following possible workarounds:
Manage cookies manually by extracting the cookie through something like webview or react-native-cookies, saving the cookie to storage and manually adding it to each subsequent request.
Implement a new endpoint that returns a token and have two authentication flows, one for the website and one for the app.
Have anyone been in a similar situation? Can you point me in the right direction, so not to over complicate my code base and ensure that I am not vulnerable to XSS or other token/cookie theft.
Thanks in advance.
To be honest I never implemented cookie based authentication in react native. How do you handle cookies now ? Basically the flow should be like this:
You authenticate with username and password.
Server will respond with a header "Set-Cookie: sessionIdExample=1234"
Next time when you make a request you should also send that cookie, meaning you have to set a header "Cookie: sessionIdExample=1234"
From your question I guess you don't manually set that cookie, so most probably the http client is doing this for you. Now when you close the app that cookie value is lost as you said. Notice that switching to a token based authentication won't help with this. So what should you do:
Login with username and password.
When you receive that session cookie persist it. You can check async-storage or the more secure react-native-keychain for persisting data.
For the following requests set the session cookie manually.
When you close the app and then open it again, check in your async-storage or keychain if you already have a cookie saved there. If so, set that cookie and everything should work fine.
This case is very much similar to question by Wiktor Zychla, see How to set the timeout properly when federating with the ADFS 2.0
We are experiencing the same behavior, ADFS happily redirects the user back to Sharepoint site and FedAuth cookie is recreated, even though ADFS should prompt for credentials - we want the user to reauthenticate after some period of idle time. Basically it looks like the session is always sliding.
We have disabled persistent cookies, so the FedAuth cookie is removed when session is ended by closing the browser, so the user is forced to reauthenticate after all browser windows are closed and a new session is started, so that works.
As far as I understand the Web SSO lifetime setting in ADFS Snap-in controls the time after which the user should need to re-authenticate on AD FS (enter his credentials again). Tokenlifetime and LogonTokenCacheExpirationWindow together control, when Sharepoint should redirect back to AD FS to in order to renew FedAuth cookie.
Following is a quote from http://msdn.microsoft.com/en-us/library/hh446526.aspx :
To force users to re-enter their credentials whenever they are redirected back to ADFS, you should set the web SSO lifetime in ADFS to be less than or equal to SAMLtokenlifetime minus the value of LogonTokenCacheExpirationWindow.
So, we have done following:
1. Setting the lifetime of SAML token
Add-PSSnapin Microsoft.ADFS.PowerShell
Set-AdfsRelyingPartyTrust –TargetName "[ourrelayingpartytrustreference]" –TokenLifeTime 7
2. Setting LogonTokenCacheExpirationWindow (and disabling persistent cookies)
Add-PSSnapin Microsoft.SharePoint.Powershell -EA 0
$sts = Get-SPSecurityTokenServiceConfig
$sts.UseSessionCookies = $true
$sts.LogonTokenCacheExpirationWindow = (New-Timespan -Minutes 1)
$sts.Update()
iisreset
3. Adjusted Web SSO lifetime: 5 minutes in AD FS 2.0 Management console snapin (running Get-ADFSProperties in Powershell correctly returns SsoLifetime: 5)
Thus the expected outcome is:
User starts a fresh new session, requests the web site
Browser is redirected to AD FS, user enter credentials, and browser is redirected back to Sharepoint site, FedAuth cookie is generated
User remains idle for 10 minutes (to make sure that session sliding period has passed)
User requests another page in Sharepoint, browser is redirected to AD FS
Since Web SSO lifetime was 5 minutes, and it was, as in msdn documentation instructs, less than SAMLtokenlifetime minus the value
of LogonTokenCacheExpirationWindow (SAMLtokenlifetime -
LogontokenCacheExpirationWindow = 6 minutes), AD FS prompts the user
for credentials, user enters credentials, and browser is redirected
to Sharepoint page requested and FedAuth cookie is recreated.
Current actual behavior (steps 1-4 similar):
(5.) AD FS does not prompt for credentials, browser is redirected to Sharepoint page and FedAuth cookie is recreated.
So - for us it looks like AD FS session never expires, no matter what we do.
If we create a false configuration of setting LogonTokenCacheExpirationWindow value higher than SAMLtokenlifetime (e.g. LogonTokecacheExpirationWindow = 8 and SAMLtokenlifetime = 7), we get the expected behavior of loop between Sharepoint and AD FS.
We are desperately seeking for a solution to properly expire the session, if user has remained idle for some period of time.
We also tried following configuration change (as per the guidance at http://social.msdn.microsoft.com/Forums/en-US/Geneva/thread/802b1bb6-cda3-4470-a0d1-ee709d5c4b7c/):
Set-ADFSProperties -SsoLifetime 1
Set-ADFSProperties -ReplayCacheExpirationInterval 1
Set-ADFSProperties -SamlMessageDeliveryWindow 1
No Global.asax changes yet made.
As far as I understand, we have configured everything according to the documentation, however we cannot force the user to reauthenticate. Any help pointing out the error in configuration is appreciated.
Apologies if you have already done this, but be sure you have restarted AD FS after making the websso changes. We did not get our expected results until we restarted the services. Also, if you have a proxy, may want to restart that as well.
Do you have any pieces of infrastructure that are rewriting the cookies?