Skip to main content
The logout flow allows users to terminate their sessions and sign out of the application. Kratos supports both browser-based logout with cookies and API-based logout with session tokens.

Flow types

Logout is handled differently for browser and API clients.

Browser logout

For browser applications using session cookies:
1

Create logout flow

Initialize a logout flow to get the logout URL and token:
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/logout/browser' \
  -H 'Cookie: ory_kratos_session=...'
Response:
{
  "logout_url": "https://{project}.projects.oryapis.com/self-service/logout?token=abc123...",
  "logout_token": "abc123..."
}
2

Visit logout URL

Redirect the user’s browser to the logout_url or submit the token:
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/logout?token=abc123...' \
  -H 'Cookie: ory_kratos_session=...'
The session cookie is invalidated and the user is redirected to the configured return URL.
Query parameters:
  • return_to - URL to redirect to after logout

API logout

For native applications using session tokens:
curl -X DELETE \
  'https://{project}.projects.oryapis.com/self-service/logout/api' \
  -H 'Content-Type: application/json' \
  -d '{
    "session_token": "your_session_token"
  }'
Response: 204 No Content The session token is immediately revoked.
A 204 response is returned even if the token was already revoked. This prevents leaking information about token validity.

Flow initialization

Browser flow initialization

Create a logout URL:
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/logout/browser?return_to=https://your-app.com' \
  -H 'Cookie: ory_kratos_session=...'
Error cases:
  • 401 Unauthorized: No active session exists
  • 400 Bad Request: Invalid return_to URL

Direct logout (browser)

Skip flow initialization by using a logout token from the session:
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/logout?token=<logout_token>' \
  -H 'Cookie: ory_kratos_session=...'
The logout token is included in the session response from /sessions/whoami.

Configuration

Configure logout behavior:
selfservice:
  flows:
    logout:
      after:
        default_browser_return_url: https://your-app.com/login
  
  allowed_return_urls:
    - https://your-app.com
    - https://app.example.com

Security considerations

Logout token validation:The logout token in the URL must match the logout token in the session cookie. This prevents CSRF attacks where an attacker tricks a user into logging out.

Token validation

When processing a logout request, Kratos:
  1. Extracts the logout token from the query parameter
  2. Fetches the session from the cookie
  3. Compares the tokens
  4. Only proceeds if they match

Return URL validation

Return URLs are validated against configured allowed domains to prevent open redirects:
selfservice:
  allowed_return_urls:
    - https://your-app.com
    - https://subdomain.your-app.com

AJAX logout

For single-page applications, use AJAX with JSON responses:
fetch('https://{project}.projects.oryapis.com/self-service/logout/browser', {
  credentials: 'include',
  headers: { 'Accept': 'application/json' }
})
  .then(res => res.json())
  .then(({ logout_url }) => {
    // Option 1: Redirect to logout URL
    window.location.href = logout_url
    
    // Option 2: Call logout URL with fetch
    fetch(logout_url, {
      credentials: 'include',
      headers: { 'Accept': 'application/json' }
    })
      .then(() => {
        // Logout successful - 204 response
        window.location.href = '/login'
      })
  })

Complete examples

# 1. Get logout URL
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/logout/browser?return_to=https://your-app.com' \
  -H 'Cookie: ory_kratos_session=...'

# Response:
# {
#   "logout_url": "https://{project}.projects.oryapis.com/self-service/logout?token=abc123&return_to=https://your-app.com",
#   "logout_token": "abc123"
# }

# 2. Visit logout URL
curl -X GET \
  'https://{project}.projects.oryapis.com/self-service/logout?token=abc123&return_to=https://your-app.com' \
  -H 'Cookie: ory_kratos_session=...'

# Browser is redirected to https://your-app.com
# Session cookie is cleared

Error handling

Cause: No active session exists.Solution: User is already logged out. Redirect to login or home page.

Session revocation

When a logout completes:
  1. The session is marked as revoked in the database
  2. Session cookies are cleared (browser flows)
  3. The session token becomes invalid immediately
  4. A SessionRevoked event is emitted (available in event streams)

CSRF protection

Browser logout flows are protected against CSRF:
  • The logout token acts as a CSRF token
  • The token must be present in both the URL and session cookie
  • Failed validation returns a 403 Forbidden error
API logout doesn’t require CSRF protection as it uses bearer token authentication.

Logout all sessions

To revoke all sessions for an identity, use the Admin API:
curl -X DELETE \
  'https://{project}.projects.oryapis.com/admin/identities/{identity_id}/sessions' \
  -H 'Authorization: Bearer ory_pat_...'
This immediately invalidates all sessions for the specified identity.

API reference

EndpointMethodDescription
/self-service/logout/browserGETCreate logout flow for browsers
/self-service/logout/apiDELETERevoke session token for native apps
/self-service/logoutGETComplete logout with token
All endpoints are defined in selfservice/flow/logout/handler.go:33-36

Build docs developers (and LLMs) love