Skip to main content

User logout

Ory Kratos supports two logout flows:

  • Browser-based (easy): This flow works for all applications running on top of a browser. Websites, single-page apps, Cordova/Ionic, and so on.
  • API-based (advanced): This flow works for native applications like iOS (Swift), Android (Java), Microsoft (.NET), React Native, Electron, and others.

Self-service logout for server-side browser applications

To ensure that a logout was indeed intended by the user, Ory Kratos first generates a Logout URL for a given Ory Session Cookie. You can then open the Logout URL in the Browser.

After successful logout, the browser will be redirected either to the return_to query parameter from the initial request URL, or fall back to the default_browser_return_url value set in Ory Kratos' configuration file:

# kratos.yaml
import { Configuration, V0alpha1Api } from '@ory/client';
const kratos = new V0alpha1Api(new Configuration({ basePath: '' }));

const route = (req: Request, res: Response) => {
kratos.createSelfServiceLogoutFlowUrlForBrowsers(req.cookies['ory_kratos_session']).then(({data}) => {
.then(({ data }) => {
console.log(data.logout_url) // The logout URL
console.log(data.logout_token) // The logout token

// You can render the logout URL like so:
// <a href="{{data.logout_url}}>Logout</a>

// Or call the logout token:
// kratos.submitSelfServiceLogoutFlow(data.logout_token).then(() => {
// Logged out
// })

If an error occurs, the browser is redirected to the Error UI.

Self-service logout for client-side browser applications

Similar to server-side browser applications, Ory Kratos first generates a Logout URL for a given Ory Session Cookie. However, you can simply call the Logout URL using an AJAX request. Ory Kratos returns a 204 No Content response on success or an error otherwise.

The following scripts show you how to do the browser flow based on cURL. Prerequisites are a recent version of cURL and a registered account in Kratos.

Before we start, we need to log in:

# Username/email and password for an existing account

# We use this cookie jar to initiate the login flow

# Initialize the flow
flow=$( \
curl -s -H "Accept: application/json" --cookie $cookieJar --cookie-jar $cookieJar \
'' \

# Get the action URL
actionUrl=$(echo $flow | jq -r '.ui.action')

# Get the CSRF Token
csrfToken=$( \
echo $flow | \
jq -r '.ui.nodes[] | select("csrf_token") | .attributes.value' \

# Complete the login
session=$( \
curl -s --cookie $cookieJar --cookie-jar $cookieJar -X POST \
-H "Accept: application/json" -H "Content-Type: application/json" \
--data '{ "identifier": "'$username'", "password": "'$password'", "method": "password", "csrf_token": "'$csrfToken'" }' \
"$actionUrl" \

echo $session | jq

# Check the current user id
curl -s --cookie $cookieJar --cookie-jar $cookieJar -H "Accept: application/json" \ | \
jq -r ".id"

To log out, first get the generated Logout URL then point the Browser to it:

# Get the Logout URL
logoutUrl=$( \
curl -s --cookie $cookieJar --cookie-jar $cookieJar -H "Accept: application/json" \ | \
jq -r ".logout_url" \

# Complete the logout
curl -s --cookie $cookieJar --cookie-jar $cookieJar "$logoutUrl"

# Check the current user id again. It should be `null` after a successful logout
curl -s --cookie $cookieJar --cookie-jar $cookieJar -H "Accept: application/json" \ | \
jq -r ".id"

Self-service logout for API clients

API clients (such as native mobile apps) use Ory Session Tokens. To revoke such a token, call the logout API endpoint:

# Set your token here

curl -s -v -X DELETE \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
--data '{"session_token": "'$session_token'"}' \

> DELETE /self-service/logout/api HTTP/1.1
> Host:
> User-Agent: curl/7.64.1
> Accept: application/json
> Content-Type: application/json
> Content-Length: 53

< HTTP/1.1 204 No Content
< Cache-Control: private, no-cache, no-store, must-revalidate
< Vary: Cookie
< Date: Fri, 18 Jun 2021 09:42:04 GMT