0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-10 22:22:45 -05:00

feat(console): add passport.js guide (#6344)

This commit is contained in:
wangsijie 2024-07-29 09:20:15 +08:00 committed by GitHub
parent 17e139dff1
commit 0a20edc3d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 206 additions and 0 deletions

View file

@ -32,6 +32,7 @@ import webNextAppRouter from './web-next-app-router/index';
import webNextAuth from './web-next-auth/index';
import webNuxt from './web-nuxt/index';
import webOutline from './web-outline/index';
import webPassport from './web-passport/index';
import webPhp from './web-php/index';
import webPython from './web-python/index';
import webRuby from './web-ruby/index';
@ -245,6 +246,13 @@ export const guides: Readonly<Guide[]> = Object.freeze([
Component: lazy(async () => import('./web-outline/README.mdx')),
metadata: webOutline,
},
{
order: 6.1,
id: 'web-passport',
Logo: lazy(async () => import('./web-passport/logo.svg?react')),
Component: lazy(async () => import('./web-passport/README.mdx')),
metadata: webPassport,
},
{
order: 999,
id: 'web-gpt-plugin',

View file

@ -0,0 +1,163 @@
import InlineNotification from '@/ds-components/InlineNotification';
import UriInputField from '@/mdx-components/UriInputField';
import Steps from '@/mdx-components/Steps';
import Step from '@/mdx-components/Step';
import NpmLikeInstallation from '@/mdx-components/NpmLikeInstallation';
<Steps>
<Step title="Prerequisites">
In this guide, we assume you have set up Express with session in you project. If you haven't, check out the [Express.js website](https://expressjs.com/) to get started.
</Step>
<Step
title="Installation"
subtitle="Install Passport.js for your project"
>
Install `passport` and the OIDC strategy plugin, `passport-openidconnect`:
<NpmLikeInstallation packageName="passport passport-openidconnect" />
</Step>
<Step title="Configure redirect URI">
<InlineNotification>
In the following steps, we assume your app is running on <code>http://localhost:3000</code>.
</InlineNotification>
First, lets enter your redirect URI.
<UriInputField name="redirectUris" defaultValue="http://localhost:3000/api/auth/callback/logto" />
Don't forget to click the **Save** button.
</Step>
<Step title="Initialize Passport.js with OIDC strategy">
<Code title="src/passport.ts" className="language-ts">
{`import passport from 'passport';
import OpenIDConnectStrategy, { type Profile, type VerifyCallback } from 'passport-openidconnect';
const endpoint = '${props.endpoint}';
const appId = '${props.app.id}';
const appSecret = '${props.app.secret}';
export default function initPassport() {
passport.use(
new OpenIDConnectStrategy(
{
issuer: \`\${endpoint}/oidc\`,
authorizationURL: \`\${endpoint}/oidc/auth\`,
tokenURL: \`\${endpoint}/oidc/token\`,
userInfoURL: \`\${endpoint}/oidc/me\`,
clientID: appId,
clientSecret: appSecret,
callbackURL: '/callback',
scope: ['profile', 'offline_access'],
},
(issuer: string, profile: Profile, callback: VerifyCallback) => {
callback(null, profile);
}
)
);
passport.serializeUser((user, callback) => {
callback(null, user);
});
passport.deserializeUser(function (user, callback) {
callback(null, user as Express.User);
});
}`}
</Code>
This code initializes Passport with the **`OpenIDConnectStrategy`**. The serialize and deserialize methods are set for demonstration purposes.
Ensure to initialize and attach Passport middleware in your application:
```tsx
import initPassport from 'src/passport';
// ... other code
initPassport();
// ... other code
app.use(passport.authenticate('session'));
// ... other code
```
</Step>
<Step title="Implement sign-in and sign-out">
We'll now create specific routes for authentication processes:
### Sign in: `/sign-in`
```tsx
app.get('/sign-in', passport.authenticate('openidconnect'));
```
This route builds and redirects to an OIDC auth route.
### Handle sign in callback: `/callback`
```tsx
app.get(
'/callback',
passport.authenticate('openidconnect', {
successReturnToOrRedirect: '/',
})
);
```
This handles the OIDC sign-in callback, stores tokens, and redirects to the homepage.
### Sign out: `/sign-out`
```tsx
app.get('/sign-out', (request, response, next) => {
request.logout((error) => {
if (error) {
next(error);
return;
}
response.redirect(`${endpoint}/oidc/session/end?client_id=${appId}`);
});
});
```
This redirects to Logto's session end URL, then back to the homepage.
### Add to the homepage
```tsx
app.get('/', (request: Request, response) => {
const { user } = request;
response.setHeader('content-type', 'text/html');
if (user) {
response.end(
`<h1>Hello Logto</h1><p>Signed in as ${JSON.stringify(
user
)}, <a href="/sign-out">Sign Out</a></p>`
);
} else {
response.end(`<h1>Hello Logto</h1><p><a href="/sign-in">Sign In</a></p>`);
}
});
```
</Step>
<Step title="Checkpoint: Test Logto and Passport integration">
Now, you can test your application to see if the authentication works as expected.
</Step>
</Steps>

View file

@ -0,0 +1,3 @@
{
"order": 6.1
}

View file

@ -0,0 +1,11 @@
import { ApplicationType } from '@logto/schemas';
import { type GuideMetadata } from '../types';
const metadata: Readonly<GuideMetadata> = Object.freeze({
name: 'Passport',
description: 'Passport is authentication middleware for Node.js.',
target: ApplicationType.Traditional,
});
export default metadata;

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="400px" height="500px" viewBox="0 0 400 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.3.1 (12002) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="passport_logo_final" sketch:type="MSLayerGroup" transform="translate(-400.000000, -350.000000)">
<g id="Group" sketch:type="MSShapeGroup">
<g id="Shape">
<g transform="translate(400.000000, 350.000000)">
<path d="M200,0 C89.5,0 0,89.5 0,200 L100,200 C100,144.8 144.8,100 200,100 L200,0 L200,0 Z" fill="#D6FF00"></path>
<path d="M400,200 C400,89.5 310.5,0 200,0 L200,100 C255.2,100 300,144.8 300,200 L400,200 L400,200 Z" fill="#34E27A"></path>
<path d="M200,400 C310.5,400 400,310.5 400,200 L300,200 C300,255.2 255.2,300 200,300 L200,400 L200,400 Z" fill="#00B9F1"></path>
<path d="M100,400 L100,200 L0,200 L0,500 L200,500 L200,400 L100,400 Z" fill="#FFFFFF"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB