Authentifizierung zu deiner Passport.js-Anwendung hinzufügen
Dieser Leitfaden zeigt dir, wie du Logto in deine Anwendung mit Passport.js und OIDC-Strategie integrierst.
- In diesem Leitfaden gehen wir davon aus, dass du Express mit Session in deinem Projekt eingerichtet hast. Falls nicht, schaue dir die Express.js-Website an, um loszulegen.
Voraussetzungen
- Ein Logto Cloud Konto oder ein selbst gehostetes Logto.
- Eine Logto-Traditionelle Anwendung erstellt.
- Ein Express-Projekt mit konfigurierter Sitzung. Sieh dir die Express.js-Website an.
Installation
Installiere das Logto SDK über deinen bevorzugten Paketmanager:
- npm
- pnpm
- yarn
npm i passport passport-openidconnectpnpm add passport passport-openidconnectyarn add passport passport-openidconnectIntegration
Passport.js mit OIDC-Strategie initialisieren
import passport from 'passport';
import OpenIDConnectStrategy, { type Profile, type VerifyCallback } from 'passport-openidconnect';
const endpoint = '<your-logto-endpoint>';
const appId = '<your-application-id>';
const appSecret = '<your-application-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);
});
}
Dieser Code initialisiert Passport mit der OpenIDConnectStrategy. Die Methoden serialize und deserialize sind zu Demonstrationszwecken gesetzt.
Stelle sicher, dass du das Passport-Middleware in deiner Anwendung initialisierst und anhängst:
import initPassport from './passport';
// ... anderer Code
initPassport();
// ... anderer Code
app.use(passport.authenticate('session'));
// ... anderer Code
Redirect-URIs konfigurieren
Bevor wir ins Detail gehen, hier ein schneller Überblick über die Endbenutzererfahrung. Der Anmeldeprozess lässt sich wie folgt vereinfachen:
- Deine App löst die Anmeldemethode aus.
- Der Benutzer wird auf die Logto-Anmeldeseite umgeleitet. Bei nativen Apps wird der Systembrowser geöffnet.
- Der Benutzer meldet sich an und wird zurück zu deiner App umgeleitet (konfiguriert als Redirect-URI).
Bezüglich der umleitungsbasierten Anmeldung
- Dieser Authentifizierungsprozess folgt dem OpenID Connect (OIDC) Protokoll, und Logto erzwingt strenge Sicherheitsmaßnahmen, um die Benutzeranmeldung zu schützen.
- Wenn du mehrere Apps hast, kannst du denselben Identitätsanbieter (Logto) verwenden. Sobald sich der Benutzer bei einer App anmeldet, wird Logto den Anmeldeprozess automatisch abschließen, wenn der Benutzer auf eine andere App zugreift.
Um mehr über die Gründe und Vorteile der umleitungsbasierten Anmeldung zu erfahren, siehe Logto-Anmeldeerfahrung erklärt.
In den folgenden Code-Snippets gehen wir davon aus, dass deine App unter http://localhost:3000/ läuft.
Redirect-URIs konfigurieren
Wechsle zur Anwendungsdetailseite der Logto-Konsole. Füge eine Redirect-URI http://localhost:3000/callback hinzu.
Genau wie beim Anmelden sollten Benutzer zu Logto weitergeleitet werden, um sich von der gemeinsamen Sitzung abzumelden. Sobald dies abgeschlossen ist, wäre es ideal, den Benutzer zurück zu deiner Website zu leiten. Füge zum Beispiel http://localhost:3000/ als Redirect-URI nach dem Abmelden hinzu.
Klicke dann auf "Speichern", um die Änderungen zu speichern.
Anmeldung und Abmeldung implementieren
Wir werden nun spezifische Routen für Authentifizierungsprozesse erstellen:
app.get('/sign-in', passport.authenticate('openidconnect'));
app.get(
'/callback',
passport.authenticate('openidconnect', {
successReturnToOrRedirect: '/',
})
);
app.get('/sign-out', (request, response, next) => {
request.logout((error) => {
if (error) {
next(error);
return;
}
response.redirect(`${endpoint}/oidc/session/end?client_id=${appId}`);
});
});
Dann zur Startseite hinzufügen
app.get('/', (request: Request, response) => {
const { user } = request;
response.setHeader('content-type', 'text/html');
if (user) {
response.end(
`<h1>Hello Logto</h1><p>Angemeldet als ${JSON.stringify(
user
)}, <a href="/sign-out">Abmelden</a></p>`
);
} else {
response.end(`<h1>Hello Logto</h1><p><a href="/sign-in">Anmelden</a></p>`);
}
});
Checkpoint: Teste deine Anwendung
Jetzt kannst du deine Anwendung testen:
- Starte deine Anwendung, du wirst den Anmeldebutton sehen.
- Klicke auf den Anmeldebutton, das SDK wird den Anmeldeprozess initiieren und dich zur Logto-Anmeldeseite weiterleiten.
- Nachdem du dich angemeldet hast, wirst du zurück zu deiner Anwendung geleitet und siehst den Abmeldebutton.
- Klicke auf den Abmeldebutton, um den Token-Speicher zu leeren und dich abzumelden.
Berechtigungen und Ansprüche
Logto verwendet die OIDC Scopes- und Claims-Konventionen, um die Berechtigungen (Scopes) und Ansprüche (Claims) für das Abrufen von Benutzerinformationen aus dem ID-Token und dem OIDC userinfo-Endpunkt zu definieren. Sowohl „Berechtigung (Scope)“ als auch „Anspruch (Claim)“ sind Begriffe aus den OAuth 2.0- und OpenID Connect (OIDC)-Spezifikationen.
Für Standard-OIDC-Ansprüche wird die Aufnahme in das ID-Token strikt durch die angeforderten Berechtigungen bestimmt. Erweiterte Ansprüche (wie custom_data und organizations) können zusätzlich so konfiguriert werden, dass sie im ID-Token über die Custom ID token-Einstellungen erscheinen.
Kurz gesagt: Wenn du eine Berechtigung (Scope) anforderst, erhältst du die entsprechenden Ansprüche (Claims) in den Benutzerinformationen. Zum Beispiel: Wenn du die `email`-Berechtigung anforderst, erhältst du die `email`- und `email_verified`-Daten des Benutzers.
Standardmäßig fordert das Logto SDK immer drei Berechtigungen an: `openid`, `profile` und `offline_access`. Es gibt keine Möglichkeit, diese Standardberechtigungen zu entfernen. Du kannst jedoch beim Konfigurieren von Logto weitere Berechtigungen hinzufügen:
export default function initPassport() {
passport.use(
new OpenIDConnectStrategy(
{
// ... other options
clientID: appId,
clientSecret: appSecret,
callbackURL: '/callback',
scope: ['openid', 'offline_access', 'profile', 'email'],
}
// ... other options
)
);
// ... other options
}
Hier ist die Liste der unterstützten Berechtigungen (Scopes) und der entsprechenden Ansprüche (Claims):
Standard OIDC-Berechtigungen (Scopes)
openid (Standard)
| Claim-Name | Typ | Beschreibung |
|---|---|---|
| sub | string | Der eindeutige Identifikator des Benutzers |
profile (Standard)
| Claim-Name | Typ | Beschreibung |
|---|---|---|
| name | string | Der vollständige Name des Benutzers |
| username | string | Der Benutzername des Benutzers |
| picture | string | URL zum Profilbild des Endbenutzers. Diese URL MUSS auf eine Bilddatei (z. B. PNG, JPEG oder GIF) verweisen, nicht auf eine Webseite mit einem Bild. Beachte, dass diese URL speziell auf ein Profilfoto des Endbenutzers verweisen SOLLTE, das zur Darstellung des Endbenutzers geeignet ist, und nicht auf ein beliebiges vom Endbenutzer aufgenommenes Foto. |
| created_at | number | Zeitpunkt, zu dem der Endbenutzer erstellt wurde. Die Zeit wird als Anzahl der Millisekunden seit der Unix-Epoche (1970-01-01T00:00:00Z) dargestellt. |
| updated_at | number | Zeitpunkt, zu dem die Informationen des Endbenutzers zuletzt aktualisiert wurden. Die Zeit wird als Anzahl der Millisekunden seit der Unix-Epoche (1970-01-01T00:00:00Z) dargestellt. |
Weitere Standard-Ansprüche (Claims) wie family_name, given_name, middle_name, nickname, preferred_username, profile, website, gender, birthdate, zoneinfo und locale werden ebenfalls im profile-Scope enthalten sein, ohne dass der userinfo-Endpunkt angefragt werden muss. Ein Unterschied zu den oben genannten Claims besteht darin, dass diese Claims nur zurückgegeben werden, wenn ihre Werte nicht leer sind, während die oben genannten Claims null zurückgeben, wenn die Werte leer sind.
Im Gegensatz zu den Standard-Claims verwenden die Claims created_at und updated_at Millisekunden anstelle von Sekunden.
email
| Claim-Name | Typ | Beschreibung |
|---|---|---|
string | Die E-Mail-Adresse des Benutzers | |
| email_verified | boolean | Ob die E-Mail-Adresse verifiziert wurde |
phone
| Claim-Name | Typ | Beschreibung |
|---|---|---|
| phone_number | string | Die Telefonnummer des Benutzers |
| phone_number_verified | boolean | Ob die Telefonnummer verifiziert wurde |
address
Bitte siehe die OpenID Connect Core 1.0 für Details zum Address-Claim.
Scopes, die mit (Standard) gekennzeichnet sind, werden immer vom Logto SDK angefordert. Claims unter den Standard-OIDC-Scopes sind immer im ID-Token enthalten, wenn der entsprechende Scope angefordert wird — sie können nicht deaktiviert werden.
Erweiterte Berechtigungen (Scopes)
Die folgenden Scopes sind von Logto erweitert und liefern Claims über den userinfo-Endpunkt. Diese Claims können auch so konfiguriert werden, dass sie direkt im ID-Token enthalten sind, über Konsole > Benutzerdefiniertes JWT. Siehe Benutzerdefiniertes ID-Token für weitere Details.
custom_data
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| custom_data | object | Die benutzerdefinierten Daten des Benutzers |
identities
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| identities | object | Die verknüpften Identitäten des Benutzers | |
| sso_identities | array | Die verknüpften SSO-Identitäten des Benutzers |
roles
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| roles | string[] | Die Rollen (Roles) des Benutzers | ✅ |
urn:logto:scope:organizations
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| organizations | string[] | Die Organisations-IDs, denen der Benutzer angehört | ✅ |
| organization_data | object[] | Die Organisationsdaten, denen der Benutzer angehört |
Diese Organisations-Claims können auch über den userinfo-Endpunkt abgerufen werden, wenn ein opaker Token verwendet wird. Allerdings können opake Tokens nicht als Organisationstoken für den Zugriff auf organisationsspezifische Ressourcen verwendet werden. Siehe Opaker Token und Organisationen für weitere Details.
urn:logto:scope:organization_roles
| Claim-Name | Typ | Beschreibung | Standardmäßig im ID-Token enthalten |
|---|---|---|---|
| organization_roles | string[] | Die Organisationsrollen, denen der Benutzer angehört, im Format <organization_id>:<role_name> | ✅ |