Express: Integrate @logto/express
This tutorial assumes you have created an Application of type "Traditional Web" in Admin Console. If you are not ready, read this before continuing.
Add dependenciesโ
- npm
- Yarn
- pnpm
npm i @logto/express cookie-parser express-session
yarn add @logto/express cookie-parser express-session
pnpm add @logto/express cookie-parser express-session
Init LogtoClientโ
In the following code snippets, we assume your app is running on http://localhost:3000
.
You can find and copy "App Secret" from application details page in Admin Console:

Import and initialize LogtoClient:
import { LogtoExpressConfig } from '@logto/express';
const config: LogtoExpressConfig = {
appId: '<your-application-id>',
appSecret: '<your-application-secret>',
endpoint: '<your-logto-endpoint>', // E.g. http://localhost:3001
baseUrl: '<your-express-app-base-url>', // E.g. http://localhost:3000
};
Prepare required middlewaresโ
The SDK requires express-session to be configured in prior.
import cookieParser from 'cookie-parser';
import session from 'express-session';
app.use(cookieParser());
app.use(session({ secret: 'random_session_key', cookie: { maxAge: 14 * 24 * 60 * 60 } }));
Sign inโ
The sign-in flow can be simplified as:
Configure sign-in redirect URIโ
Let's switch to the Application details page of Admin Console in this section. Add a Redirect URI http://localhost:3000/logto/sign-in-callback
and click "Save Changes".

Redirect URI is an OAuth 2.0 concept which implies the location should redirect after authentication.
Prepare logto routesโ
Prepare routes to connect with Logto.
Go back to your IDE/editor, use the following code to implement the API routes first:
import { handleAuthRoutes } from '@logto/express';
app.use(handleAuthRoutes(config));
This will create 3 routes automatically:
/logto/sign-in
: Sign in with Logto./logto/sign-in-callback
: Handle sign-in callback./logto/sign-out
: Sign out from Logto.
Implement sign-inโ
We're almost there! Now, create a sign-in button to redirect to the sign-in route on user click.
app.get('/', (req, res) => {
res.setHeader('content-type', 'text/html');
res.end(`<div><a href="/logto/sign-in">Sign In</a></div>`);
});
Get user profileโ
In order to get user profile, we need to use the withLogto
middleware:
import { withLogto } from '@logto/express';
app.use(withLogto(config));
Then the user profile will be attached to req
, example usage:
app.get('/user', (req, res) => {
res.json(req.user);
});
Fetch user infoโ
For most cases, it is recommended to use claims
in req.user
as "user info", this can be fast because claims
is cached when tokens are granted. If you need more accurate user info, set config.fetchUserInfo
to true
, to tell the SDK to fetch the user information from the OIDC UserInfo Endpoint.
app.get('/user', withLogto({ ...config, fetchUserInfo: true }), (req, res) => {
res.json(req.user.userInfo);
});
The user information response will vary based on the scopes used in the LogtoConfig
while initializing the LogtoClient
; and the following table lists the relations between user information and scopes:
Field Name | Type | Required Scope | Notes |
---|---|---|---|
sub | string | openid | The openid scope is added by default. |
name | string | profile | The profile scope is added by default. |
username | string | profile | The profile scope is added by default. |
picture | string | profile | The profile scope is added by default. |
string | email | ||
email_verified | boolean | email | |
phone_number | string | phone | |
phone_number_verified | boolean | phone | |
custom_data | object | custom_data | |
identities | object | identities |
Protect routesโ
After setting up withLogto
in the previous step, we can protect routes by creating a simple middleware:
const requireAuth = async (req: Request, res: Response, next: NextFunction) => {
if (!req.user.isAuthenticated) {
res.redirect('/logto/sign-in');
}
next();
};
And then:
app.get('/protected', requireAuth, (req, res) => {
res.end('protected resource');
});
Get access tokenโ
If you want to get the access token, set getAccessToken
to true
:
app.get(
'/fetch-access-token',
withLogto({
...config,
// Fetch access token from remote, this may slow down the response time,
// you can also add "resource" if needed.
getAccessToken: true,
}),
(request, response) => {
// Get access token here
console.log(request.user.accessToken);
response.json(request.user);
}
);
Sign outโ
Calling /logto/sign-out
will clear all the Logto data in memory and cookies if they exist.
After signing out, it'll be great to redirect your user back to your website. Let's add http://localhost:3000
as one of the Post Sign-out URIs in Admin Console (shows under Redirect URIs).