Logto provides official SDKs for multiple frameworks, but the integration approach depends on your app type:
- SSR / full-stack frameworks (Nuxt, Next.js, etc.) typically need a server-aware SDK that can safely store secrets and manage redirect-based flows on the server.
- SPA frameworks (Vue, React, etc.) typically use a client-side SDK and rely on redirect-based login without server secrets.
In this guide, you’ll implement Logto authentication twice:
1) Nuxt 3 (SSR) using @logto/nuxt
2) Vue 3 (SPA) using Logto’s Vue SDK
No fluff — just a production-ready, copy-paste-friendly walkthrough.
Before you start: create a Logto app in the Console
In Logto Console, create an application that matches your framework:
- For Nuxt 3, create a Traditional Web application.
- For Vue 3, create a Single Page Application (SPA) application.
You’ll need these values for both setups:
- Endpoint (your https://logto.io/ tenant URL)
- App ID
- (Nuxt only) App Secret
Part 1 — Nuxt 3 (SSR): add authentication with @logto/nuxt
Nuxt is often deployed with SSR (or hybrid rendering). Logto’s Nuxt SDK is designed for SSR and uses secure cookies + server-side handling to complete authentication.
1) Install the Nuxt SDK
npm i @logto/nuxt
# or
pnpm add @logto/nuxt
# or
yarn add @logto/nuxt
2) Add environment variables
Create a .env file:
NUXT_LOGTO_ENDPOINT="https://your-tenant.logto.app"
NUXT_LOGTO_APP_ID="your-app-id"
NUXT_LOGTO_APP_SECRET="your-app-secret"
NUXT_LOGTO_COOKIE_ENCRYPTION_KEY="a-strong-random-string"
Important: NUXT_LOGTO_COOKIE_ENCRYPTION_KEY must be a strong random string because it protects encrypted auth cookies.
3) Configure nuxt.config.ts
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@logto/nuxt'],
runtimeConfig: {
logto: {
endpoint: process.env.NUXT_LOGTO_ENDPOINT,
appId: process.env.NUXT_LOGTO_APP_ID,
appSecret: process.env.NUXT_LOGTO_APP_SECRET,
cookieEncryptionKey: process.env.NUXT_LOGTO_COOKIE_ENCRYPTION_KEY,
},
},
})
4) Configure redirect URIs in Logto Console
Assuming your Nuxt app runs on http://localhost:3000:
-
Redirect URI:
http://localhost:3000/callback -
Post sign-out redirect URI:
http://localhost:3000/
These must match the callback and return URLs used by the SDK.
5) Understand the built-in routes
The Nuxt module provides built-in routes for the auth flow:
/sign-in/sign-out/callback
You can customize them if you want:
// nuxt.config.ts
export default defineNuxtConfig({
logto: {
pathnames: {
signIn: '/login',
signOut: '/logout',
callback: '/auth/callback',
},
},
})
If you change the callback path, update the redirect URI in Logto Console accordingly.
6) Implement a simple Sign in / Sign out button
<!-- pages/index.vue -->
<script setup lang="ts">
const user = useLogtoUser()
</script>
<template>
<NuxtLink :to="`/sign-${user ? 'out' : 'in'}`">
Sign {{ user ? 'out' : 'in' }}
</NuxtLink>
<pre v-if="user" style="margin-top: 16px">{{ user }}</pre>
</template>
useLogtoUser() is reactive — it updates when the session changes.
7) Request additional user claims (scopes)
By default, you get basic OIDC claims. If you need more (e.g., email/phone), add scopes:
// nuxt.config.ts
import { UserScope } from '@logto/nuxt'
export default defineNuxtConfig({
logto: {
scopes: [UserScope.Email, UserScope.Phone],
},
})
8) Use the Logto client (server-only)
useLogtoClient() is server-only. On the client it returns undefined.
Example: fetch user info on the server once:
// composables/useServerUserInfo.ts
import { useLogtoClient, useState, callOnce } from '#imports'
export const useServerUserInfo = async () => {
const client = useLogtoClient()
const userInfo = useState<any>('logto-user-info', () => null)
await callOnce(async () => {
if (!client) return
if (!(await client.isAuthenticated())) return
userInfo.value = await client.fetchUserInfo()
})
return userInfo
}
Part 2 — Vue 3 (SPA): add authentication with the Vue SDK
Vue SPAs don’t have a server runtime to securely store secrets, so the recommended setup uses the Logto Vue SDK and SPA application settings in Logto Console.
1) Install the Vue SDK
Install Logto’s Vue SDK (Vue 3 only):
npm i @logto/vue
# or
pnpm add @logto/vue
# or
yarn add @logto/vue
2) Configure redirect URIs in Logto Console
Assuming your Vue app runs on http://localhost:5173:
-
Redirect URI:
http://localhost:5173/callback -
Post sign-out redirect URI:
http://localhost:5173/
(Use your actual dev server origin if it’s different.)
3) Initialize Logto in main.ts
// src/main.ts
import { createApp } from 'vue'
import { createLogto } from '@logto/vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(
createLogto({
endpoint: import.meta.env.VITE_LOGTO_ENDPOINT,
appId: import.meta.env.VITE_LOGTO_APP_ID,
})
)
app.use(router)
app.mount('#app')
Add .env variables:
# .env
VITE_LOGTO_ENDPOINT="https://your-tenant.logto.app"
VITE_LOGTO_APP_ID="your-app-id"
4) Add a callback route
In SPAs, you must handle the redirect callback route.
Example with Vue Router:
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../pages/Home.vue'
import Callback from '../pages/Callback.vue'
export default createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/callback', component: Callback },
],
})
Callback page:
<!-- src/pages/Callback.vue -->
<script setup lang="ts">
import { onMounted } from 'vue'
import { useLogto } from '@logto/vue'
import { useRouter } from 'vue-router'
const { handleSignInCallback } = useLogto()
const router = useRouter()
onMounted(async () => {
await handleSignInCallback(window.location.href)
router.replace('/')
})
</script>
<template>
<p>Signing you in…</p>
</template>
5) Sign in / Sign out buttons
<!-- src/pages/Home.vue -->
<script setup lang="ts">
import { useLogto } from '@logto/vue'
const { isAuthenticated, signIn, signOut, getIdTokenClaims } = useLogto()
const handleSignIn = async () => {
await signIn(import.meta.env.VITE_LOGTO_REDIRECT_URI)
}
const handleSignOut = async () => {
await signOut(import.meta.env.VITE_LOGTO_POST_SIGN_OUT_REDIRECT_URI)
}
</script>
<template>
<button v-if="!isAuthenticated" @click="handleSignIn">
Sign in
</button>
<button v-else @click="handleSignOut">
Sign out
</button>
</template>
Add redirect-related env vars:
VITE_LOGTO_REDIRECT_URI="http://localhost:5173/callback"
VITE_LOGTO_POST_SIGN_OUT_REDIRECT_URI="http://localhost:5173/"
If you want to display the current user:
<script setup lang="ts">
import { ref } from 'vue'
import { useLogto } from '@logto/vue'
const { isAuthenticated, getIdTokenClaims } = useLogto()
const claims = ref<any>(null)
const loadClaims = async () => {
claims.value = await getIdTokenClaims()
}
</script>
<template>
<div v-if="isAuthenticated">
<button @click="loadClaims">Load user claims</button>
<pre v-if="claims">{{ claims }}</pre>
</div>
</template>
Choosing between Nuxt and Vue integrations
If you are building a Nuxt app with SSR (or hybrid rendering), prefer @logto/nuxt because it’s designed for server-side flows and secure cookie handling.
If you are building a Vue SPA (no server runtime), use @logto/vue and the SPA application type in Logto Console.
Quick sanity check
- Clicking Sign in should redirect you to Logto’s hosted sign-in screen.
- After signing in, you should land on your callback route and end up back in the app.
- Clicking Sign out should clear the shared session and return you to your post sign-out URL.
Final notes
This document intentionally keeps the examples minimal and production-oriented. Once authentication works, the next steps are typically:
- Protecting routes (Nuxt middleware / Vue router guards)
- Calling your APIs with access tokens
- Adding organization/roles/permissions if your product needs it
Top comments (0)