Zum Hauptinhalt springen

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.

tipp:
  • 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

Installation

Installiere das Logto SDK über deinen bevorzugten Paketmanager:

npm i passport passport-openidconnect

Integration

Passport.js mit OIDC-Strategie initialisieren

passport.ts
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:

your-app-entry.ts
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:

  1. Deine App löst die Anmeldemethode aus.
  2. Der Benutzer wird auf die Logto-Anmeldeseite umgeleitet. Bei nativen Apps wird der Systembrowser geöffnet.
  3. Der Benutzer meldet sich an und wird zurück zu deiner App umgeleitet (konfiguriert als Redirect-URI).

Bezüglich der umleitungsbasierten Anmeldung

  1. Dieser Authentifizierungsprozess folgt dem OpenID Connect (OIDC) Protokoll, und Logto erzwingt strenge Sicherheitsmaßnahmen, um die Benutzeranmeldung zu schützen.
  2. 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.


hinweis:

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.

Redirect-URI in der Logto-Konsole

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:

your-app-entry.ts
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

your-app-entry.ts
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:

  1. Starte deine Anwendung, du wirst den Anmeldebutton sehen.
  2. Klicke auf den Anmeldebutton, das SDK wird den Anmeldeprozess initiieren und dich zur Logto-Anmeldeseite weiterleiten.
  3. Nachdem du dich angemeldet hast, wirst du zurück zu deiner Anwendung geleitet und siehst den Abmeldebutton.
  4. Klicke auf den Abmeldebutton, um den Token-Speicher zu leeren und dich abzumelden.

Berechtigungen und Ansprüche

Logto verwendet OIDC Berechtigungen und Ansprüche Konventionen, um die Berechtigungen und Ansprüche für das Abrufen von Benutzerinformationen aus dem ID-Token und dem OIDC userinfo endpoint zu definieren. Sowohl "Berechtigung (Scope)" als auch "Anspruch (Claim)" sind Begriffe aus den OAuth 2.0 und OpenID Connect (OIDC) Spezifikationen.

Kurz gesagt, wenn du eine Berechtigung anforderst, erhältst du die entsprechenden Ansprüche 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`, und es gibt keine Möglichkeit, diese Standardberechtigungen zu entfernen. Aber du kannst weitere Berechtigungen hinzufügen, wenn du Logto konfigurierst:

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):

openid

Claim-NameTypBeschreibungBenötigt userinfo?
substringDer eindeutige Identifikator des BenutzersNein

profile

Claim-NameTypBeschreibungBenötigt userinfo?
namestringDer vollständige Name des BenutzersNein
usernamestringDer Benutzername des BenutzersNein
picturestringURL zum Profilbild des Endbenutzers. Diese URL MUSS auf eine Bilddatei (z. B. PNG, JPEG oder GIF) verweisen und nicht auf eine Webseite, die ein Bild enthält. Beachte, dass diese URL speziell auf ein Profilfoto des Endbenutzers verweisen SOLLTE, das sich zur Darstellung des Endbenutzers eignet, und nicht auf ein beliebiges vom Endbenutzer aufgenommenes Foto.Nein
created_atnumberZeitpunkt, zu dem der Endbenutzer erstellt wurde. Die Zeit wird als Anzahl der Millisekunden seit der Unix-Epoche (1970-01-01T00:00:00Z) dargestellt.Nein
updated_atnumberZeitpunkt, 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.Nein

Weitere Standardansprüche 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 das Userinfo-Endpunkt abgefragt werden muss. Ein Unterschied zu den oben genannten Ansprüchen besteht darin, dass diese Ansprüche nur zurückgegeben werden, wenn ihre Werte nicht leer sind, während die oben genannten Ansprüche null zurückgeben, wenn die Werte leer sind.

hinweis:

Im Gegensatz zu den Standardansprüchen verwenden die Ansprüche created_at und updated_at Millisekunden anstelle von Sekunden.

email

Claim-NameTypBeschreibungBenötigt userinfo?
emailstringDie E-Mail-Adresse des BenutzersNein
email_verifiedbooleanOb die E-Mail-Adresse verifiziert wurdeNein

phone

Claim-NameTypBeschreibungBenötigt userinfo?
phone_numberstringDie Telefonnummer des BenutzersNein
phone_number_verifiedbooleanOb die Telefonnummer verifiziert wurdeNein

address

Bitte siehe OpenID Connect Core 1.0 für Details zum Address-Anspruch.

custom_data

Claim-NameTypBeschreibungBenötigt userinfo?
custom_dataobjectDie benutzerdefinierten DatenJa

identities

Claim-NameTypBeschreibungBenötigt userinfo?
identitiesobjectDie verknüpften Identitäten des BenutzersJa
sso_identitiesarrayDie verknüpften SSO-Identitäten des BenutzersJa

roles

Claim-NameTypBeschreibungBenötigt userinfo?
rolesstring[]Die Rollen des BenutzersNein

urn:logto:scope:organizations

Claim-NameTypBeschreibungBenötigt userinfo?
organizationsstring[]Die Organisations-IDs, denen der Benutzer angehörtNein
organization_dataobject[]Die Organisationsdaten, denen der Benutzer angehörtJa
hinweis:

Diese Organisationsansprüche können auch über das 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-NameTypBeschreibungBenötigt userinfo?
organization_rolesstring[]Die Organisationsrollen des Benutzers im Format <organization_id>:<role_name>Nein

Im Hinblick auf Leistung und Datenmenge gilt: Wenn "Benötigt userinfo?" mit "Ja" angegeben ist, erscheint der Anspruch nicht im ID-Token, sondern wird in der Antwort des Userinfo-Endpunkts zurückgegeben.

Weiterführende Lektüre

Endbenutzerflüsse: Authentifizierungsflüsse, Kontoflüsse und Organisationsflüsse Connectors konfigurieren Autorisierung (Authorization)