I rolled my own STS provider using WIF and also have a few apps which are Relying Parties. The session timeout on the STS provider is set to 30mins and so are the relying parties.
When a person wants to signout of the Relying Parties and the STS provider they issue a federated logout query parameter to the STS provider.
https://STSProvider.com/Default.aspx?wa=wsignout1.0
This creates a page with image tags that have federated logout requests for all the relying parties they are signed into.
The problem with this is that, since their session timed out on the STS provider then it kicks them back to the login screen. And the page with all the federated logout img tags for the relying parties are not served. So, the person stays logged in to all the relying parties.
What is the best way to handle a federated logout where the STS's session cannot be indefinate?
I suppose you authenticate the user on the STS using SessionSecurityToken. If that is the case you can try setting its IsPersistent property to true.
var token = new SessionSecurityToken(...args...);
token.IsPersistent = true;
Related
We have a web app in which we allow users to log into the app using any Open ID provider(e.g. Okta, Google, Facebook etc.). We want to implement the correct Open ID Connect prescribed methodology/workflow to keep the user logged into the site.
The existing implementation, looks at the expiry of the Access Token then if it's close to expiry uses a Refresh Token to get a new Access Token to keep the user logged in. I feel like this is wrong. When a user logs in to the web app, the Identity Token is used to Authenticate the identity of the user using the Authorization Code workflow. The Access Token and Refresh Token are stored on the server side. Periodically, the Refresh Token is used to get new Access Tokens to keep the user logged into the site. I believe this is a security risk because -
Imagine if a user is logged onto his OP account in a browser. He opens up Sky and is directly logged into MP because he’s already logged into MP. He then in a separate tab, logs out of his OP account. He will continue to be logged into MP for days on the basis of this Refresh Token/Access Token mechanism! Isn’t this a security risk?
If feel like the correct way to go about this is to use Session Management using iframes as prescribed here on OIDC -
https://openid.net/specs/openid-connect-session-1_0.html
For more context, when a user logs into our WebApp we pull data from the OP's UserInfo endpoint to create a profile within our WebApp and set permissions/roles within our app based on data sent over from the OP's UserInfo endpoint. We continue doing this periodically. For this purpose, I feel like using the Access Token(and using the Refresh Token to get new Access Token) to access the UserInfo API is correct because it conforms to the OAuth 2.0 concept of protecting/authorizing API/Resource endpoints using Access Tokens.
I want to know if this is indeed the correct way to manage how a user should be logged in when supporting Open ID Connect.
I think the first question is whether you want to bind the lifetime of an OpenID Connect provider Single Sign On session with the session of your application. You just want to authenticate a user using their OpenID Connect service. If I logout of Google, I expect to be logged out of GMail, but not a third-party application that used Google for authentication. Would you like to implement Single Sign Out as well?
But if I wanted to be logged out when you logout of the OpenID Connect provider, I would implement the OpenID Connect Session management. There is one thing good to be aware of when using iframes and cookies - browsers have an option to "Block third-party cookies" (that's how Chrome calls it), it's turned off by default, but as far as I know, it disables the SSO functionality when turned on.
I'm not sure why you request the userinfo endpoint periodically. If you just want to check whether the access token is still valid, you could also use the token introspection endpoint.
For security concerns, I would suggest you to read the OAuth 2.0 for Browser-Based Apps RFC. It recommends using the auth code flow with PKCE instead of the implicit flow. With the implicit flow, access tokens transported in redirect URLs stay in network and browser caches and can be used right away by an attacker. The auth code with PKCE needs a code_verifier (one-time secret) in order to be exchanged for tokens. So I would first check how the providers work with a configuration you choose and if it's even supported.
I was creating my own oauth2 server with SSO enabled for Google and Facebook. I found this example https://github.com/spring-guides/tut-spring-boot-oauth2 to be very useful and I was able to make my oauth2 server expandable after several tweaks.
For session storage, I used redis and everything seems to be working with the spring magics.
However I encountered a session problem when implementing logout. According to single sign on best practice, when a user logout from one client, all other clients with the same session from the auth server should also be logged out. So I added an endpoint for each client to invoke upon successful login to register it's name based on the user session from the auth server. However I noticed that each time I refresh the page on my client web app, I get a new session from the auth server. As a result, each time when I try to logout, the session associated with all registered clients will always become the old one.
I've been searching for solutions online but no luck yet. It would be greatly appreciated if someone could help me with this issue.
TL;DR version:
I implemented an oauth2 server with SSO enabled for Facebook with Spring Boot. After I successfully logged in with my Facebook account, I can see my client web app resources. Every time I refresh the page, I see a new session gets created from the oauth2 server and it gets stored in the redis storage and all the old sessions are kept in the storage as well.
UPDATE
It seems that all the new sessions are generated by anonymous users each time I refresh the page.
Ok after some digging, it turns out that anonymous user by Spring Boot is not much different from unauthenticated users, according to this doc https://docs.spring.io/spring-security/site/docs/current/reference/html/anonymous.html.
It makes sense that every time I refresh page a new session would generate. My problem was that I wasn't using the correct session ID when registering client app upon successful user authentication. Therefore I override "SavedRequestAwareAuthenticationSuccessHandler.java" file so that I can obtain client_id from the request parameter and then register the correct session ID obtained from the Authentication object to this client ID.
I have a portal application developed using spring security and mvc framework. This portal application connects to IDP (Developed using Spring security and spring saml) for authentication. if the user authentication is success,user will be navigated to homepage where multiple links are provided for external applications… When the user clicks on the application link, user should successfully navigated to the respective application without challenging login page.
Other applications are developed using struts and spring security. How do I make sure that when a link is clicked from the portal, either saml token or context is passed to other application so it will not ask for login.
Any help is greatly appreciated.
The most common flow for SAML is something like the following:
Application (called service provider, or SP) receives request (any request, like request for a business resource) from unauthenticated user
It redirects the user (most commonly via http redirect) to the IdP (in which the SP should already be registered)
If the user is not authenticated to the IdP (not logged in to SSO), a login form is presented and login is managed by the IdP until there is a user session with the IdP
If the user is already authenticated with the IdP (because either he was already or entered a correct user/password), the IdP issues its claim token and posts the user with the token back to the Assertion Consumer Service in the SP (the original application)
The Assertion Consumer Service (practically just an API endpoint) receives and validates the SAML token and creates an own application session with the user. Now the user is authenticated to the application (SP)
Upon the next request to the application (SP), there is already a session, so SAML is not involved
Note that if there is already a session with the IdP, all of this is seamless for the user. A bunch of redirects take place, but the user will just reach the application without entering credentials.
So the short answer to your question is that your external applications need to support SAML SSO and need to be registered with the identity provider, in which case they can just use the IdP for authenticating the user and signing the claims it may have.
I have configured WSO2 Identity Server as IDP and have two applications configured as SP. All working fine, except few things:
when I logged out from one application, another application don't see, that I was logged out
when I login into one application, another application don't see, that I was logged in
IMHO, there is main principles of SSO and SLO.
When I check SecurityContextHolder.getContext().getAuthentication() there is no changes after logout or login in another app.
Maybe I should call WSO2 page /samlsso before every load url?
What can I do wrong? How to retrieve from another app, that user logged out/logged in?
EDIT:
For example, WSO2 API Manager Store have such mechanism:
when I logged out from my application and reload Store page, then going redirection to main not logged page in Store. Same with login.
UPDATE:
I found problem in class org.springframework.security.saml.websso.SingleLogoutProfileImpl. When logout request is coming from WSO2 IS, than objects Authentication and SAMLCredential are nulls and error No user is logged in is occured, but for real user still logged in in Spring SAML application.
Same discussion was here, but with no effect :\
You have to verify whether both apps are calling Identity Server (IS) using the same host name. E.g. https://is.blahblah.com/samlsso.
IS session is based on cookies ('commonAuthId' and 'samlssoTokenId' cookies to be specific). If apps are calling IS using two different host names, there will be two different sessions created at the IS side. For SSO and SLO to happen both apps must share a single IS session.
We are using travelocity.com and avis.com web app for test SAML2 sso. You can found the more details here[1]. Further you can checked this documentation[2] Registering the two service providers in the Identity Server and followed the 1 to 8 steps.
[1] https://docs.wso2.com/display/IS500/Configuring+Single+Sign-On+with+SAML+2.0
[2] https://docs.wso2.com/display/IS500/Customizing+Login+Pages
I'm trying to understand how to make sure that a logged on user's account is still "valid" (where valid means for example not locked out, not deleted)
I've set up an identity provider using IdentityServer v3. On the "relying party"-side, I have an ASP.NET WebApi hosted using Owin. On the RP-side, I'm using UseOpenIdConnectAuthentication to install the OpenIdConnectAuthenticationMiddleware in the Owin pipeline.
What's working so far:
Any unauthenticated user visiting my web app is redirected to the login page on IdentityServer
The user logs on (I'm using the implicit flow)
The user is redirected back to my web app
My web app receives the JWT containing the id token and access token
My web app calls the user info endpoint to retrieve the claims using the access token
My web app creates a new ClaimsIdentity containing the claims my app is interested of. This is then persisted in a cookie, using:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
SlidingExpiration = true
});
This works fine, but I want some kind of hourly validation that the user is still "valid" from the identity servers perspective.
Is there some standard pattern how I should re-validate that a user account is valid? I don't want to force the user to log on again, I just want to confirm that a user can't stay on forever even if his user account is deleted.
You can send the user to the Authorization Server again with an OpenID Connect authentication request but with the additional parameter prompt=none as documented in the spec: http://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint If that returns successfully, the user is still logged in, else an error will be returned. The user will not be prompted in either case.