Skip to content

[Feature]: Use Redirect URL Returned by handleLogout in BaseAuthProvider #1791

@gugupy

Description

@gugupy

Description

Problem

Currently, all AdminJS authentication adapters (@adminjs/express, @adminjs/fastify, @adminjs/nestjs) handle logout by destroying the local session and redirecting to the login URL, for example:

router.get('/logout', (req, res) => {
  req.session.destroy(() => res.redirect(admin.options.rootPath + '/login'));
});

This works for simple local authentication but does not support OAuth/OIDC logout flows, such as with:

  • Keycloak
  • Auth0
  • Azure AD
  • Google Workspace

In these cases, AdminJS only clears the local session but never calls the provider’s logout endpoint — so the user remains authenticated at the provider level. When they revisit the login page, they are automatically re-logged in (silent login).

Why This Matters

Each OAuth provider has its own logout URL (e.g., Keycloak’s protocol/openid-connect/logout), and these need to be called explicitly.

Because AdminJS plugins manage logout internally and redirect immediately, there’s no clean way to integrate provider-specific logout behavior.

Suggested Solution

When the configured BaseAuthProvider implements handleLogout, and that function returns a redirect URL, the adapters should redirect to that URL instead of hardcoding the login redirect. This is help

// Current behavior
router.get('/logout', async (req, res) => {
  await provider.handleLogout(req, res);
  req.session.destroy(() => res.redirect(admin.options.rootPath + '/login'));
});
// Proposed behavior
router.get('/logout', async (req, res) => {
  const redirectUrl = await provider.handleLogout?.(req, res);

  // Always destroy the session
  if (req.session) {
    await new Promise(resolve => req.session.destroy(resolve));
  }

  // If handleLogout returned a URL, redirect there
  if (redirectUrl) {
    return res.redirect(redirectUrl);
  }

  // Otherwise, fallback to AdminJS login path
  return res.redirect(admin.options.rootPath + '/login');
});

Benefits

  • Proper OAuth logout support: enables redirecting to provider logout endpoints.
  • Backward compatible: existing providers continue to work if handleLogout returns undefined.
  • Minimal change: no breaking API changes or new interfaces.

Alternatives

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions