We put a lot of emphasis on the login step of an application: authentication methods, authentication factors, user identity protection, passwordless, single sign-on, etc. What about the logout step? Do you think it's so easy to implement that it doesn't deserve much attention?
Implementing logout may not be as easy as you think at first, especially in contexts where multiple actors may be involved in the login step, as it may happen in the Auth0 context.
This article will give you a high-level overview of logout issues and the different types of logouts. It will not go into the implementation details of logout, but you will get an idea of the complexity behind this apparently simple operation.
If you prefer, you can also watch this video on the same topic:
A Few Questions about Logout
An Arabic proverb reads: "Think of the going out before you enter". This highlights the importance of planning well for a way out before entering any environment, physical or virtual. This also applies to logging out of applications. Understanding how to properly log out of an application has the same weight as logging in.
Before you dive into the different types of logout, ask yourself a few questions that may help you understand how to implement it for your application needs.
What is the relationship between login and logout?
Login is the initial step in an authenticated session, which is a session that has an authenticated user associated with it. Logout is the final step of an authenticated session, that is, the last step in a session whose activities are bound to an authenticated user. Before the login and after the logout, any user activity in your application is not bound to an authenticated user but to a so-called unknown user, often called an anonymous user.
So, we can say that during the time between the login and the logout steps, your application knows who the logged-in user is.
How many authenticated sessions do you have?
In the Auth0 context, when your application user logs in by using the Universal Login page, Auth0 creates a new authenticated session. Likewise, when your application receives confirmation of user authentication from Auth0, it should create another new authenticated session.
The first session tracks the interaction between the user and the Auth0 server: let's call it the Auth0 session. The second session tracks the interaction between the user and your application: let's call it the Application session. The following diagram highlights these two sessions in the context of Auth0:
You can use a third-party Identity provider (IdP) to authenticate your users through Auth0. For example, you can allow your users to authenticate with their favorite social media providers, such as Google, Facebook, or Twitter. In this case, a third session is created in addition to the Auth0 session and the application session: the 3rd-party IdP session. The following diagram illustrates this new scenario:
Why do you need to log out?
This may seem like a strange question, but think a bit about it. What is the purpose of logging out of an application? Basically, it means terminating an authenticated session. All the information associated with the session must be destroyed so that unauthorized parties can't take it over. In other words, it's a security measure. But you should not underestimate that it also has an impact on the user experience, as you will see later.
Where do you want to log out from?
Again, this may seem like a silly question at first. Probably the most natural answer is: "I want to log out of the application". But as you learned earlier, there are scenarios where there are multiple authenticated sessions. Which of these sessions do you need to close? Just the application session? All sessions?
You will learn about the options in a moment.
Why do you ask these questions?
These questions (some of which are not yet answered) should help you think about the correct way to let your users log out of your application in your specific scenario. Carefully analyze the context of your application to find the right way to let your users log out. With these questions in mind, let's see what types of logouts are available.
Types of Logouts
I guess that it shouldn't sound weird at this point to talk about different types of logouts. Just as there are different ways to log in to your application, there are different ways to log out. Let's explore them.
Logging out of your application means closing your application session. How you close your application session depends on how it is implemented. For example, if your application is a regular web application, you might have implemented your session using a cookie and session storage on the server side. To close the user's session, your application should invalidate the cookie and clear the session storage. Handling your application session is your responsibility.
Closing your application session doesn't close the Auth0 session. This means that the user's session with Auth0 is still alive. Technically, this means that the user's browser still has a valid authentication cookie issued by Auth0. If the user accesses the Universal Login page to authenticate while the Auth0 session is still valid, they are not even prompted for their credentials. Their authentication status is confirmed, and a new ID token is issued.
The following diagram shows the session status after application logout:
It is up to you to decide whether this logout type is right for your application. You know your application business scenario and the user experience you want to provide to your users.
Suppose you don't want your user to be left with an active Auth0 session when they log out of your application. In this case, you must close both your application session and the Auth0 session.
As mentioned before, it is your responsibility to handle the logout of your application. To close the user's Auth0 session, your application must call the Auth0 logout endpoint. This way, the next time the user accesses the Universal Login page, they will be prompted for their credentials.
In short, when the user clicks the logout button in your application, you close your application session and then call the Auth0 logout endpoint.
The following diagram shows the session status after application and Auth0 logouts:
Check if this logout type is appropriate for your needs.
Suppose that your application allows users to log in with a third-party Identity provider, such as Google, via Auth0. As you've already seen, in this scenario, you have the sessions shown in the following diagram:
If you apply the application and Auth0 logout, the IdP session remains active.
This may be an acceptable scenario in some contexts. For example, most users use social logins to access multiple independent applications. If they use Google to access your application, there is a high probability that they are already authenticated with Google because they may have Gmail or some other open application that requires Google as the IdP. So, when your user logs out of your application by closing only the application session and the Auth0 session, they can still use Gmail or any other application they have logged in to through Google.
However, there are scenarios where this approach may not be appropriate. Consider the case where the third-party IdP is not a social media provider but an enterprise IdP. In these scenarios, you may want the user to log out of the IdP when they log out of your application. The Federated logout accomplishes this goal. After logging out of the application, the authenticated sessions involved in your scenario will look like this:
Note that not all third-party IdPs support Federated logout. Check which ones support it.
The Federated logout introduces some user experience challenges. While logging out of your application and Auth0 is expected by the user, logging out of a third-party IdP may be something unexpected and even annoying to the user. Consider a user who uses Google to access your application, and after they log out of your application, they are unable to access their email on Gmail because their authenticated session has been terminated. As a best practice, you should make your users aware that they are logging out of their third-party IdP. For example, you can require confirmation to log out of the third-party IdP. Alternatively, you can implement the logout function so that the user can choose whether or not to log out of their third-party IdP as well.
The logout scenarios analyzed so far assume that there is a single application and that the user logs out of that application. What happens when multiple applications are involved in the same authenticated session? What if the user logs out of the third-party IdP instead of your application? What is the desired behavior?
The following diagram illustrates this specific scenario:
The diagram shows a situation where two applications (Application A and Application B) share the same authenticated sessions: the Auth0 session and a third-party IdP session.
This scenario would be similar even without the third-party IdP. However, the inclusion of the third-party IdP makes explicit the case where the user logs out of it instead of one of the applications.
As said before, what to do when the user logs out of one of these applications or from the IdP depends on your business needs. In some scenarios, you may want to do nothing: the other applications will continue to work until the user logs out of them. In other scenarios, you may want to terminate the sessions of the other applications.
The logout that terminates the sessions of the other applications is usually called Global logout or Distributed logout. From a certain point of view, it can be seen as the counterpart of the Single Sign-On (SSO). For this reason, it is also known as Single Logout (SLO), especially in the context of SAML.
Basically, when a user logs out of one of the applications sharing the same authenticated session, a logout request is sent to the other applications. The details of how this happens depend on the specific protocol (e.g., SAML, OIDC), where the initial logout happens (one of the applications or the IdP), and the type of application (regular web application, SPA). This article will not go into those details. If you are curious, take a look at these docs:
- OpenID Connect Session Management. The OIDC specification for implementing Global logout by actively monitoring the user's current authentication status.
Front-Channel Logout. The OIDC specification for implementing Global logout when the browser notifies the IdP of the application session termination.
Back-Channel Logout. A high-level overview of the OpenID Connect Back-Channel Logout specification, i.e., when a regular web application communicates the termination of the application session to the IdP.
Best Practices for Application Session Management. A blog post about the best practices for checking and terminating authenticated sessions.
Of course, the same user experience issues we mentioned for the Federated logout also apply to Global logout.
Life after Logout
You have explored the different types of logouts you may encounter as you deal with increasingly complex scenarios. But what happens after the user logs out of your application? Since their authenticated session terminates, they are no longer authorized to access the protected pages of your application. Where will they be redirected?
This is mostly a user experience decision. You can redirect your users to the home page of your application, a specific page, or the authentication page (i.e., the Universal Login page). The choice is up to you, but there are a few points to keep in mind:
- When your logout involves Auth0 (i.e., it's not just an Application logout), you'll need to specify where to redirect the user. Learn how to do this based on the OIDC logout endpoint or the alternative logout endpoint.
- Register the URL of the page to which users will be redirected in the Allowed Logout URLs field of your Auth0 Application Settings in the Auth0 dashboard. This is a security measure to prevent URL injection attacks.
- Let's say you only use the Application logout or allow users to authenticate with a third-party IdP, but you don't use the Federated logout. In these cases, be sure to redirect users to an unprotected page after they log out. Otherwise, their active authenticated session with Auth0 or the IdP will re-authenticate them, and a new application session will start. The perceived effect is that the users will not log out of your application.
In this article, you were invited to ask yourself a few questions about when you are going to implement your logout function. These questions should help you choose the right approach to define the logout for your specific scenario.
Then you explored some logout types based on different scenarios: you started with a scenario where the simple Application logout might be enough and arrived at a scenario where multiple applications are involved, and you need a Global logout.
At the end of this article, I hope you now have an idea of the complexity behind the logout step. It may look easy at first, but in scenarios where multiple applications and multiple IdPs are involved, it becomes very challenging. The alternative to this complexity would be to discourage your users from logging out of your application. Is that what you want? 🙂