Skip to main content

Overview

Proper logout implementation is critical for application security. Logout involves invalidating user sessions, revoking tokens, and clearing authentication state both on the client and server side.

Logout Flow

A complete logout implementation requires several steps:
  1. Revoke Tokens: Invalidate access and refresh tokens
  2. Clear Server Session: Remove session data from server-side storage
  3. Clear Client State: Remove cookies and client-side authentication data
  4. Optional IdP Logout: Redirect to Identity Provider logout (for SSO)

Revoke User Sessions

Scalekit provides session management endpoints to revoke active user sessions.

Revoke Single Session

Revoke a specific user session by session ID:

    Revoke All User Sessions

    Revoke all active sessions for a user (useful for security incidents):

      Clear Client-Side State

      Remove all authentication data from the client:
      // Clear all authentication cookies
      function clearAuthCookies(res) {
        const cookieOptions = {
          httpOnly: true,
          secure: true,
          sameSite: 'strict',
          maxAge: 0 // Expire immediately
        }
        
        res.clearCookie('access_token', cookieOptions)
        res.clearCookie('refresh_token', cookieOptions)
        res.clearCookie('session_id', cookieOptions)
      }
      
      // Clear client-side storage (if used)
      function clearClientStorage() {
        // Clear localStorage (avoid storing sensitive data here)
        localStorage.removeItem('user')
        localStorage.removeItem('preferences')
        
        // Clear sessionStorage
        sessionStorage.clear()
      }
      

      Identity Provider Logout (SSO)

      For SSO users, you may want to log them out of their Identity Provider as well:

      Single Logout (SLO) URL

      Redirect users to their IdP logout endpoint:
      app.post('/auth/logout', async (req, res) => {
        const userId = req.session.user.sub
        const sessionId = req.session.sessionId
        const organizationId = req.session.user.organizationId
        
        // Revoke session in Scalekit
        await scalekit.session.revokeSession(userId, sessionId)
        
        // Clear server session
        req.session.destroy()
        
        // Clear cookies
        clearAuthCookies(res)
        
        // Construct IdP logout URL
        const idpLogoutUrl = `${process.env.SCALEKIT_ENVIRONMENT_URL}/oauth/logout?` +
          `organization_id=${organizationId}&` +
          `post_logout_redirect_uri=${encodeURIComponent('https://yourapp.com/logged-out')}`
        
        // Redirect to IdP logout
        res.redirect(idpLogoutUrl)
      })
      

      Complete Logout Implementation

      Here’s a complete logout handler that combines all best practices:
      import { Scalekit } from '@scalekit-sdk/node'
      
      const scalekit = new Scalekit(
        process.env.SCALEKIT_ENVIRONMENT_URL,
        process.env.SCALEKIT_CLIENT_ID,
        process.env.SCALEKIT_CLIENT_SECRET
      )
      
      app.post('/auth/logout', async (req, res) => {
        try {
          // Security: Validate user is authenticated
          if (!req.session || !req.session.user) {
            return res.status(401).json({ error: 'Not authenticated' })
          }
          
          const userId = req.session.user.sub
          const sessionId = req.session.sessionId
          const organizationId = req.session.user.organizationId
          const logoutFromIdP = req.body.logoutFromIdP // Optional parameter
          
          // Step 1: Revoke session in Scalekit
          try {
            await scalekit.session.revokeSession(userId, sessionId)
            console.log(`Session ${sessionId} revoked for user ${userId}`)
          } catch (error) {
            // Log error but continue with logout
            console.error('Failed to revoke session:', error.message)
          }
          
          // Step 2: Clear server-side session
          req.session.destroy(error => {
            if (error) {
              console.error('Failed to destroy session:', error)
            }
          })
          
          // Step 3: Clear client-side cookies
          res.clearCookie('access_token', {
            httpOnly: true,
            secure: true,
            sameSite: 'strict'
          })
          res.clearCookie('refresh_token', {
            httpOnly: true,
            secure: true,
            sameSite: 'strict'
          })
          
          // Step 4: Redirect to IdP logout if requested
          if (logoutFromIdP && organizationId) {
            const idpLogoutUrl = `${process.env.SCALEKIT_ENVIRONMENT_URL}/oauth/logout?` +
              `organization_id=${organizationId}&` +
              `post_logout_redirect_uri=${encodeURIComponent('https://yourapp.com/logged-out')}`
            
            return res.redirect(idpLogoutUrl)
          }
          
          // Step 5: Return success response
          res.json({ 
            message: 'Logged out successfully',
            redirect: '/login'
          })
        } catch (error) {
          console.error('Logout error:', error)
          res.status(500).json({ error: 'Logout failed' })
        }
      })
      

      Security Best Practices

      Critical Security Practices:
      1. Always Revoke Server-Side: Revoke sessions on the server even if client-side logout fails.
      2. Clear All Authentication Data: Remove tokens, cookies, and session data from both client and server.
      3. Handle Errors Gracefully: Continue logout process even if individual steps fail.
      4. Log Security Events: Log all logout events for security auditing.
      5. Prevent CSRF: Protect logout endpoints with CSRF tokens.
      6. Logout on Password Change: Revoke all sessions when users change passwords.
      7. Session Timeout: Implement automatic session timeout for inactive users.

      Next Steps

      Session Management

      Learn about session validation and refresh

      API Overview

      Return to API documentation overview

      Build docs developers (and LLMs) love