I'm working on a roll-your-own Federation implementation. There are two RPs. SSO between the RPs does not work (erroneously). I suspect it has to do with the cookie that the STS is creating. The STS is writing a fedauth cookie for itself. From my understanding, it should be writing a Forms Authentication cookie?
When hitting the STS for the second time from the other RP I can see in the ClaimsPrincipal that IsAuthenticated=True, yet the user is prompted to login and not automatically redirected back to the RP.
It's worth noting that SSO did work previously, auto redirect and all, but the RPs on the load balancer couldn't share cookies as it was using the machine key (and no sticky sessions). I fixed this by implementing a custom SessionSecurityTokenHandler that utilizes the certificate (code below). It's at this point that the STS started writing FedAuth cookies and SSO started failing.
The sts token is being written with:
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(token);
Token handler:
var sessionTransforms = new List<CookieTransform>(new CookieTransform[]
{
new DeflateCookieTransform(),
new RsaEncryptionCookieTransform(federationConfiguration.ServiceCertificate),
new RsaSignatureCookieTransform(federationConfiguration.ServiceCertificate)
});
var sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());
federationConfiguration.IdentityConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
The STS writes its own cookie. It POSTs the security token to your application. Your application will typically respond by writing a session authentication cookie, which it will use until it expires (and then it goes back to the STS)
If you work in a web farm then there is an out of the box support for this using WIF configuration :
Of course, the machines in the web farm should then share the same machine key. You can of course use your own mechanism but that seldom makes sense.
Next, each RP should therefore write its own "session" cookie that proves your authentication. If two RP's live in the same domain then they should use a different cookie name.
Related
I would like to enable extended (virtually forever) authentication for my web/mobile application, similar to how many popular sites operate (e.g. Facebook), virtually never needing to re-log in unless your credentials are changed from another terminal or the session is deliberately ended server-side. I am currently evaluating Apache Shiro. I have not yet been able to find a way to support dropping a cookie with some kind of access token that would be submitted every time the site is revisited so that the user does not need to log in again. Is there a way to do it?
Yes,
You can configure the session cookie's MaxAge:
https://shiro.apache.org/web.html#session_cookie
Using the bean properties of the cookie: https://shiro.apache.org/static/current/apidocs/org/apache/shiro/web/servlet/SimpleCookie.html
I'm not sure I'm following the last bit about access tokens and cookies though.
Typically, using a session cookie is default functionality for web apps running on most Java Servlet containers (this differs once you get into REST API frameworks)
I'm building a platform on .Net5 that will consist of at least 3 MVC web applications: User, Admin, Product. Authentication is performed on the User application where we can take a Username/Password to log the user in. The User Application also has the Forgot Password/Reset Password, etc functionality on it. Authorization is claims based. Based on this document I believe I would fall into Figure 9-2 Authentication by identity microservice, where my other microservices are web applications rather than APIs.
The issue I'm running into is trying to figure out the proper way to implement this.
Do I use JWT or Cookies for this? The article above does have a link for cookie sharing but wouldn't JWT be appropriate?
If I did use JWT, how do I pass it back to the server if I used something like #Html.ActionLink? Or is it expected that I would be using a front end framework like React and thus making any calls back to the server manually?
Again, if I'm using JWT, how would I pass it from the User application to the other applications?
I am implementing front-channel SAML 2.0 SSO golang Service Provider, with Okta as my Identity Provider (this is just a POC and should eventually work with any IdP).
Implementing the sign on process was straightforward with saml2 package. I've created the login endpoint that redirects to the SAML application login URL at the intended IdP, as well as the POST callback endpoint which is properly receiving the SAML assertion and is able to validate it. After that a session with a random cookie is created with the same TTL as the Identity Provider session TTL. So far everything works well (I haven't implemented Single Sign-Out yet, but I'm planning to).
However, when some time passes and the session expires, I'd like to renew it only if the user is still logged in with the Idp and hasn't been removed from the SAML Application. I would like to avoid redirecting the user to perform SSO again with IdP, because it would mean that if they are still logged in, they would be redirected back to the home page of my application. I wasn't able to find great sources on my options to go about it online.
Questions:
1.1 One solution that comes to mind is storing the requested URL in the RelayState parameter, whenever the session has expired, then redirect the user to the IdP SSO URL. When the redirect returns to the SAML callback POST endpoint, check the RelayState parameter and if set, redirect back to that (original) URL. That means that for users that use the system continuously, I would have to request Assertions very often. Does that make sense?
1.2 A second solution that comes to mind is to implement a back-channel of communicating directly from my SP to the IdP. That would allow me to verify a user is still logged in 'behind the users back'. If that's a sound idea:
a. Do I need to have dedicated code for each IdP?
b. Do I need to load an API key to the IdP which would allow secure communication?
c. Do I need to upload a public certificate to the IdP that would be able to verify that my SP signed the requests?
Will using the Assertion to get an OAuth 2.0 Access Token help me in achieving this?
I've chosen SAML 2.0 for now, since the environment is an enterprise oriented one and I thought it fits well with it based on what I read. Would using OpenID Connect instead help achieve my goals easier and fit well with enterprise oriented products?
I am beginner in using CAS and i'm using it in one of my project to use its Single Sign On services. Till now i have implemented Single sign on, I have one JAVA client and a PHP Client. But for using Single Sign Out functionality i configured my running CAS according to CAS documentation. I have done all the changes in the deployerConfigContext.xml of my working CAS. My CAS is up running, but on logging out it doesn't show any SAML logout request. I'm using Official PHP Client and Java Client made by me. I think it may be due to these lines which i'm not able to configure it in my Client side.
The way the notification is done (back or front channel) is configured at a service level through the logoutType property. This value is set to LogoutType.BACK_CHANNEL by default.
I'm not able to understand by this line where actually i had to set the Logouttype to BACK_CHANNEL, if its my Client then why is it that it is set to BACK_CHANNEL by default as a Client can be made by anyone.
Any help is highly appreciated.
Thanks in Advance.
Take a look at the jasig documentation: http://jasig.github.io/cas/development/installation/Logout-Single-Signout.html
When a CAS session ends, it notifies each of the services that the SSO
session is no longer valid, and that relying parties need to
invalidate their own session.
This can happen in two ways:
CAS sends an HTTP POST message directly to the service ( back channel communication): this is the traditional way of performing
notification to the service.
CAS redirects (HTTP 302) to the service with a message and a RelayState parameter (front channel communication): This feature is
inspired by SAML SLO, and is needed if the client application is
composed of several servers and use session affinity. The expected
behaviour of the CAS client is to invalidate the application web
session and redirect back to the CAS server with the RelayState
parameter.
And the important part:
Usage Warning!
Front-channel SLO at this point is still experimental.
So your SSO server sends a request to the application directly. The authenticator recognizes that this request is a special one and logouts the referenced user.
Update:
Take a look at the following links:
https://wiki.jasig.org/display/casum/single+sign+out
https://github.com/Jasig/cas/blob/6c3df3a5f42d2d8b771ba773aeda3ba5a4c525e3/cas-server-webapp/src/main/webapp/WEB-INF/spring-configuration/applicationContext.xml
https://github.com/Jasig/cas/blob/6c3df3a5f42d2d8b771ba773aeda3ba5a4c525e3/cas-server-core/src/main/java/org/jasig/cas/logout/LogoutManagerImpl.java
Did you accidantly remove or overwrite your logoutManager declaration in your applicationContext? Is there an logoutManager bean in your running spring context?
I would start by setting break points in the handleLogoutForSloService, performBackChannelLogout and performLogout methods of LogoutManagerImpl.java.
Are they beeing called?
Can you step through them?
Is performBackChannelLogout called?
Is this.httpClient.sendMessageToEndPoint(msg) in performBackChannelLogout successful?
If you are logged on to 2 services, performBackChannelLogout should be called twice with both service urls.
I'm currently making tests with the CAS server 3.5.2 and I'm facing
problems with the logout.
My knowledge in these topics is limited and I don't manage to go further on
that point.
I installed a CAS server and I've got 2 instances of the same java
application that point to that CAS server (appologize if I don't use the
adecuates terms).
So, when I access to the protected resources of my client aplication, I'm
redirected to the CAS login page, I check in my DB if credentials are ok
and then I access the resource. Then, if I access to the same protected
resource from the second instance of the client application I'm not
redirected to login page. That's perfect.
The problem is situated in the logout. To do so, I first execute a
session.invalidate() and access to the CAS logout page. It's ok because,
from the application from which I logged out, I must login again to access
the protected resources. On the other side, the second application remains
connected and I can access the protected resources without login again.
Well, I know that the session.invalidate() is local to the first
application but I thought that CAS server would have "broadcasted" the
desconnexion to the other application but no.
Is there somebody who can give me experience feedback for the single sing
out topic ?
First make sure that SSO is enabled in the CAS properties file, if not make sure the SSO Listener is enabled in the clients.
If they are enabled then my guess would be the issue is in either the LogoutManagerImpl.java or SamlCompliantLogoutMessageCreator.java files.
The SSO in CAS is performed through the back-channel by transmitting a SAML XML message.
I had an issue with the SSO function last year only to find out that the XML message being broadcasted had an error that prevented it from being parsed.
Finally I solved...
In web.xml, the order of filters is important. Filters for Single-sign out must be placed at the begining.
See that section https://wiki.jasig.org/display/CASC/CAS+Client+for+Java+3.1#CASClientforJava3.1-OrderofRequiredFilters