logto
@logto/nuxt

The better Nuxt auth module for developers.

Logto Nuxt 3 SDK

VersionBuild Status

The Logto Nuxt 3 SDK written in TypeScript.

Check out our docs for more information.

Installation

Using npm

npm install @logto/nuxt

Using yarn

yarn add @logto/nuxt

Using pnpm

pnpm add @logto/nuxt

Get sample

A sample project can be found at playground.

Check out the full JS repo and try it with pnpm.

pnpm i && pnpm dev

The minimal configuration to run the playground is (use .env file for example):

NUXT_LOGTO_ENDPOINT=<your-logto-endpoint>
NUXT_LOGTO_APP_ID=<your-logto-app-id>
NUXT_LOGTO_APP_SECRET=<your-logto-app-secret>
NUXT_LOGTO_COOKIE_ENCRYPTION_KEY=<random-string>

Get an access token in the browser

Use the useLogtoAccessToken composable when the browser has to call an API directly, for example an external resource server:

<script setup lang="ts">
const { refresh, error, pending } = useLogtoAccessToken();

const load = async () => {
  const accessToken = await refresh();

  if (!accessToken) {
    // `not_authenticated` means the session cannot be refreshed; start a sign-in instead of
    // retrying.
    await navigateTo('/sign-in');
    return;
  }

  return $fetch('https://api.example.com/profile', {
    headers: { Authorization: `Bearer ${accessToken}` },
  });
};
</script>

Pass resource and organizationId to request a token for a specific API or organization, matching the server-side getAccessToken parameters:

const { refresh } = useLogtoAccessToken({
  resource: 'https://api.example.com',
  organizationId: 'org_123',
});

The composable requests the token from an SDK-managed endpoint, which defaults to /api/logto/access-token and can be changed with the pathnames.accessToken module option.

The refresh always runs on the server against the existing session: a still-valid token is reused, an expired one is exchanged through the refresh token, and the renewed session is written back to the cookies before the response is returned. The refresh token and the app secret never reach the browser.

Notes:

  • refresh() only runs in the browser. During SSR the state stays empty, so no access token is ever serialized into the server-rendered payload. Server-side code should use useLogtoClient() instead, which reads the token straight from the request-scoped client.
  • State is shared between every component using the same resource and organization, and concurrent refresh() calls share a single request.
  • When the session is missing or can no longer be refreshed, the endpoint responds with 401 and the error code not_authenticated, which is available as NotAuthenticatedErrorCode.

Request-specific sign-in options

Set module-level signInOptions for defaults shared by every sign-in. To override them for an individual request, register the logto:sign-in-options Nitro hook in a server plugin:

// server/plugins/logto.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('logto:sign-in-options', ({ event, signInOptions }) => {
    const prompt = getQuery(event).prompt;

    if (prompt === 'login' || prompt === 'consent') {
      Object.assign(signInOptions, { prompt });
    }
  });
});

Hook values override module-level defaults. The SDK still owns the callback redirect URI. Validate or allowlist request input before copying it into sign-in options.

Resources

WebsiteDocsDiscord