Zum Hauptinhalt springen

Authentifizierung zu deiner iOS (Swift)-Anwendung hinzufügen

hinweis:

Diese Anleitung geht davon aus, dass du eine Anwendung des Typs "Native app" in der Admin-Konsole erstellt hast.

Installation

hinweis:

Die minimal unterstützte iOS-Version des Logto Swift SDK ist iOS 13.

Das Logto Swift SDK ist in zwei Hauptversionen erhältlich:

  • v2: Öffnet die Anmeldeerfahrung in ASWebAuthenticationSession (dem Systembrowser), was Passkey-Anmeldung ermöglicht und die Browsersitzung teilt. Beachte, dass v2 die nativen Social-Plugin-Ziele entfernt; Social Connectors funktionieren weiterhin über den Browser. Wenn du auf die native WeChat- oder Alipay-SDK-Übergabe angewiesen bist, bleibe bei v1.
  • v1: Öffnet die Anmeldeerfahrung in einer eingebetteten WebView, was für die nativen Social-Plugin-Ziele erforderlich ist, aber Passkey-Anmeldung nicht unterstützt (WebView unterstützt WebAuthn, den zugrunde liegenden Standard von Passkeys, nicht).

Diese Anleitung behandelt beide Versionen. Wähle deine Version in den untenstehenden Tabs aus; die Auswahl bleibt während dieser Anleitung synchronisiert.

Verwende die folgende URL, um das Logto SDK als Abhängigkeit im Swift Package Manager hinzuzufügen.

https://github.com/logto-io/swift.git

Seit Xcode 11 kannst du ein Swift-Paket direkt importieren, ohne zusätzliche Tools.

Wenn Xcode nach der Paketversion fragt, wähle die Version, die du integrieren möchtest:

Verwende die neueste v2-Version als Version. Die neueste v2-Version ist 2.0.0.

Wenn du Package.swift direkt verwendest:

Package.swift
// Füge das Logto SDK als Abhängigkeit hinzu
.package(url: "https://github.com/logto-io/swift.git", from: "2.0.0")

Wir unterstützen derzeit Carthage und CocoaPods nicht, aufgrund einiger technischer Probleme.

Carthage

Carthage benötigt eine xcodeproj-Datei zum Bauen. Wir werden später versuchen, eine Lösung zu finden.

CocoaPods

CocoaPods unterstützt keine lokale Abhängigkeit und kein Monorepo, daher ist es schwierig, ein .podspec für dieses Repository zu erstellen.

Integration

Init LogtoClient

Initialisiere den Client, indem du eine LogtoClient-Instanz mit einem LogtoConfig-Objekt erstellst.

ContentView.swift
import Logto
import LogtoClient

let config = try? LogtoConfig(
endpoint: "<your-logto-endpoint>", // Z.B. http://localhost:3001
appId: "<your-app-id>"
)
let client = LogtoClient(useConfig: config)
info:

Standardmäßig speichern wir Anmeldeinformationen wie ID-Token und Auffrischungstoken im Schlüsselbund. Daher muss sich der Benutzer nicht erneut anmelden, wenn er zurückkehrt.

Um dieses Verhalten zu deaktivieren, setze usingPersistStorage auf false:

let config = try? LogtoConfig(
// ...
usingPersistStorage: false
)

Implementiere An- und Abmeldung

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.


Redirect-URI konfigurieren

Wechseln wir zur Seite "Anwendungsdetails" der Logto-Konsole. Füge eine Redirect-URI io.logto.app://callback hinzu und klicke auf "Änderungen speichern".

Redirect-URI in Logto-Konsole

In v2 öffnet sich die Anmeldeerfahrung in ASWebAuthenticationSession (dem Systembrowser), und die Weiterleitung wird über ein OS-Level Callback-Matching zurück zu deiner App geleitet. Für eine Redirect-URI mit benutzerdefiniertem Schema wie io.logto.app://callback registriere nur den Schema-Teil (io.logto.app) in der Info.plist deiner App und füge dann die vollständige Redirect-URI zu den Redirect-URIs deiner Logto-Anwendung hinzu.

Öffne in Xcode dein App-Target, wähle Info, erweitere URL Types und füge einen Eintrag mit io.logto.app in URL Schemes hinzu. Wenn du die Info.plist direkt bearbeitest, füge Folgendes hinzu:

Info.plist
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>io.logto.app</string>
<key>CFBundleURLSchemes</key>
<array>
<string>io.logto.app</string>
</array>
</dict>
</array>

Für den Browser-Flow in v2 musst du LogtoClient.handle(url:) nicht aufrufen; diese Plugin-Handoff-API wurde mit dem eingebetteten WebView-Flow entfernt.

Du kannst auch eine HTTPS-Redirect-URI wie https://example.com/callback verwenden:

  1. Füge deiner App die Associated Domains-Funktion hinzu.
  2. Konfiguriere webcredentials:example.com, damit ASWebAuthenticationSession HTTPS-Callbacks ab iOS 17.4 und neuer zuordnen kann.
  3. Wenn dieselbe URL deine App auch außerhalb der Authentifizierungssitzung als Universal Link öffnen soll, konfiguriere applinks:example.com und hoste eine gültige apple-app-site-association-Datei für die Domain und den Pfad.
  4. Füge die HTTPS-URI zu den Redirect-URIs deiner Logto-Anwendung hinzu.
  5. Übergebe dieselbe URI an signInWithBrowser.

Ab iOS 17.4 verwendet das SDK die HTTPS-Callback-Matching-API von ASWebAuthenticationSession, sodass HTTPS-Redirects automatisch abgeschlossen werden und die Sitzung beendet wird. Auf älteren iOS-Versionen kann die Autorisierungsanfrage weiterhin die HTTPS-Redirect-URI verwenden, aber die Sitzung wird möglicherweise nicht automatisch geschlossen, es sei denn, deine App verarbeitet den Universal Link Callback selbst. Behalte eine Redirect-URI mit benutzerdefiniertem Schema als Kompatibilitätsoption, wenn du eine automatische Fertigstellung auf älteren iOS-Versionen benötigst.

Anmelden und Abmelden

hinweis:

Bevor du .signInWithBrowser(redirectUri:) aufrufst, stelle sicher, dass du die Redirect-URI im Admin Console korrekt konfiguriert hast.

In v2 führt client.signOut(postLogoutRedirectUri:) ein vollständiges Abmelden durch: Es werden die lokalen Anmeldedaten gelöscht, das Auffrischungstoken widerrufen und die Logto-Sitzung beendet, indem der Endpunkt zum Sitzungsende im Systembrowser geöffnet wird. Der Browser navigiert dann über die Post-Logout-Redirect-URI zurück zu deiner App. Bevor du dies verwendest, wechsle zur Anwendungsdetailseite der Logto Console, füge die Post-Logout-Redirect-URI io.logto.app://signed-out hinzu und klicke auf "Änderungen speichern". Die Post-Logout-Redirect-URI kann dasselbe benutzerdefinierte Schema verwenden, das du für die Anmeldung registriert hast.

Zum Beispiel in einer SwiftUI-App:

ContentView.swift
// Beispielcode, Kommentare ggf. übersetzen
struct ContentView: View {
@State var isAuthenticated: Bool

private let redirectUri = "io.logto.app://callback"
private let postLogoutRedirectUri = "io.logto.app://signed-out"

init() {
isAuthenticated = client.isAuthenticated
}

var body: some View {
VStack {
if isAuthenticated {
Button("Sign Out") {
Task { [self] in
let error = await client.signOut(postLogoutRedirectUri: postLogoutRedirectUri)
if let error = error {
print(error)
return
}
isAuthenticated = false
}
}
} else {
Button("Sign In") {
Task { [self] in
do {
try await client.signInWithBrowser(redirectUri: redirectUri)
isAuthenticated = true
} catch let error as LogtoClientErrors.SignIn {
// Fehler während der Anmeldung aufgetreten
} catch {
// andere Fehler
}
}
}
}
}
}
}
hinweis:
  • Du kannst auch client.signOut() ohne eine Post-Logout-Redirect-URI aufrufen. In diesem Fall ist keine Console-Konfiguration erforderlich: Der Browser zeigt die Logto-Abmeldeseite an, und der Benutzer kehrt durch manuelles Schließen zur App zurück.
  • Wenn kein UI-Kontext verfügbar ist, kannst du client.clearCredentials() aufrufen, um die lokalen Anmeldedaten zu löschen und das Auffrischungstoken zu widerrufen. Beachte, dass dadurch die Logto-Sitzung im Browser erhalten bleibt, sodass die nächste signInWithBrowser-Anmeldung den Benutzer möglicherweise stillschweigend über diese Sitzung erneut anmeldet.

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.

Benutzerinformationen abrufen

Benutzerinformationen anzeigen

Um die Informationen des Benutzers anzuzeigen, kannst du die Methode client.getIdTokenClaims() verwenden. Zum Beispiel in einer SwiftUI-App:

ContentView.swift
struct ContentView: View {
@State var isAuthenticated: Bool
@State var name: String?

init() {
isAuthenticated = client.isAuthenticated
name = try? client.getIdTokenClaims().name
}

var body: some View {
VStack {
if isAuthenticated {
Text("Willkommen, \(name)")
} else {
Text("Bitte anmelden")
}
}
}
}

Zusätzliche Ansprüche anfordern

Möglicherweise fehlen einige Benutzerinformationen im zurückgegebenen Objekt von client.getIdTokenClaims(). Dies liegt daran, dass OAuth 2.0 und OpenID Connect (OIDC) so konzipiert sind, dass sie dem Prinzip der minimalen Rechte (PoLP) folgen, und Logto auf diesen Standards basiert.

Standardmäßig werden begrenzte Ansprüche zurückgegeben. Wenn du mehr Informationen benötigst, kannst du zusätzliche Berechtigungen anfordern, um auf mehr Ansprüche zuzugreifen.

info:

Ein "Anspruch (Claim)" ist eine Behauptung über ein Subjekt; eine "Berechtigung (Scope)" ist eine Gruppe von Ansprüchen. Im aktuellen Fall ist ein Anspruch ein Informationsstück über den Benutzer.

Hier ist ein nicht-normatives Beispiel für die Beziehung zwischen Berechtigung und Anspruch:

tipp:

Der "sub"-Anspruch bedeutet "Subjekt", was der eindeutige Identifikator des Benutzers ist (d. h. Benutzer-ID).

Das Logto SDK wird immer drei Berechtigungen anfordern: openid, profile und offline_access.

Um zusätzliche Berechtigungen anzufordern, kannst du die Berechtigungen an das LogtoConfig-Objekt übergeben. Zum Beispiel:

ContentView.swift
let config = try? LogtoConfig(
endpoint: "<your-logto-endpoint>", // Z.B. http://localhost:3001
appId: "<your-app-id>",
scopes: [
UserScope.Email.rawValue,
UserScope.Phone.rawValue,
]
)

Dann kannst du auf die zusätzlichen Ansprüche im Rückgabewert von client.getIdTokenClaims() zugreifen:

let claims = try? client.getIdTokenClaims()
// Jetzt kannst du auf zusätzliche Ansprüche `claims.email`, `claims.phone` usw. zugreifen.

Ansprüche, die Netzwerk-Anfragen benötigen

Um das ID-Token nicht aufzublähen, erfordern einige Ansprüche Netzwerk-Anfragen, um abgerufen zu werden. Zum Beispiel ist der custom_data Anspruch nicht im Benutzerobjekt enthalten, selbst wenn er in den Berechtigungen angefordert wird. Um auf diese Ansprüche zuzugreifen, kannst du die client.fetchUserInfo() Methode verwenden:

let userInfo = try? client.fetchUserInfo()
// Jetzt kannst du auf den Anspruch `userInfo.custom_data` zugreifen
Diese Methode wird die Benutzerinformationen abrufen, indem sie eine Anfrage an den Userinfo-Endpunkt stellt. Um mehr über die verfügbaren Berechtigungen und Ansprüche zu erfahren, siehe den Berechtigungen und Ansprüche Abschnitt.

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.

Hier ist die Liste der unterstützten Berechtigungen (Scopes) und der entsprechenden Ansprüche (Claims):

Standard OIDC-Berechtigungen (Scopes)

openid (Standard)

Claim-NameTypBeschreibung
substringDer eindeutige Identifikator des Benutzers

profile (Standard)

Claim-NameTypBeschreibung
namestringDer vollständige Name des Benutzers
usernamestringDer Benutzername des Benutzers
picturestringURL 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_atnumberZeitpunkt, zu dem der Endbenutzer erstellt wurde. Die Zeit wird als Anzahl der Millisekunden seit der Unix-Epoche (1970-01-01T00:00:00Z) dargestellt.
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.

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.

hinweis:

Im Gegensatz zu den Standard-Claims verwenden die Claims created_at und updated_at Millisekunden anstelle von Sekunden.

email

Claim-NameTypBeschreibung
emailstringDie E-Mail-Adresse des Benutzers
email_verifiedbooleanOb die E-Mail-Adresse verifiziert wurde

phone

Claim-NameTypBeschreibung
phone_numberstringDie Telefonnummer des Benutzers
phone_number_verifiedbooleanOb die Telefonnummer verifiziert wurde

address

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

info:

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-NameTypBeschreibungStandardmäßig im ID-Token enthalten
custom_dataobjectDie benutzerdefinierten Daten des Benutzers

identities

Claim-NameTypBeschreibungStandardmäßig im ID-Token enthalten
identitiesobjectDie verknüpften Identitäten des Benutzers
sso_identitiesarrayDie verknüpften SSO-Identitäten des Benutzers

roles

Claim-NameTypBeschreibungStandardmäßig im ID-Token enthalten
rolesstring[]Die Rollen (Roles) des Benutzers

urn:logto:scope:organizations

Claim-NameTypBeschreibungStandardmäßig im ID-Token enthalten
organizationsstring[]Die Organisations-IDs, denen der Benutzer angehört
organization_dataobject[]Die Organisationsdaten, denen der Benutzer angehört
hinweis:

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-NameTypBeschreibungStandardmäßig im ID-Token enthalten
organization_rolesstring[]Die Organisationsrollen, denen der Benutzer angehört, im Format <organization_id>:<role_name>

API-Ressourcen

Wir empfehlen, zuerst 🔐 Rollenbasierte Zugangskontrolle (RBAC) zu lesen, um die grundlegenden Konzepte von Logto RBAC zu verstehen und wie man API-Ressourcen richtig einrichtet.

Logto-Client konfigurieren

Sobald du die API-Ressourcen eingerichtet hast, kannst du sie bei der Konfiguration von Logto in deiner App hinzufügen:

ContentView.swift
let config = try? LogtoConfig(
endpoint: "<your-logto-endpoint>", // Z.B. http://localhost:3001
appId: "<your-app-id>",
resources: ["https://shopping.your-app.com/api", "https://store.your-app.com/api"], // API-Ressourcen hinzufügen
)
let client = LogtoClient(useConfig: config)

Jede API-Ressource hat ihre eigenen Berechtigungen (Berechtigungen).

Zum Beispiel hat die Ressource https://shopping.your-app.com/api die Berechtigungen shopping:read und shopping:write, und die Ressource https://store.your-app.com/api hat die Berechtigungen store:read und store:write.

Um diese Berechtigungen anzufordern, kannst du sie bei der Konfiguration von Logto in deiner App hinzufügen:

ContentView.swift
let config = try? LogtoConfig(
endpoint: "<your-logto-endpoint>",
appId: "<your-app-id>",
scopes: ["shopping:read", "shopping:write", "store:read", "store:write"],
resources: ["https://shopping.your-app.com/api", "https://store.your-app.com/api"],
)
let client = LogtoClient(useConfig: config)

Du wirst bemerken, dass Berechtigungen separat von API-Ressourcen definiert sind. Dies liegt daran, dass Resource Indicators for OAuth 2.0 spezifiziert, dass die endgültigen Berechtigungen für die Anfrage das kartesische Produkt aller Berechtigungen bei allen Zielservices sein werden.

Somit können im obigen Fall die Berechtigungen aus der Definition in Logto vereinfacht werden, beide API-Ressourcen können read und write Berechtigungen ohne Präfix haben. Dann, in der Logto-Konfiguration:

ContentView.swift
let config = try? LogtoConfig(
endpoint: "<your-logto-endpoint>",
appId: "<your-app-id>",
scopes: ["read", "write"],
resources: ["https://shopping.your-app.com/api", "https://store.your-app.com/api"],
)
let client = LogtoClient(useConfig: config)

Für jede API-Ressource wird sowohl read als auch write Berechtigungen angefordert.

hinweis:

Es ist in Ordnung, Berechtigungen anzufordern, die in den API-Ressourcen nicht definiert sind. Zum Beispiel kannst du die Berechtigung email anfordern, auch wenn die API-Ressourcen die Berechtigung email nicht verfügbar haben. Nicht verfügbare Berechtigungen werden sicher ignoriert.

Nach der erfolgreichen Anmeldung wird Logto die entsprechenden Berechtigungen an API-Ressourcen gemäß den Rollen des Benutzers ausstellen.

Zugangstoken für die API-Ressource abrufen

Um das Zugangstoken für eine spezifische API-Ressource abzurufen, kannst du die Methode getAccessToken verwenden:

ContentView.swift
let accessToken = try await client.getAccessToken(for: "https://shopping.your-app.com/api")

Diese Methode gibt ein JWT-Zugangstoken zurück, das verwendet werden kann, um auf die API-Ressource zuzugreifen, wenn der Benutzer die entsprechenden Berechtigungen hat. Wenn das aktuell zwischengespeicherte Zugangstoken abgelaufen ist, versucht diese Methode automatisch, ein Auffrischungstoken zu verwenden, um ein neues Zugangstoken zu erhalten.

Zugangstoken an Anfrage-Header anhängen

Platziere das Token im Authorization-Feld der HTTP-Header im Bearer-Format (Bearer YOUR_TOKEN), und du bist startklar.

hinweis:

Der Integrationsablauf des Bearer-Tokens kann je nach verwendetem Framework oder Anfrager variieren. Wähle deinen eigenen Weg, um den Anfrage-Authorization-Header anzuwenden.

await LogtoRequest.get(
useSession: session,
endpoint: userInfoEndpoint,
headers: ["Authorization": "Bearer \(accessToken)"]
)

Weiterführende Lektüre

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