# How to Troubleshoot Common Authentication Issues in Logto: A Complete Developer’s Guide

> Troubleshoot common Logto authentication issues. Learn to fix missing interaction states, invalid tokens, and SSO connector problems with this developer guide.

- Repository: [Logto/logto](https://github.com/logto-io/logto)
- Tags: how-to-guide
- Published: 2026-07-05

---

**Most Logto authentication failures stem from three root causes: missing interaction states in session storage, invalid or expired one-time tokens, or misconfigured SSO connectors.**

When users can’t sign in to your application, the issue usually traces back to how Logto manages the sign-in flow state, validates temporary credentials, or communicates with external identity providers. Understanding the exact error patterns in the `logto-io/logto` source code lets you diagnose problems in minutes rather than hours.

## Diagnosing Interaction State Failures

Logto’s authentication flow relies on **interaction objects** stored in session storage. When a user initiates sign-in, the server creates an interaction of type `InteractionEvent.SignIn`. If subsequent requests can’t retrieve this object, the flow breaks immediately.

### What Happens When Interactions Go Missing

The [`submit-interaction.ts`](https://github.com/logto-io/logto/blob/main/submit-interaction.ts) handler expects to find a stored interaction before processing authentication results. If the session storage lacks the expected record, Logto returns a `404` error with the code `session.not_found`. This commonly occurs when:

- The client calls the submit endpoint without first creating an interaction via the SSO authorization endpoint.
- A server restart or cache flush clears the session storage before the flow completes.
- Multiple concurrent requests corrupt the stored state.

### Where the Logic Resides

According to the Logto source code, the critical paths are:

- **Submission handler**: [`packages/core/src/routes/interaction/actions/submit-interaction.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/actions/submit-interaction.ts) calls `assignInteractionResults` after processing.
- **Storage helpers**: [`packages/core/src/routes/interaction/utils/interaction.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/utils/interaction.ts) contains `storeInteractionResult` and `clearInteractionStorage`.
- **SSO routes**: [`packages/core/src/routes/interaction/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/single-sign-on.ts) logs interaction updates via `createLog(`Interaction.SignIn.Update`)`.

### How to Diagnose Interaction Errors

Check the `oidc_model_instances` table directly when you suspect state corruption:

```sql
SELECT * FROM oidc_model_instances WHERE id = '<interaction-id>';

```

Verify the interaction exists via API before submitting:

```bash
curl http://localhost:3001/api/interaction/1234 \
  -H "Cookie: your-session-cookie"

# Expect 200 if valid, 404 if missing

```

Review server logs for the specific interaction event:

```ts
// Look for this log pattern in your output
createLog(`Interaction.SignIn.Update`);

```

### Quick Fixes for Interaction Issues

1. **Ensure proper flow order**: The client must call `POST /interaction/sso/:connectorId/authorization-url` before posting authentication results. This endpoint creates the interaction object.
2. **Clear stale state**: Use the `clearInteractionStorage` helper (line 96 in [`submit-interaction.ts`](https://github.com/logto-io/logto/blob/main/submit-interaction.ts)) or restart the development server to wipe corrupted sessions.
3. **Verify interaction type**: Confirm the stored JSON shows `"event": "SignIn"` if you expect a sign-in flow, not `"Register"` or `"ForgotPassword"`.

## Resolving One-Time Token (OTT) Validation Errors

Logto uses **one-time tokens** for auto-consent flows and passwordless email login. The `koa-consent-guard` middleware validates these tokens against the current session, but strict validation rules often cause unexpected redirects to the switch-account page.

### Common OTT Failure Modes

The consent guard in [`packages/core/src/middleware/koa-consent-guard.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/middleware/koa-consent-guard.ts) enforces three strict conditions:

- **`one_time_token.token_consumed`**: The token was already used (lines 44-48).
- **Mismatched `login_hint`**: The session’s primary email differs from the URL parameter (lines 38-41).
- **Missing parameters**: The request lacks either `one_time_token` or `login_hint` (lines 31-40).

### How to Diagnose Token Problems

Inspect the primary email comparison logic when users see unexpected account-switch prompts:

```ts
// From koa-consent-guard.ts
if (primaryEmail !== loginHint && !hasLoginPrompt(prompt) && !hasMatchingLastSubmittedLogin) {
  // Redirects to switch-account
}

```

Check token consumption status using the library directly:

```ts
import { checkOneTimeToken } from '@logto/core/libraries';

const tokenInfo = await checkOneTimeToken(token, loginHint);
console.log('Consumed:', tokenInfo.consumed);

```

Look for redirect patterns in your network logs:

```ts
// Error pages appear as redirects to:
/experience/one-time-token?errorMessage=one_time_token.token_consumed

```

### Quick Fixes for OTT Issues

1. **Regenerate tokens**: Call `/api/experience/one-time-token` to create a fresh token after consumption.
2. **Match email hints**: Ensure the `login_hint` query parameter exactly matches the user’s primary email in Logto. Typos in the domain or casing cause immediate rejection.
3. **Prevent double-submission**: Clear the token from your UI state immediately after a successful login to prevent users from clicking "Back" and resubmitting consumed tokens.

## Fixing SSO Connector Lookup Problems

When users select an enterprise identity provider (Google, Azure AD, Okta), Logto must resolve the connector configuration and generate an authorization URL. Failures here typically manifest as `404 Not Found` or `422 Unprocessable Entity` responses.

### Connector Resolution Failures

The SSO flow in [`packages/core/src/routes/interaction/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/single-sign-on.ts) fails when:

- The connector ID doesn’t exist in the database.
- The connector lacks the requested operation (e.g., missing `authorization-url` route).
- The callback payload from the identity provider violates the `authorizationUrlPayloadGuard` schema.

### Where the Logic Resides

Key files for connector troubleshooting:

- **SSO route handlers**: [`packages/core/src/routes/interaction/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/single-sign-on.ts) (creates auth URLs and processes callbacks).
- **Library functions**: [`libraries/sso-connector.ts`](https://github.com/logto-io/logto/blob/main/libraries/sso-connector.ts) (line 175 handles default prompt selection).
- **Authorization URI builder**: [`packages/core/src/routes/connector/authorization-uri.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/connector/authorization-uri.ts).
- **OIDC connector implementation**: [`packages/core/src/sso/OidcConnector/index.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/sso/OidcConnector/index.ts) contains the `getAuthorizationUrl` method.

### How to Diagnose Connector Issues

Verify connector existence in the database:

```sql
SELECT * FROM connectors WHERE id = '<connector-id>' AND enabled = true;

```

Check domain filtering (affects connector availability):

```ts
// The SSO selection endpoint filters by email domain
GET /interaction/sso/connectors?email=user@company.com

```

Validate payload structure against the guard:

```ts
// authorizationUrlPayloadGuard expects specific fields
koaGuard({ body: authorizationUrlPayloadGuard })

```

Inspect the connector’s URL generation:

```ts
// From OidcConnector/index.ts
return `${oidcConfig.authorizationEndpoint}?${queryParameters.toString()}`;

```

### Quick Fixes for SSO Problems

1. **Refresh connector configuration**: Run `pnpm cli connector link -p .` from the Logto root to re-link connector packages and update the database entries.
2. **Validate domain lists**: Ensure the connector’s `domains` field in the database includes the user’s email domain, or the connector won’t appear in the selection list.
3. **Check credentials**: Verify the connector’s `config` JSON contains valid `clientId` and `clientSecret` values; missing credentials cause silent failures during the token exchange phase.

## Step-by-Step Authentication Debugging Workflow

When you encounter an unexplained authentication failure, follow this systematic approach using Logto’s internal libraries:

```ts
// 1️⃣ Reproduce the failure
const response = await fetch('http://localhost:3001/api/interaction/12345/submit', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ event: 'signIn', identifier: { ... } }),
});

// 2️⃣ Verify interaction existence
const interaction = await queries.interactions.findInteractionById('12345');
if (!interaction) {
  console.error('Interaction missing — client likely skipped SSO auth step');
}

// 3️⃣ Check one-time token status (if applicable)
const tokenStatus = await libraries.oneTimeTokens.checkOneTimeToken(token, loginHint);
if (tokenStatus.consumed) {
  console.error('Token already used, generate new token');
}

// 4️⃣ Validate SSO connector (if using enterprise login)
const connector = await libraries.ssoConnectors.getSsoConnectorById(connectorId);
if (!connector) {
  console.error(`Connector ${connectorId} not found in database`);
}

// 5️⃣ Inspect logs for interaction updates
// Look for: Interaction.SignIn.Update in your logging pipeline

```

## Summary

- **Interaction state errors** trigger `session.not_found` (404) when the sign-in flow starts without proper session initialization or when storage clears prematurely.
- **One-time token failures** occur when tokens are consumed twice, `login_hint` parameters mismatch the user’s primary email, or required parameters are missing from the request.
- **SSO connector issues** result from invalid connector IDs, domain mismatches, or corrupted configuration stored in the `connectors` table.
- **Diagnostic locations** focus on [`packages/core/src/routes/interaction/actions/submit-interaction.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/actions/submit-interaction.ts), [`packages/core/src/middleware/koa-consent-guard.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/middleware/koa-consent-guard.ts), and [`packages/core/src/routes/interaction/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/single-sign-on.ts).

## Frequently Asked Questions

### Why does Logto return "session not found" even though the user just started signing in?

This error indicates the interaction ID provided to the submit endpoint has no corresponding record in the session storage. According to the Logto source code in [`submit-interaction.ts`](https://github.com/logto-io/logto/blob/main/submit-interaction.ts), the server expects an existing `InteractionEvent` object created by prior calls to `POST /interaction` or the SSO authorization URL endpoint. If your frontend calls the submit endpoint directly without the preliminary interaction setup, or if the server restarted and cleared Redis/DB sessions, this error appears immediately.

### How can I debug why one-time tokens keep showing as "consumed"?

The [`koa-consent-guard.ts`](https://github.com/logto-io/logto/blob/main/koa-consent-guard.ts) middleware marks tokens as consumed immediately after validation to prevent replay attacks. If users see this error, check for double-submit scenarios where the browser sends the request twice (common with aggressive form submissions or "Back" button usage). You can verify token status by calling `libraries.oneTimeTokens.checkOneTimeToken(token, loginHint)` from your debug console. To fix, generate a fresh token via the `/api/experience/one-time-token` endpoint and ensure your UI clears the token from state immediately after the first successful submission.

### What causes "Connector not found" errors when using SSO?

This error originates in [`packages/core/src/routes/interaction/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/single-sign-on.ts) when the provided `connectorId` doesn’t match any record in the `connectors` database table. First, query `SELECT * FROM connectors WHERE id = '<your-id>'` to confirm the connector exists and `enabled = true`. If missing, run `pnpm cli connector link` to re-register the connector. Also verify the connector supports the requested operation—some legacy connectors may lack the `getAuthorizationUrl` method required by the SSO flow, causing the route handler to return 404 during the authorization phase.