# Logto Authentication and Authorization Flows: A Deep Dive into OIDC Implementation

> Explore how Logto implements OIDC and OAuth 2.0 for secure authentication and authorization. Understand its layered architecture for robust flows.

- Repository: [Logto/logto](https://github.com/logto-io/logto)
- Tags: deep-dive
- Published: 2026-07-06

---

**Logto implements a full OpenID Connect (OIDC) and OAuth 2.0 server that splits authentication and authorization into three logical layers: front-end entry points, core routing logic, and token services, enabling secure Authorization Code flows with PKCE support.**

The `logto-io/logto` repository provides a production-ready identity infrastructure that handles both **authentication** (verifying user identity) and **authorization** (granting resource access) through standard-compliant OIDC flows. This guide examines how the TypeScript codebase orchestrates the Authorization Code flow—the most common pattern used by Logto-based applications—from the initial login request through token validation and RBAC enforcement.

## Initiating the Login Flow: The `/api/authn` Endpoint

Every authentication journey begins at the `/api/authn` endpoint defined in [`packages/core/src/routes/authn.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/authn.ts). When a client application redirects a user to Logto, this route performs critical validation and session initialization.

```http
GET https://<logto-host>/api/authn?client_id=...&redirect_uri=...&response_type=code&scope=openid profile email

```

The implementation verifies the `client_id`, `redirect_uri`, `response_type`, and `scope` parameters against the database. Upon validation, it generates a **state token** to prevent CSRF attacks and stores it in the user's session using the session utility located in [`packages/shared/src/utils/session.ts`](https://github.com/logto-io/logto/blob/main/packages/shared/src/utils/session.ts). 

The endpoint then renders the **Experience UI**—Logto's customizable sign-in interface. If the application requires social login or enterprise SSO, the route triggers the appropriate connector flow while preserving the authentication context.

## Handling User Authentication: Connectors and Callbacks

### Social and Enterprise Connector Redirects

For external identity providers, Logto utilizes [`packages/core/src/routes/connector/authorization-uri.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/connector/authorization-uri.ts). This module generates the authorization URL for third-party providers (Google, SAML, OIDC connectors) and handles the redirect to the external authentication page.

After the user authenticates with the external provider, the provider redirects back to Logto's callback endpoint with an authorization `code`.

### The Callback Endpoint and Session Creation

The callback handling logic resides in [`packages/core/src/routes/callback.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/callback.ts). This critical component:

1. Receives the authorization `code` from the connector
2. Validates the stored **state token** against CSRF attacks
3. Exchanges the external provider's code for a **Logto internal session**
4. Sets a short-lived `logto_session` cookie
5. Redirects the user to the originally requested `redirect_uri`, appending the OIDC `code` that the client will exchange for tokens

The session creation process persists a lightweight entry in PostgreSQL containing the user ID, authentication method, and connector metadata via the utilities in [`packages/shared/src/utils/session.ts`](https://github.com/logto-io/logto/blob/main/packages/shared/src/utils/session.ts).

## Token Exchange: Issuing JWTs at `/api/token`

Once the client receives the authorization `code`, it makes a POST request to the token endpoint:

```http
POST https://<logto-host>/api/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
code=<code-from-callback>
redirect_uri=...
client_id=...
client_secret=...

```

The token issuance logic resides in the same [`packages/core/src/routes/authn.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/authn.ts) file (POST handler). This route validates the authorization `code`, retrieves the associated session, and generates three token types:

- **ID Token**: A signed JWT containing the user's `sub` (subject), `email`, profile claims, and optional custom claims
- **Access Token**: A JWT for calling Logto Management APIs or protected resources  
- **Refresh Token**: A long-lived token used to obtain new access tokens without re-authentication

Token signing utilizes the **JWK** service implemented in [`packages/core/src/routes/logto-config/jwt-customizer.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/logto-config/jwt-customizer.ts), which supports automatic key rotation and tenant-specific custom claims. The TTL cache utility in [`packages/shared/src/utils/ttl-cache.ts`](https://github.com/logto-io/logto/blob/main/packages/shared/src/utils/ttl-cache.ts) optimizes JWK retrieval performance.

The response follows the standard OAuth 2.0 format:

```json
{
  "access_token": "...",
  "id_token": "...",
  "refresh_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600
}

```

## Authorization: Enforcing RBAC and Scope Validation

### Resource and Scope Validation

When clients access protected resources, Logto validates the **access token** against configured permissions. The **resource route** in [`packages/core/src/routes/resource.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/resource.ts) handles resource registration, while [`packages/core/src/routes/role.scope.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/role.scope.ts) implements the scope-checking logic that maps token claims to permissions.

### Access Control Middleware

The enforcement layer lives in [`packages/core/src/routes/applications/application-access-control.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/applications/application-access-control.ts). This middleware:

- Extracts the `scp` (scope) claim from the access token
- Matches scopes against the tenant's **role-based access control (RBAC)** configuration
- Returns `403 Forbidden` for insufficient permissions or allows the request to proceed

This architecture separates **authentication** (proving identity) from **authorization** (checking permissions), allowing fine-grained access control without re-authentication.

## Session Management and Refresh Token Lifecycle

Logto maintains session state in PostgreSQL through the utilities in [`packages/shared/src/utils/session.ts`](https://github.com/logto-io/logto/blob/main/packages/shared/src/utils/session.ts). Each session contains the user ID, authentication method, and references to external connector data.

When access tokens expire, clients present the **refresh token** to `/api/token` with `grant_type=refresh_token`. The implementation:

1. Verifies the refresh token's signature and checks revocation status
2. Issues a new access token (and optionally a new refresh token)
3. Updates the persisted session to reflect the latest activity
4. Returns the new token set to the client

## Security Hardening Mechanisms

Logto adds several OIDC-compliant security layers beyond the basic protocol:

- **CSRF State Tokens**: Stored in sessions ([`session.ts`](https://github.com/logto-io/logto/blob/main/session.ts)) and validated during callback processing ([`callback.ts`](https://github.com/logto-io/logto/blob/main/callback.ts)) to prevent cross-site request forgery
- **PKCE Support**: Required for public clients (SPAs, mobile apps), enforced in [`authn.ts`](https://github.com/logto-io/logto/blob/main/authn.ts) through `code_challenge` verification
- **JWK Rotation**: Automatic signing key rotation managed in [`packages/core/src/routes/logto-config/jwt-customizer.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/logto-config/jwt-customizer.ts)
- **Replay Attack Mitigation**: Each authorization `code` is single-use only, persisted in the database with strict expiration timestamps in [`authn.ts`](https://github.com/logto-io/logto/blob/main/authn.ts)
- **Scope-Based RBAC**: Fine-grained permission model enforced through [`role.scope.ts`](https://github.com/logto-io/logto/blob/main/role.scope.ts)

## Implementation Example: Node.js SDK Integration

The following example demonstrates how the Node.js SDK mirrors the server-side flows described above:

```typescript
import { LogtoClient } from '@logto/client';

// Step 1: Generate the authorization URL
const authUrl = LogtoClient.buildAuthUrl({
  clientId: 'my-app',
  redirectUri: 'https://myapp.com/callback',
  scope: 'openid profile email',
  responseType: 'code',
});

// Step 2: Redirect the user to Logto
// User authenticates → Logto redirects to https://myapp.com/callback?code=...

// Step 3: Exchange the code for tokens
const tokens = await LogtoClient.fetchTokens({
  code: req.query.code,
  redirectUri: 'https://myapp.com/callback',
  clientId: 'my-app',
  clientSecret: 'secret',
});

// tokens.accessToken, tokens.idToken, tokens.refreshToken available

```

The SDK simply orchestrates the HTTP interactions; all cryptographic operations, session management, and protocol enforcement occur server-side within the routes referenced earlier.

## Summary

- **Logto implements a complete OIDC/OAuth 2.0 server** with the Authorization Code flow as the primary authentication mechanism, located in [`packages/core/src/routes/authn.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/authn.ts) and [`packages/core/src/routes/callback.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/callback.ts).
- **Connector architecture** supports social and enterprise SSO through [`packages/core/src/routes/connector/authorization-uri.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/connector/authorization-uri.ts), enabling external identity provider integration without custom protocol implementations.
- **Token lifecycle management** encompasses ID tokens, access tokens, and refresh tokens, with signing operations handled by [`packages/core/src/routes/logto-config/jwt-customizer.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/logto-config/jwt-customizer.ts) and session storage in [`packages/shared/src/utils/session.ts`](https://github.com/logto-io/logto/blob/main/packages/shared/src/utils/session.ts).
- **Authorization enforcement** separates concerns through [`packages/core/src/routes/role.scope.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/role.scope.ts) and [`packages/core/src/routes/applications/application-access-control.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/applications/application-access-control.ts), enabling fine-grained RBAC based on token scopes.
- **Security hardening** includes PKCE for public clients, CSRF state tokens, automatic JWK rotation, and single-use authorization codes to prevent replay attacks.

## Frequently Asked Questions

### What authentication protocols does Logto support?

Logto supports **OpenID Connect (OIDC)** and **OAuth 2.0** as its core protocols, implementing the Authorization Code flow, PKCE extension for public clients, and Client Credentials flow for machine-to-machine authentication. The implementation resides in [`packages/core/src/routes/authn.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/authn.ts) and adheres to the OIDC specification for token issuance and validation.

### How does Logto prevent CSRF attacks during authentication?

Logto generates a cryptographically random **state token** in [`packages/core/src/routes/authn.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/authn.ts) and stores it in the user's session via [`packages/shared/src/utils/session.ts`](https://github.com/logto-io/logto/blob/main/packages/shared/src/utils/session.ts). When the external provider redirects back to the callback endpoint in [`packages/core/src/routes/callback.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/callback.ts), Logto validates that the returned state matches the stored value, rejecting any requests where the state parameter is missing or mismatched.

### Where does Logto store session data?

Session data persists in **PostgreSQL** through the utilities defined in [`packages/shared/src/utils/session.ts`](https://github.com/logto-io/logto/blob/main/packages/shared/src/utils/session.ts). Each session record contains the user ID, authentication method, connector metadata, and expiration timestamps. This approach allows horizontal scalability while maintaining strong consistency for security-critical session validation during token exchanges.

### How does Logto enforce role-based access control (RBAC)?

Logto enforces RBAC through a multi-layer approach: [`packages/core/src/routes/role.scope.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/role.scope.ts) defines the scope-to-permission mappings, while [`packages/core/src/routes/applications/application-access-control.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/applications/application-access-control.ts) implements middleware that extracts the `scp` claim from JWT access tokens and validates it against the tenant's configured roles. If the required scopes are absent, the middleware returns a `403 Forbidden` response before the request reaches protected business logic.