From 3b644e51f30693d0b518d40ac28e85e4c76d3402 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 20:07:59 +0200 Subject: [PATCH 01/30] feat(translation): add german --- docs/index.de.md | 2 +- docs/security/authentication.de.md | 874 +++++++++++++++++++++++++++++ 2 files changed, 875 insertions(+), 1 deletion(-) create mode 100644 docs/security/authentication.de.md diff --git a/docs/index.de.md b/docs/index.de.md index 7917a389a..d91166a56 100644 --- a/docs/index.de.md +++ b/docs/index.de.md @@ -25,4 +25,4 @@ Die Dokumentationen zu älteren Versionen von Vapor findest du unter [https://le ## Authoren -Das Vapor-Kernteam und viele weitere Mitglieder der Vapor-Community. +Das Vapor Kernteam und viele andere Mitglieder der Vapor Community. diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md new file mode 100644 index 000000000..5c35bf153 --- /dev/null +++ b/docs/security/authentication.de.md @@ -0,0 +1,874 @@ +# Authentifizierung + +Bei der Authentifzierung handelt sich um die Überprüfung einer Benutzeridentität, zum Beispiel anhand von Anmeldeinformationen oder einem Token. Die Authentifizierung unterscheidet sich von der Authentisierung. Bei Authentisierung geht es mehr um die Überprüfung von Berechtigungen eines Benutzers. + +## Einführung + +Vapor ermöglicht die Basis- und Bearerauthentifzierung mittels dem Authorization-Header. Die Authenifzierung erfolgt durch einen sogenannten _Authenticator_, der die eigentliche Logik beinhaltet und dazu verwendent wird um, einzelne Endpunkte oder auch die gesamte Anwendung zu sichern. +| Protokoll | Beschreibung | +|-------------------------------------------------------------|----------------------------------------------------------| +| `RequestAuthenticator`/`AsyncRequestAuthenticator` | Base authenticator capable of creating middleware. | +| [`BasicAuthenticator`/`AsyncBasicAuthenticator`](#basis) |Authenticates Basic authorization header. | +| [`BearerAuthenticator`/`AsyncBearerAuthenticator`](#bearer) |Authenticates Bearer authorization header. | +| `CredentialsAuthenticator`/`AsyncCredentialsAuthenticator` |Authenticates a credentials payload from the request body.| + +Bei erfolgreicher Authentifizierung, übergibt der Authenticator die Benutzeridentität an die Eigenschaft `req.auth`. Mit der Methode `get(_:)` können wir auf die Identität zugreifen. Wenn die Authentifizerung fehl schlägt, wird keine Identität übergeben und jeglicher Versuch darauf zuzugreifen schlägt fehl. + +## Authentifizierbar + +Um einen Benutzer zu authentifizieren, muss das Objekt mit dem Protokoll `Authenticatable` versehen werden. Beim Objekt kann es sich um eine Struktur, Klasse oder ein Fluent-Model handeln. Für das folgende Beispiel erstellen wir eine Struktur `User` mit der Eigenschaft `name`. + +```swift +import Vapor + +struct User: Authenticatable { + var name: String +} +``` + +### Endpunkt + +Endpunkte können mit Authentikatoren versehen werden. + +```swift +let protected = app.grouped(UserAuthenticator()) +protected.get("me") { req -> String in + try req.auth.require(User.self).name +} +``` + +Mit der Methode _require(:)_ können wir die Benutzeridentität abfragen. Sollte die Authentifizierung fehlschlagen, wird ein entsprechender Fehler ausgegeben und der Endpunkt bleibt unberührt. + +### Guard Middleware + +Mit der Methode _guardMiddleware()_ gehen wir auf Nummer sich gehen und + +```swift +let protected = app.grouped(UserAuthenticator()) + .grouped(User.guardMiddleware()) +``` + +Requiring authentication is not done by the authenticator middleware to allow for composition of authenticators. Read more about [composition](#composition) below. + +## Basis + +Die Basisauthentifierung überträgt mittels Authorization-Header Benutzername und Passwort an den Server. Benutzername und Passwort werden dabei mit einem semikolon-getrennt in eine Base64-Zeichenfolge gewandelt und mit dem Prefix `Basic`versehen. + +```http +GET /me HTTP/1.1 +Authorization: Basic dGVzdDpzZWNyZXQ= +``` + +Die Basisauthentifierzung wird nur einmalig verwendet, um nach der erfolgreichen Authentifizierung einen Token zu erzeugen. + +Durch den Token wird die Häufigkeit einer notwendigen Übermittlung des Passwortes verringert. Zudem sollte die Authentifizerung nie im Klartext oder über eine unverschlüsselte Verbindung erfolgen. + +Damit wir die Basisauthentifierzung in unserer Anwendung verwenden können, müssen wir einen Struktur anlegen und diese mit dem Protokoll _BasicAuthenticator_ versehen. + +```swift +import Vapor + +struct UserAuthenticator: BasicAuthenticator { + typealias User = App.User + + func authenticate( + basic: BasicAuthorization, + for request: Request + ) -> EventLoopFuture { + if basic.username == "test" && basic.password == "secret" { + request.auth.login(User(name: "Vapor")) + } + return request.eventLoop.makeSucceededFuture(()) + } +} +``` + +```swift +import Vapor + +struct UserAuthenticator: AsyncBasicAuthenticator { + typealias User = App.User + + func authenticate( + basic: BasicAuthorization, + for request: Request + ) async throws { + if basic.username == "test" && basic.password == "secret" { + request.auth.login(User(name: "Vapor")) + } + } +} +``` + +Das Protokoll verlangt, dass wir die Methode _authenticate(basic:for:)_ anlegen. Die Methode wird bei einer Anfrage mit Basis-Header aufgerufen. Eine Struktur mit Benutzername und Passwort wird somit an die Methode übergeben. + +## Bearer + +Die Bearerauthentifierzung sendet einen Token an den Server. Der Token wird mit dem Prefix `Bearer` versehen. + +```http +GET /me HTTP/1.1 +Authorization: Bearer foo +``` + +Die Bearerauthentifierzung wird für die Authentifizerung von API-Endpunkten verwendet. Dabei fragt der User nach einem Token, indem er Benutzername und Passwort an einen Login-Endpunkt schickt. Der Token ist anschließend für einen gewissen Zeitraum gültig. + +Innerhalb der Gültigkeit kann der Benutzer den Token an Stelle der eigentlichen Anmeldeinformationen verwenden. Mit dem Ablauf des Tokens, muss über den Endpunkt einer neuer Token angefordert werden. + +Zur Verwendung einer Bearerauthentifizierung, müssen wir eine Struktur erstellen und diese mit dem Protokoll `BearerAuthenticator` versehen. + +```swift +import Vapor + +struct UserAuthenticator: BearerAuthenticator { + typealias User = App.User + + func authenticate( + bearer: BearerAuthorization, + for request: Request + ) -> EventLoopFuture { + if bearer.token == "foo" { + request.auth.login(User(name: "Vapor")) + } + return request.eventLoop.makeSucceededFuture(()) + } +} +``` + +```swift +import Vapor + +struct UserAuthenticator: AsyncBearerAuthenticator { + typealias User = App.User + + func authenticate( + bearer: BearerAuthorization, + for request: Request + ) async throws { + if bearer.token == "foo" { + request.auth.login(User(name: "Vapor")) + } + } +} +``` + +Das Protokoll verlangt, dass wir die Methode _authenticate(bearer:for:)_ anlegen. Die Methode wird bei einer Anfrage mit Bearer-Header aufgerufen. Das Objekt wird an die Methode übergeben. + +## Kombinierung + +Authentikatoren können für eine höhrere Sicherheit miteinander kombiniert werden. + +### Kombinieren von Methoden + +```swift +app.grouped(UserPasswordAuthenticator()) + .grouped(UserTokenAuthenticator()) + .grouped(User.guardMiddleware()) + .post("login") +{ req in + let user = try req.auth.require(User.self) + // Do something with user. +} +``` + +Im folgenden Beispiel folgt das Objekt _UserTokenAuthenticator_ dem _UserPasswordAuthenticator_ und zum Schluss die _GuardMiddleware_. + +In diesem Beispiel wird von zwei Authentifikatoren `UserPasswordAuthenticator` und `UserTokenAuthenticator` ausgegangen, die beide `User` authentifizieren. Diese beiden Authentifikatoren werden der Routengruppe hinzugefügt. Schließlich wird `GuardMiddleware` nach den Authentifikatoren hinzugefügt, um sicherzustellen, dass `User` erfolgreich authentifiziert wurde. + +Die Zusammenstellung der Authentikator macht es möglich, dass der Benutzer sich + +Diese Zusammensetzung von Authentifikatoren führt zu einer Route, auf die entweder mit einem Passwort oder einem Token zugegriffen werden kann. Ein solcher Weg könnte es einem Benutzer ermöglichen, sich anzumelden und ein Token zu generieren, das er dann weiter zur Generierung neuer Token verwenden kann. + +### Kombinieren von Benutzern + +The second method of authentication composition is chaining authenticators for different user types. Take the following example: + +```swift +app.grouped(AdminAuthenticator()) + .grouped(UserAuthenticator()) + .get("secure") +{ req in + guard req.auth.has(Admin.self) || req.auth.has(User.self) else { + throw Abort(.unauthorized) + } + // Do something. +} +``` + +This example assumes two authenticators `AdminAuthenticator` and `UserAuthenticator` that authenticate `Admin` and `User`, respectively. Both of these authenticators are added to the route group. Instead of using `GuardMiddleware`, a check in the route handler is added to see if either `Admin` or `User` were authenticated. If not, an error is thrown. + +This composition of authenticators results in a route that can be accessed by two different types of users with potentially different methods of authentication. Such a route could allow for normal user authentication while still giving access to a super-user. + +## Anleitung + +Die Authenifizieung kann über die Eigenschaft _req.auth_ manuell durchgeführt werden. Das kann zu Beispiel zu Testzwecke hilfreich sein. + +Um einen Benutzer manuell anzumelden, müssen wir einen Objekt vom Typ _Authenticatble_ der Methode _req.auth.login(_:) mitgegeben. + +```swift +req.auth.login(User(name: "Vapor")) +``` + +Um den authentifizierten Benutzer zu erhalten, verwende `req.auth.require(_:)` + +```swift +let user: User = try req.auth.require(User.self) +print(user.name) // String +``` + +Du kannst auch `req.auth.get(_:)` verwenden, wenn du nicht automatisch einen Fehler auslösen willst, wenn die Authentifizierung fehlschlägt. + +```swift +let user = req.auth.get(User.self) +print(user?.name) // String? +``` + +Um einen Benutzer abzumelden, müssen wir die Identität an die Methode _req.auth.logout(_:)_ übergeben. + +```swift +req.auth.logout(User.self) +``` + +## Fluent + +[Fluent](../fluent/overview.md) bietet uns hierzu bereits Protokolle an, die wir auf unseren Models anwenden können. + +_ModelTokenAuthenicatable_ ist für die Authentifizierung mit einem Bearer-Token. _ModelAuthenticatable_ ist für die Authentifizierung mittels Anmeldeinformationen und wird in den meisten Fällen nur auf einen einzigen Endpunkt angewendet, um eben einen solchen Bearer-Token zu erstellen. + +This guide assumes you are familiar with Fluent and have successfully configured your app to use a database. If you are new to Fluent, start with the [overview](../fluent/overview.md). + +### Benutzer-Authentifizierung + +Für den Anfang brauchen wir ein Model zum Authentifizieren des Benutzers. + +```swift +import Fluent +import Vapor + +final class User: Model, Content { + static let schema = "users" + + @ID(key: .id) + var id: UUID? + + @Field(key: "name") + var name: String + + @Field(key: "email") + var email: String + + @Field(key: "password_hash") + var passwordHash: String + + init() { } + + init(id: UUID? = nil, name: String, email: String, passwordHash: String) { + self.id = id + self.name = name + self.email = email + self.passwordHash = passwordHash + } +} +``` + +Das Model. Das Feld _Email_ sollte unique sein, um Redundanzen zu vermeiden. Somit würde die Migration für das obere Beispiel so aussehen. + +```swift +import Fluent +import Vapor + +extension User { + struct Migration: AsyncMigration { + var name: String { "CreateUser" } + + func prepare(on database: Database) async throws { + try await database.schema("users") + .id() + .field("name", .string, .required) + .field("email", .string, .required) + .field("password_hash", .string, .required) + .unique(on: "email") + .create() + } + + func revert(on database: Database) async throws { + try await database.schema("users").delete() + } + } +} +``` + +Anschließend müssen wir der Anwendung noch die Migration mitgeben. + +```swift +app.migrations.add(User.Migration()) +``` + +Als Nächstes legen für die Benutzererstellung einen Endpunkt und eine Struktur an. + +```swift +import Vapor + +extension User { + struct Create: Content { + var name: String + var email: String + var password: String + var confirmPassword: String + } +} +``` + +Wir können die Struktur mit dem Protokoll _Validatable_ versehen um weitere Validierungen hinzuzufügen. + +```swift +import Vapor + +extension User.Create: Validatable { + static func validations(_ validations: inout Validations) { + validations.add("name", as: String.self, is: !.empty) + validations.add("email", as: String.self, is: .email) + validations.add("password", as: String.self, is: .count(8...)) + } +} +``` + +Jetzt kannst du den Endpunkt "POST /users" erstellen. + +```swift +app.post("users") { req async throws -> User in + try User.Create.validate(content: req) + let create = try req.content.decode(User.Create.self) + guard create.password == create.confirmPassword else { + throw Abort(.badRequest, reason: "Passwords did not match") + } + let user = try User( + name: create.name, + email: create.email, + passwordHash: Bcrypt.hash(create.password) + ) + try await user.save(on: req.db) + return user +} +``` + +Der Endpunkt überprüft die Anfrage, entziffert die von uns erstellte Struktur _User.Create_ und gleicht das Passwort ab. Zusammen mit den entzifferten Informationen wird anschließend der Benutzer in der Datenbank angelegt. Das Klartext-Passwort wird dabei mit _Bycrypt_ verschlüsselt. + +Wir können das Projekt nun starten. + +```http +POST /users HTTP/1.1 +Content-Length: 97 +Content-Type: application/json + +{ + "name": "Vapor", + "email": "test@vapor.codes", + "password": "secret42", + "confirmPassword": "secret42" +} +``` + +#### Modell-Authentifizierbar + +Nachdem wir nun einen Model für den Benutzer und einen Endpunkt zum Anlegen eines Benutzers haben, können wir das Model mit dem Protokoll _ModelAuthenticatable_ versehen. + +```swift +import Fluent +import Vapor + +extension User: ModelAuthenticatable { + static let usernameKey = \User.$email + static let passwordHashKey = \User.$passwordHash + + func verify(password: String) throws -> Bool { + try Bcrypt.verify(password, created: self.passwordHash) + } +} +``` + +Mit Hilfe der ersten beiden Eigenschaften _usernameKey_ und _passwordHashKey_ bestimmen wir, welche Felder im Model für den Benutzernamen und dem Passwort-Hash verwenden werden soll. Mit der _\_ legen wir hierzu ein KeyPath an, worüber Fluent darauf zugreifen kann. + +Mit der Methode _verify(password:)_ können wir das Plaintext-Passwort eines Basic-Headers gegenprüfen. Weil wir anfangs in unserem Beispiel _Bycrypt_ verwendet haben, müssen wir bei der Überprüfung des Hashwertes ebenfalls _Bycrypt_ anwenden. + +Nun können wir auch einen Endpunkt mit einem Authentikator versehen. + +```swift +let passwordProtected = app.grouped(User.authenticator()) +passwordProtected.post("login") { req -> User in + try req.auth.require(User.self) +} +``` + +Dank des Protokolls _ModelAuthenticatable_ können wir die statische Methode _athenticator(:)_ verwenden, um einen Authenticator zu erstellen. + +Test that this route works by sending the following request. + +```http +POST /login HTTP/1.1 +Authorization: Basic dGVzdEB2YXBvci5jb2RlczpzZWNyZXQ0Mg== +``` + +Die Anfragen übergibt als Benutzernamen _test@vapor.codes_ und als Passwort _secret42_: + +This request passes the username `test@vapor.codes` and password `secret42` via the Basic authentication header. You should see the previously created user returned. + +In der Theorie können wir alle Endpunkte mit der Standardauthentifizierung versehen, was allerdings weniger ratsam wäre. Mit der Token-Authentifizierung übertragen wir viel seltener die sensiblen Daten über das Internet. Zumal ist die Authentifizierung um einiges schneller, da nur das Passwort-Hashing durchgeführt wird. + +### Benutzertoken + +Für einen Benutzertoken erstellen wir eine neues Model. + +```swift +import Fluent +import Vapor + +final class UserToken: Model, Content { + static let schema = "user_tokens" + + @ID(key: .id) + var id: UUID? + + @Field(key: "value") + var value: String + + @Parent(key: "user_id") + var user: User + + init() { } + + init(id: UUID? = nil, value: String, userID: User.IDValue) { + self.id = id + self.value = value + self.$user.id = userID + } +} +``` + +Für den eindeutigen Tokenwert müssen wir im Model ein Feld mit der Bezeichnung _value_ anlegen. Um eine Verbindung zum Benutzer herzustellen, müssen wir zusätzlich ein Parent-Relation anlegen. + +Anschließend können wir uns der Migration widmen. + +```swift +import Fluent + +extension UserToken { + struct Migration: AsyncMigration { + var name: String { "CreateUserToken" } + + func prepare(on database: Database) async throws { + try await database.schema("user_tokens") + .id() + .field("value", .string, .required) + .field("user_id", .uuid, .required, .references("users", "id")) + .unique(on: "value") + .create() + } + + func revert(on database: Database) async throws { + try await database.schema("user_tokens").delete() + } + } +} +``` + +In der Migration geben wir an, dass der Wert für das Feld _value_ eindeutig sein soll und das ein Fremdschlüssel mit Verweis auf die Tabelle _Users_ anlegegt werden soll. + +Nun müssen wir der Anwendung die Migration mitgeben. + +```swift +app.migrations.add(UserToken.Migration()) +``` + +Zum Schluss erweitern wir das Model _User_ noch um eine Methode für die Erstellung des Tokens. Die Methode wird beim Login aufgerufen. + +```swift +extension User { + func generateToken() throws -> UserToken { + try .init( + value: [UInt8].random(count: 16).base64, + userID: self.requireID() + ) + } +} +``` + +Hier verwenden wir `[UInt8].random(count:)`, um einen zufälligen Token-Wert zu erzeugen. In diesem Beispiel werden 16 Bytes bzw. 128 Bits an Zufallsdaten verwendet. Du kannst diese Zahl nach Belieben anpassen. Die Zufallsdaten werden dann base-64 kodiert, damit sie leicht in HTTP-Headern übertragen werden können. + +Da Sie nun Benutzer-Tokens generieren können, aktualisieren Sie die Route "POST /login", um ein Token zu erstellen und zurückzugeben. + +```swift +let passwordProtected = app.grouped(User.authenticator()) +passwordProtected.post("login") { req async throws -> UserToken in + let user = try req.auth.require(User.self) + let token = try user.generateToken() + try await token.save(on: req.db) + return token +} +``` + +Teste, ob diese Route funktioniert, indem du die gleiche Login-Anfrage wie oben verwendest. Du solltest jetzt beim Einloggen ein Token erhalten, das ungefähr so aussieht: + +``` +8gtg300Jwdhc/Ffw784EXA== +``` + +Behalte den Token, den du bekommst, denn wir werden ihn bald benutzen. + +#### Model Token Authenticatable + +Konforme `UserToken` mit `ModelTokenAuthenticatable`. Damit können Token dein `User`-Modell authentifizieren. + +```swift +import Vapor +import Fluent + +extension UserToken: ModelTokenAuthenticatable { + static let valueKey = \UserToken.$value + static let userKey = \UserToken.$user + + var isValid: Bool { + true + } +} +``` + +Die erste Protokollanforderung legt fest, in welchem Feld der eindeutige Wert des Tokens gespeichert wird. Dies ist der Wert, der im Bearer-Authentifizierungs-Header gesendet wird. Die zweite Anforderung legt die übergeordnete Beziehung zum Modell "User" fest. So sucht Fluent nach dem authentifizierten Benutzer. + +Die letzte Anforderung ist ein boolescher Wert "isValid". Wenn dieser Wert "False" ist, wird das Token aus der Datenbank gelöscht und der Benutzer wird nicht authentifiziert. Der Einfachheit halber werden wir die Token für die Ewigkeit machen, indem wir den Wert "wahr" fest einprogrammieren. + +Da das Token nun `ModelTokenAuthenticatable` entspricht, kannst du einen Authentifikator zum Schutz der Routen erstellen. + +Erstelle einen neuen Endpunkt "GET /me", um den aktuell authentifizierten Benutzer zu erhalten. + +```swift +let tokenProtected = app.grouped(UserToken.authenticator()) +tokenProtected.get("me") { req -> User in + try req.auth.require(User.self) +} +``` + +Ähnlich wie `User` hat `UserToken` jetzt eine statische Methode `authenticator()`, die einen Authentifikator erzeugen kann. Der Authentifikator versucht, einen passenden `UserToken` mit dem Wert aus dem Bearer-Authentifizierungs-Header zu finden. Wenn er eine Übereinstimmung findet, holt er den zugehörigen `User` und authentifiziert ihn. + +Teste, ob diese Route funktioniert, indem du die folgende HTTP-Anfrage sendest, wobei der Token der Wert ist, den du in der Anfrage "POST /login" gespeichert hast. + +```http +GET /me HTTP/1.1 +Authorization: Bearer +``` + +Du solltest den authentifizierten "User" zurückbekommen. + +## Sitzung + +Die [Session API](../advanced/sessions.md) von Vapor kann verwendet werden, um die Benutzerauthentifizierung zwischen Anfragen automatisch aufrechtzuerhalten. Dazu wird nach erfolgreicher Anmeldung eine eindeutige Kennung für den Benutzer in den Sitzungsdaten der Anfrage gespeichert. Bei nachfolgenden Anfragen wird die Kennung des Nutzers aus der Sitzung geholt und zur Authentifizierung des Nutzers verwendet, bevor dein Route Handler aufgerufen wird. + +Sessions eignen sich hervorragend für Front-End-Webanwendungen, die in Vapor erstellt wurden und HTML direkt an Webbrowser ausgeben. Für APIs empfehlen wir eine zustandslose, Token-basierte Authentifizierung, um die Benutzerdaten zwischen den Anfragen aufrechtzuerhalten. + +### Session-Authentifizierbar + +Um die sitzungsbasierte Authentifizierung zu nutzen, brauchst du einen Typ, der `SessionAuthenticatable` entspricht. Für dieses Beispiel verwenden wir eine einfache Struktur. + +```swift +import Vapor + +struct User { + var email: String +} +``` + +Um `SessionAuthenticatable` zu entsprechen, musst du eine `sessionID` angeben. Dies ist der Wert, der in den Sitzungsdaten gespeichert wird und den Nutzer eindeutig identifizieren muss. + +```swift +extension User: SessionAuthenticatable { + var sessionID: String { + self.email + } +} +``` + +Für unseren simplen Typ "Benutzer" verwenden wir die E-Mail-Adresse als eindeutigen Sitzungsbezeichner. + +### Session-Authentifikator + +Als Nächstes brauchen wir einen "SessionAuthenticator", um die Instanzen unseres Benutzers aus dem persistierten Sitzungsbezeichner aufzulösen. + + +```swift +struct UserSessionAuthenticator: SessionAuthenticator { + typealias User = App.User + func authenticate(sessionID: String, for request: Request) -> EventLoopFuture { + let user = User(email: sessionID) + request.auth.login(user) + return request.eventLoop.makeSucceededFuture(()) + } +} +``` + +Falls du `async`/`await` benutzt, kannst du den `AsyncSessionAuthenticator` verwenden: + +```swift +struct UserSessionAuthenticator: AsyncSessionAuthenticator { + typealias User = App.User + func authenticate(sessionID: String, for request: Request) async throws { + let user = User(email: sessionID) + request.auth.login(user) + } +} +``` + +Da alle Informationen, die wir für die Initialisierung unseres Beispiels "Benutzer" benötigen, in der Sitzungskennung enthalten sind, können wir den Benutzer synchron erstellen und anmelden. In einer realen Anwendung würdest du wahrscheinlich den Sitzungsbezeichner verwenden, um eine Datenbankabfrage oder eine API-Anfrage durchzuführen, um die restlichen Benutzerdaten vor der Authentifizierung zu erhalten. + +Als Nächstes erstellen wir einen einfachen Bearer Authenticator, der die erste Authentifizierung durchführt. + +```swift +struct UserBearerAuthenticator: AsyncBearerAuthenticator { + func authenticate(bearer: BearerAuthorization, for request: Request) async throws { + if bearer.token == "test" { + let user = User(email: "hello@vapor.codes") + request.auth.login(user) + } + } +} +``` + +Dieser Authentifikator authentifiziert einen Benutzer mit der E-Mail `hello@vapor.codes`, wenn das Träger-Token `test` gesendet wird. + +Zum Schluss fügen wir all diese Teile in deiner Anwendung zusammen. + +```swift +// Create protected route group which requires user auth. +let protected = app.routes.grouped([ + app.sessions.middleware, + UserSessionAuthenticator(), + UserBearerAuthenticator(), + User.guardMiddleware(), +]) + +// Add GET /me route for reading user's email. +protected.get("me") { req -> String in + try req.auth.require(User.self).email +} +``` + +Die `SessionMiddleware` wird zuerst hinzugefügt, um die Sitzungsunterstützung für die Anwendung zu aktivieren. Weitere Informationen zur Konfiguration von Sitzungen findest du im Abschnitt [Session API](../advanced/sessions.md). + +Als nächstes wird der `SessionAuthenticator` hinzugefügt. Dieser sorgt für die Authentifizierung des Nutzers, wenn eine Sitzung aktiv ist. + +Wenn die Authentifizierung noch nicht in der Sitzung gespeichert wurde, wird die Anfrage an den nächsten Authentifikator weitergeleitet. Der "UserBearerAuthenticator" prüft das Inhaber-Token und authentifiziert den Benutzer, wenn es "test" entspricht. + +Schließlich stellt `User.guardMiddleware()` sicher, dass `User` von einer der vorherigen Middlewares authentifiziert wurde. Wenn der Benutzer nicht authentifiziert wurde, wird ein Fehler ausgelöst. + +Um diese Route zu testen, sende zunächst die folgende Anfrage: + +```http +GET /me HTTP/1.1 +authorization: Bearer test +``` + +Dies veranlasst `UserBearerAuthenticator`, den Benutzer zu authentifizieren. Nach der Authentifizierung speichert `UserSessionAuthenticator` die Kennung des Benutzers im Sitzungsspeicher und erzeugt ein Cookie. Verwende das Cookie aus der Antwort in einer zweiten Anfrage an die Route. + +```http +GET /me HTTP/1.1 +cookie: vapor_session=123 +``` + +Diesmal authentifiziert `UserSessionAuthenticator` den Benutzer und du solltest wieder die E-Mail des Benutzers sehen. + +### Modell Session-Authentifizierbar + +Fluent-Modelle können `SessionAuthenticator` generieren, indem sie mit `ModelSessionAuthenticatable` konform sind. Dabei wird der eindeutige Bezeichner des Modells als Sitzungsbezeichner verwendet und automatisch eine Datenbankabfrage durchgeführt, um das Modell aus der Sitzung wiederherzustellen. + +```swift +import Fluent + +final class User: Model { ... } + +// Allow this model to be persisted in sessions. +extension User: ModelSessionAuthenticatable { } +``` + +Du kannst `ModelSessionAuthenticatable` als leere Konformität zu jedem bestehenden Modell hinzufügen. Nach dem Hinzufügen steht eine neue statische Methode zur Verfügung, mit der du einen `SessionAuthenticator` für dieses Modell erstellen kannst. + +```swift +User.sessionAuthenticator() +``` + +Damit wird die Standarddatenbank der Anwendung für die Auflösung des Benutzers verwendet. Um eine Datenbank anzugeben, übergibst du den Bezeichner. + +```swift +User.sessionAuthenticator(.sqlite) +``` + +## Website-Authentifizierung + +Websites sind ein Sonderfall für die Authentifizierung, denn die Verwendung eines Browsers schränkt die Möglichkeit ein, Anmeldeinformationen mit einem Browser zu verknüpfen. Das führt zu zwei verschiedenen Authentifizierungsszenarien: + +* die Erstanmeldung über ein Formular +* nachfolgende Aufrufe, die mit einem Session-Cookie authentifiziert werden + +Vapor und Fluent bieten verschiedene Hilfsmittel, um dies nahtlos zu ermöglichen. + +### Cookie-Authentifizierung + +Die Sitzungsauthentifizierung funktioniert wie oben beschrieben. Du musst die Sitzungs-Middleware und den Sitzungsauthentifikator auf alle Routen anwenden, auf die dein Nutzer zugreifen wird. Dazu gehören alle geschützten Routen, alle Routen, die zwar öffentlich sind, auf die du aber trotzdem zugreifen willst, wenn der Benutzer eingeloggt ist (um z. B. einen Konto-Button anzuzeigen) **und** Login-Routen. + +Du kannst dies global in deiner App in **configure.swift** wie folgt aktivieren: + +```swift +app.middleware.use(app.sessions.middleware) +app.middleware.use(User.sessionAuthenticator()) +``` + +Diese Middlewares tun Folgendes: + +* Die Sitzung-Middleware wandelt den übermittelten Sitzungs-Cookie in eine Sitzung um. +* Der Authentikator gleicht die erstelle Sitzung mit den aktiven Sitzung ab. Sollte das der Fall sein, authentifiziert es die Anfrage. Die Identität wird in der Sitzung abgelegt, sodass + +* Die Sitzung-Middleware nimmt das Session-Cookie aus der Anfrage und wandelt es in eine Session um. +* der Sitzungs Authenticator nimmt die Session und prüft, ob es einen authentifizierten Benutzer für diese Session gibt. Wenn ja, authentifiziert die Middleware die Anfrage. In der Antwort sieht der Session Authenticator, ob die Anfrage einen authentifizierten Benutzer hat und speichert ihn in der Session, damit er bei der nächsten Anfrage authentifiziert ist. + +### Routen schützen + +Wenn du Routen für eine API schützt, gibst du traditionell eine HTTP-Antwort mit einem Statuscode wie **401 Unautorisiert** zurück, wenn die Anfrage nicht authentifiziert ist. Das ist jedoch keine gute Benutzererfahrung für jemanden, der einen Browser benutzt. Vapor bietet eine `RedirectMiddleware` für jeden `Authenticatable` Typ, die in diesem Szenario verwendet werden kann: + +```swift +let protectedRoutes = app.grouped(User.redirectMiddleware(path: "/login?loginRequired=true")) +``` + +Das "RedirectMiddleware"-Objekt unterstützt auch die Übergabe einer Closure, die bei der Erstellung den Redirect-Pfad als String zurückgibt, um ein erweitertes Url-Handling zu ermöglichen. Zum Beispiel kann der Pfad, von dem aus umgeleitet wurde, als Abfrageparameter an das Umleitungsziel übergeben werden, um den Status zu verwalten. + +```swift +let redirectMiddleware = User.redirectMiddleware { req -> String in + return "/login?authRequired=true&next=\(req.url.path)" +} +``` + +Dies funktioniert ähnlich wie die `GuardMiddleware`. Alle Anfragen an Routen, die bei `protectedRoutes` registriert sind und nicht authentifiziert sind, werden an den angegebenen Pfad weitergeleitet. So kannst du deine Nutzer auffordern, sich einzuloggen, anstatt nur eine **401 Unauthorized** zu liefern. + +Achte darauf, einen Session Authenticator vor der `RedirectMiddleware` einzubinden, um sicherzustellen, dass der authentifizierte Benutzer geladen wird, bevor er die `RedirectMiddleware` durchläuft. + +```swift +let protectedRoutes = app.grouped([User.SessionAuthenticator(), redirecteMiddleware]) +``` + +### Formularanfrage + +Für die Authentifizierung und spätere Sitzungen, die Anmeldung erfolgt meistens über ein Formular. + +Um einen Benutzer und zukünftige Anfragen mit einer Sitzung zu authentifizieren, musst du einen Benutzer anmelden. Vapor bietet ein `ModelCredentialsAuthenticatable`-Protokoll, dem du entsprechen musst. Damit kannst du dich über ein Formular anmelden. Zuerst musst du deinen "User" an dieses Protokoll anpassen: + +```swift +extension User: ModelCredentialsAuthenticatable { + static let usernameKey = \User.$email + static let passwordHashKey = \User.$password + + func verify(password: String) throws -> Bool { + try Bcrypt.verify(password, created: self.password) + } +} +``` + +Dies ist identisch mit `ModelAuthenticatable` und wenn du bereits damit konform gehst, brauchst du nichts weiter zu tun. Als Nächstes wendest du die Middleware `ModelCredentialsAuthenticator` auf deine POST-Anfrage für das Anmeldeformular an: + +```swift +let credentialsProtectedRoute = sessionRoutes.grouped(User.credentialsAuthenticator()) +credentialsProtectedRoute.post("login", use: loginPostHandler) +``` + +Hier wird der Standard-Authentifikator für Anmeldedaten verwendet, um die Login-Route zu schützen. Du musst `Benutzername` und `Passwort` in der POST-Anfrage senden. Du kannst dein Formular wie folgt einrichten: + +```html +
+ + + + + +
+``` + +Der `CredentialsAuthenticator` extrahiert den `Benutzernamen` und das `Passwort` aus dem Request Body, findet den Benutzer anhand des Benutzernamens und verifiziert das Passwort. Wenn das Passwort gültig ist, authentifiziert die Middleware die Anfrage. Der `SessionAuthenticator` authentifiziert dann die Sitzung für nachfolgende Anfragen. + +## JWT + +[JWT](jwt.md) bietet einen `JWTAuthenticator`, der zur Authentifizierung von JSON-Web-Token in eingehenden Anfragen verwendet werden kann. Wenn du dich mit JWT noch nicht auskennst, schau dir den [Überblick](jwt.md) an. + +Erstelle zunächst einen Typ, der eine JWT-Nutzlast repräsentiert. + +```swift +// Example JWT payload. +struct SessionToken: Content, Authenticatable, JWTPayload { + + // Constants + let expirationTime: TimeInterval = 60 * 15 + + // Token Data + var expiration: ExpirationClaim + var userId: UUID + + init(userId: UUID) { + self.userId = userId + self.expiration = ExpirationClaim(value: Date().addingTimeInterval(expirationTime)) + } + + init(user: User) throws { + self.userId = try user.requireID() + self.expiration = ExpirationClaim(value: Date().addingTimeInterval(expirationTime)) + } + + func verify(using signer: JWTSigner) throws { + try expiration.verifyNotExpired() + } +} +``` + +Als Nächstes können wir eine Darstellung der Daten definieren, die in einer erfolgreichen Anmeldeantwort enthalten sind. Zunächst wird die Antwort nur eine Eigenschaft haben, nämlich einen String, der ein signiertes JWT darstellt. + +```swift +struct ClientTokenReponse: Content { + var token: String +} +``` + +Mit unserem Modell für das JWT-Token und die Antwort können wir eine passwortgeschützte Login-Route verwenden, die eine "ClientTokenReponse" zurückgibt und ein signiertes "SessionToken" enthält. + +```swift +let passwordProtected = app.grouped(User.authenticator(), User.guardMiddleware()) +passwordProtected.post("login") { req -> ClientTokenReponse in + let user = try req.auth.require(User.self) + let payload = try SessionToken(with: user) + return ClientTokenReponse(token: try req.jwt.sign(payload)) +} +``` + +Wenn du keinen Authentifikator verwenden willst, kannst du auch etwas haben, das wie folgt aussieht. + +```swift +app.post("login") { req -> ClientTokenReponse in + // Validate provided credential for user + // Get userId for provided user + let payload = try SessionToken(userId: userId) + return ClientTokenReponse(token: try req.jwt.sign(payload)) +} +``` + +Indem du die Payload an `Authenticatable` und `JWTPayload` anpasst, kannst du mit der Methode `authenticator()` einen Routen-Authentifikator erzeugen. Füge diesen zu einer Routengruppe hinzu, um den JWT automatisch abzurufen und zu verifizieren, bevor deine Route aufgerufen wird. + +```swift +// Create a route group that requires the SessionToken JWT. +let secure = app.grouped(SessionToken.authenticator(), SessionToken.guardMiddleware()) +``` + +Das Hinzufügen der optionalen [guard middleware](#guard-middleware) setzt voraus, dass die Autorisierung erfolgreich war. + +Innerhalb der geschützten Routen kannst du mit `req.auth` auf die authentifizierten JWT-Nutzdaten zugreifen. + +```swift +// Return ok reponse if the user-provided token is valid. +secure.post("validateLoggedInUser") { req -> HTTPStatus in + let sessionToken = try req.auth.require(SessionToken.self) + print(sessionToken.userId) + return .ok +} +``` \ No newline at end of file From 9d2eec6bf9f393df52d441a8362eacff1b1bbe87 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:42:13 +0200 Subject: [PATCH 02/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 5c35bf153..37d391bc7 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -1,6 +1,7 @@ # Authentifizierung -Bei der Authentifzierung handelt sich um die Überprüfung einer Benutzeridentität, zum Beispiel anhand von Anmeldeinformationen oder einem Token. Die Authentifizierung unterscheidet sich von der Authentisierung. Bei Authentisierung geht es mehr um die Überprüfung von Berechtigungen eines Benutzers. +Bei der Authentifizierung handelt es sich um die Überprüfung einer Benutzeridentität, zum Beispiel anhand von Anmeldeinformationen oder einem Token. Die Authentifizierung unterscheidet sich von der Autorisierung, bei der die Berechtigung eines zuvor authentifizierten Benutzers zur Durchführung bestimmter Aufgaben überprüft wird. + ## Einführung From e86996aeb04d103904a8292aa8878a913afeabdd Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:42:20 +0200 Subject: [PATCH 03/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 37d391bc7..7a44dc44d 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -5,7 +5,9 @@ Bei der Authentifizierung handelt es sich um die Überprüfung einer Benutzeride ## Einführung -Vapor ermöglicht die Basis- und Bearerauthentifzierung mittels dem Authorization-Header. Die Authenifzierung erfolgt durch einen sogenannten _Authenticator_, der die eigentliche Logik beinhaltet und dazu verwendent wird um, einzelne Endpunkte oder auch die gesamte Anwendung zu sichern. +Vapor ermöglicht die [Basis](https://tools.ietf.org/html/rfc7617)- und [Bearer](https://tools.ietf.org/html/rfc6750) Authentifizierung mittels dem `Authorization` Header. Man kann auch einen User mit den Daten die in der [Content](../basics/content.de.md) API sind authentifizieren. + +Die Authentifizierung erfolgt durch einen sogenannten `Authenticator`, der die eigentliche Logik beinhaltet und dazu verwendet wird um, einzelne Endpunkte oder auch die gesamte Anwendung zu sichern. Ein `Authenticator` kann entweder einzelne Routengruppen schützen oder auch die ganze App. Die folgenden Authenticator-Helfer werden mit Vapor ausgeliefert: | Protokoll | Beschreibung | |-------------------------------------------------------------|----------------------------------------------------------| | `RequestAuthenticator`/`AsyncRequestAuthenticator` | Base authenticator capable of creating middleware. | From ad935c606126e20e740a824c7afe872c974f4bd6 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:42:53 +0200 Subject: [PATCH 04/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 7a44dc44d..88960fb4b 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -15,7 +15,7 @@ Die Authentifizierung erfolgt durch einen sogenannten `Authenticator`, der die e | [`BearerAuthenticator`/`AsyncBearerAuthenticator`](#bearer) |Authenticates Bearer authorization header. | | `CredentialsAuthenticator`/`AsyncCredentialsAuthenticator` |Authenticates a credentials payload from the request body.| -Bei erfolgreicher Authentifizierung, übergibt der Authenticator die Benutzeridentität an die Eigenschaft `req.auth`. Mit der Methode `get(_:)` können wir auf die Identität zugreifen. Wenn die Authentifizerung fehl schlägt, wird keine Identität übergeben und jeglicher Versuch darauf zuzugreifen schlägt fehl. +Bei erfolgreicher Authentifizierung übergibt der Authenticator die Benutzeridentität an die Eigenschaft `req.auth`. Mit der Methode `get(_:)` können wir auf die Identität zugreifen. Wenn die Authentifizierung fehl schlägt wird keine Identität übergeben und jeglicher Versuch, darauf zuzugreifen, schlägt fehl. ## Authentifizierbar From 2538220e44f227e450d4761a498875e75f977f6b Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:42:59 +0200 Subject: [PATCH 05/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 88960fb4b..d28af5615 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -55,7 +55,7 @@ Requiring authentication is not done by the authenticator middleware to allow fo ## Basis -Die Basisauthentifierung überträgt mittels Authorization-Header Benutzername und Passwort an den Server. Benutzername und Passwort werden dabei mit einem semikolon-getrennt in eine Base64-Zeichenfolge gewandelt und mit dem Prefix `Basic`versehen. +Die Basis Authentifizierung überträgt mittels Authorization-Header Benutzername und Passwort an den Server. Benutzername und Passwort werden dabei mit einem Doppelpunkt-verkettet (z.B. `test:secret`), base-64 kodiert und mit dem Präfix `"Basic"` versehen. Die folgende Beispielanfrage kodiert den Benutzernamen "test" mit dem Passwort "secret". ```http GET /me HTTP/1.1 From f1e5a17a5eff52f1835b79f4024b2b5ed2686d6c Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:43:05 +0200 Subject: [PATCH 06/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index d28af5615..9f4a6f769 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -64,7 +64,8 @@ Authorization: Basic dGVzdDpzZWNyZXQ= Die Basisauthentifierzung wird nur einmalig verwendet, um nach der erfolgreichen Authentifizierung einen Token zu erzeugen. -Durch den Token wird die Häufigkeit einer notwendigen Übermittlung des Passwortes verringert. Zudem sollte die Authentifizerung nie im Klartext oder über eine unverschlüsselte Verbindung erfolgen. +Durch den Token wird die Häufigkeit einer notwendigen Übermittlung des Passwortes verringert. Zudem sollte die Basis Authentifizierung nie im Klartext oder über eine unverschlüsselte Verbindung erfolgen. + Damit wir die Basisauthentifierzung in unserer Anwendung verwenden können, müssen wir einen Struktur anlegen und diese mit dem Protokoll _BasicAuthenticator_ versehen. From b6c4a55afa6eb7a133ece285dc56412c6869d0bc Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:43:10 +0200 Subject: [PATCH 07/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 9f4a6f769..3cdadb039 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -67,7 +67,7 @@ Die Basisauthentifierzung wird nur einmalig verwendet, um nach der erfolgreichen Durch den Token wird die Häufigkeit einer notwendigen Übermittlung des Passwortes verringert. Zudem sollte die Basis Authentifizierung nie im Klartext oder über eine unverschlüsselte Verbindung erfolgen. -Damit wir die Basisauthentifierzung in unserer Anwendung verwenden können, müssen wir einen Struktur anlegen und diese mit dem Protokoll _BasicAuthenticator_ versehen. +Damit wir die Basis - Authentifizierung in unserer Anwendung verwenden können, müssen wir eine Struktur anlegen und diese mit dem Protokoll `BasicAuthenticator versehen. Nachfolgend ist ein Beispiel für einen Authenticator zu sehen, der fest programmiert ist, um die obige Anfrage zu verifizieren. ```swift import Vapor From 3bd7a10a94f8e5e64e10d2e0415a465e1742795e Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:43:17 +0200 Subject: [PATCH 08/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 3cdadb039..4f73ecd3b 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -87,6 +87,8 @@ struct UserAuthenticator: BasicAuthenticator { } ``` +Wenn Sie `async`/`await` verwenden, können Sie stattdessen `AsyncBasicAuthenticator` benutzen: + ```swift import Vapor From 5aa515cddad5daffdc151473fbc6a417c7fea2a7 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:43:26 +0200 Subject: [PATCH 09/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 4f73ecd3b..7cbc3cd29 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -40,7 +40,7 @@ protected.get("me") { req -> String in } ``` -Mit der Methode _require(:)_ können wir die Benutzeridentität abfragen. Sollte die Authentifizierung fehlschlagen, wird ein entsprechender Fehler ausgegeben und der Endpunkt bleibt unberührt. +Mit der Methode `req.auth.require` können wir die Benutzeridentität abfragen. Sollte die Authentifizierung fehlschlagen, wird ein entsprechender Fehler ausgegeben und der Endpunkt bleibt unberührt. ### Guard Middleware From 5319a51db9b752f183a223858451af80a70da446 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:43:51 +0200 Subject: [PATCH 10/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 7cbc3cd29..cac6a52da 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -62,7 +62,7 @@ GET /me HTTP/1.1 Authorization: Basic dGVzdDpzZWNyZXQ= ``` -Die Basisauthentifierzung wird nur einmalig verwendet, um nach der erfolgreichen Authentifizierung einen Token zu erzeugen. +Die Basis Authentifizierung wird nur einmalig verwendet, um nach der erfolgreichen Authentifizierung einen Token zu erzeugen. Durch den Token wird die Häufigkeit einer notwendigen Übermittlung des Passwortes verringert. Zudem sollte die Basis Authentifizierung nie im Klartext oder über eine unverschlüsselte Verbindung erfolgen. From fca0eaf688164add13dcdc2f00a479f6a8ab8c3f Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:44:06 +0200 Subject: [PATCH 11/30] Update docs/security/authentication.de.md Co-authored-by: Paul Toffoloni <69189821+ptoffy@users.noreply.github.com> --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index cac6a52da..9162ee107 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -44,7 +44,7 @@ Mit der Methode `req.auth.require` können wir die Benutzeridentität abfragen. ### Guard Middleware -Mit der Methode _guardMiddleware()_ gehen wir auf Nummer sich gehen und +Wir können auch `GuardMiddleware` in der Routengruppe verwenden, um sicherzustellen, dass ein Benutzer authentifiziert wurde, bevor er den Routenhandler erreicht. ```swift let protected = app.grouped(UserAuthenticator()) From f26137bfd005c521a9a126fdf8ee0d402176530c Mon Sep 17 00:00:00 2001 From: Dominik K Date: Sun, 27 Aug 2023 23:55:55 +0200 Subject: [PATCH 12/30] feat(translation): fix german --- docs/security/authentication.de.md | 44 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 9162ee107..961efa2b6 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -10,10 +10,10 @@ Vapor ermöglicht die [Basis](https://tools.ietf.org/html/rfc7617)- und [Bearer] Die Authentifizierung erfolgt durch einen sogenannten `Authenticator`, der die eigentliche Logik beinhaltet und dazu verwendet wird um, einzelne Endpunkte oder auch die gesamte Anwendung zu sichern. Ein `Authenticator` kann entweder einzelne Routengruppen schützen oder auch die ganze App. Die folgenden Authenticator-Helfer werden mit Vapor ausgeliefert: | Protokoll | Beschreibung | |-------------------------------------------------------------|----------------------------------------------------------| -| `RequestAuthenticator`/`AsyncRequestAuthenticator` | Base authenticator capable of creating middleware. | -| [`BasicAuthenticator`/`AsyncBasicAuthenticator`](#basis) |Authenticates Basic authorization header. | -| [`BearerAuthenticator`/`AsyncBearerAuthenticator`](#bearer) |Authenticates Bearer authorization header. | -| `CredentialsAuthenticator`/`AsyncCredentialsAuthenticator` |Authenticates a credentials payload from the request body.| +| `RequestAuthenticator`/`AsyncRequestAuthenticator` |Basis Authentifizierung, der Middleware erstellen kann. | +| [`BasicAuthenticator`/`AsyncBasicAuthenticator`](#basis) |Authentifiziert den Basic authorization header. | +| [`BearerAuthenticator`/`AsyncBearerAuthenticator`](#bearer) |Authentifiziert den Bearer-Autorisierungs-Header. | +| `CredentialsAuthenticator`/`AsyncCredentialsAuthenticator` |Authentifiziert einen Credentials Payload aus dem Request Body.| Bei erfolgreicher Authentifizierung übergibt der Authenticator die Benutzeridentität an die Eigenschaft `req.auth`. Mit der Methode `get(_:)` können wir auf die Identität zugreifen. Wenn die Authentifizierung fehl schlägt wird keine Identität übergeben und jeglicher Versuch, darauf zuzugreifen, schlägt fehl. @@ -51,7 +51,7 @@ let protected = app.grouped(UserAuthenticator()) .grouped(User.guardMiddleware()) ``` -Requiring authentication is not done by the authenticator middleware to allow for composition of authenticators. Read more about [composition](#composition) below. +Die Authentifizierung wird nicht von der Authentifikator-Middleware durchgeführt, um die Komposition von Authentifikatoren zu ermöglichen. Lies unten mehr über [composition](#composition) weiter. ## Basis @@ -173,7 +173,7 @@ app.grouped(UserPasswordAuthenticator()) .post("login") { req in let user = try req.auth.require(User.self) - // Do something with user. + // Mach etwas mit dem Benutzer. } ``` @@ -197,13 +197,13 @@ app.grouped(AdminAuthenticator()) guard req.auth.has(Admin.self) || req.auth.has(User.self) else { throw Abort(.unauthorized) } - // Do something. + // Mach etwas. } ``` -This example assumes two authenticators `AdminAuthenticator` and `UserAuthenticator` that authenticate `Admin` and `User`, respectively. Both of these authenticators are added to the route group. Instead of using `GuardMiddleware`, a check in the route handler is added to see if either `Admin` or `User` were authenticated. If not, an error is thrown. +In diesem Beispiel werden zwei Authentifikatoren `AdminAuthenticator` und `UserAuthenticator` angenommen, die jeweils `Admin` und `User` authentifizieren. Diese beiden Authentifikatoren werden der Routengruppe hinzugefügt. Anstatt `GuardMiddleware` zu verwenden, wird eine Prüfung im Routehandler hinzugefügt, um zu sehen, ob entweder `Admin` oder `User` authentifiziert wurden. Wenn nicht, wird ein Fehler ausgelöst. -This composition of authenticators results in a route that can be accessed by two different types of users with potentially different methods of authentication. Such a route could allow for normal user authentication while still giving access to a super-user. +Diese Zusammensetzung von Authentifikatoren führt zu einer Route, die von zwei verschiedenen Nutzertypen mit potenziell unterschiedlichen Authentifizierungsmethoden genutzt werden kann. Ein solcher Weg könnte eine normale Benutzerauthentifizierung ermöglichen und gleichzeitig einem Superuser Zugang gewähren. ## Anleitung @@ -241,7 +241,7 @@ req.auth.logout(User.self) _ModelTokenAuthenicatable_ ist für die Authentifizierung mit einem Bearer-Token. _ModelAuthenticatable_ ist für die Authentifizierung mittels Anmeldeinformationen und wird in den meisten Fällen nur auf einen einzigen Endpunkt angewendet, um eben einen solchen Bearer-Token zu erstellen. -This guide assumes you are familiar with Fluent and have successfully configured your app to use a database. If you are new to Fluent, start with the [overview](../fluent/overview.md). +In dieser Anleitung wird davon ausgegangen, dass du mit Fluent vertraut bist und deine App erfolgreich für die Verwendung einer Datenbank konfiguriert hast. Wenn du neu in Fluent bist, beginne mit der [Übersicht](../fluent/overview.md). ### Benutzer-Authentifizierung @@ -277,7 +277,7 @@ final class User: Model, Content { } ``` -Das Model. Das Feld _Email_ sollte unique sein, um Redundanzen zu vermeiden. Somit würde die Migration für das obere Beispiel so aussehen. +Das Model. Das Feld _Email_ sollte einzigartig sein, um Redundanzen zu vermeiden. Somit würde die Migration für das obere Beispiel so aussehen. ```swift import Fluent @@ -417,7 +417,7 @@ Authorization: Basic dGVzdEB2YXBvci5jb2RlczpzZWNyZXQ0Mg== Die Anfragen übergibt als Benutzernamen _test@vapor.codes_ und als Passwort _secret42_: -This request passes the username `test@vapor.codes` and password `secret42` via the Basic authentication header. You should see the previously created user returned. +Diese Anfrage übergibt den Benutzernamen `test@vapor.codes` und das Passwort `secret42` über den Basic Authentication Header. Du solltest den zuvor erstellten Benutzer zurückbekommen. In der Theorie können wir alle Endpunkte mit der Standardauthentifizierung versehen, was allerdings weniger ratsam wäre. Mit der Token-Authentifizierung übertragen wir viel seltener die sensiblen Daten über das Internet. Zumal ist die Authentifizierung um einiges schneller, da nur das Passwort-Hashing durchgeführt wird. @@ -643,7 +643,7 @@ Dieser Authentifikator authentifiziert einen Benutzer mit der E-Mail `hello@vapo Zum Schluss fügen wir all diese Teile in deiner Anwendung zusammen. ```swift -// Create protected route group which requires user auth. +// Erstelle eine geschützte Routengruppe, die eine Benutzeranmeldung erfordert. let protected = app.routes.grouped([ app.sessions.middleware, UserSessionAuthenticator(), @@ -651,7 +651,7 @@ let protected = app.routes.grouped([ User.guardMiddleware(), ]) -// Add GET /me route for reading user's email. +// Füge eine GET /me Route hinzu, um die E-Mail des Benutzers zu lesen. protected.get("me") { req -> String in try req.auth.require(User.self).email } @@ -690,7 +690,7 @@ import Fluent final class User: Model { ... } -// Allow this model to be persisted in sessions. +// Erlaube, dass dieses Modell in Sitzungen bestehen bleibt. extension User: ModelSessionAuthenticatable { } ``` @@ -803,13 +803,13 @@ Der `CredentialsAuthenticator` extrahiert den `Benutzernamen` und das `Passwort` Erstelle zunächst einen Typ, der eine JWT-Nutzlast repräsentiert. ```swift -// Example JWT payload. +// Beispiel JWT-Payload. struct SessionToken: Content, Authenticatable, JWTPayload { - // Constants + // Konstanten let expirationTime: TimeInterval = 60 * 15 - // Token Data + // Token Daten var expiration: ExpirationClaim var userId: UUID @@ -852,8 +852,8 @@ Wenn du keinen Authentifikator verwenden willst, kannst du auch etwas haben, das ```swift app.post("login") { req -> ClientTokenReponse in - // Validate provided credential for user - // Get userId for provided user + // Überprüfe die angegebenen Anmeldeinformationen für den Benutzer + // UserId für den angegebenen Benutzer abrufen let payload = try SessionToken(userId: userId) return ClientTokenReponse(token: try req.jwt.sign(payload)) } @@ -862,7 +862,7 @@ app.post("login") { req -> ClientTokenReponse in Indem du die Payload an `Authenticatable` und `JWTPayload` anpasst, kannst du mit der Methode `authenticator()` einen Routen-Authentifikator erzeugen. Füge diesen zu einer Routengruppe hinzu, um den JWT automatisch abzurufen und zu verifizieren, bevor deine Route aufgerufen wird. ```swift -// Create a route group that requires the SessionToken JWT. +// Erstelle eine Routengruppe, die das SessionToken JWT benötigt. let secure = app.grouped(SessionToken.authenticator(), SessionToken.guardMiddleware()) ``` @@ -871,7 +871,7 @@ Das Hinzufügen der optionalen [guard middleware](#guard-middleware) setzt vorau Innerhalb der geschützten Routen kannst du mit `req.auth` auf die authentifizierten JWT-Nutzdaten zugreifen. ```swift -// Return ok reponse if the user-provided token is valid. +// Gibt eine ok-Antwort zurück, wenn das vom Benutzer bereitgestellte Token gültig ist. secure.post("validateLoggedInUser") { req -> HTTPStatus in let sessionToken = try req.auth.require(SessionToken.self) print(sessionToken.userId) From f81b25c0695c247575b87931679ca83c07afccc7 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:49:21 +0200 Subject: [PATCH 13/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 961efa2b6..2e3b3d96b 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -762,7 +762,7 @@ let protectedRoutes = app.grouped([User.SessionAuthenticator(), redirecteMiddlew Für die Authentifizierung und spätere Sitzungen, die Anmeldung erfolgt meistens über ein Formular. -Um einen Benutzer und zukünftige Anfragen mit einer Sitzung zu authentifizieren, musst du einen Benutzer anmelden. Vapor bietet ein `ModelCredentialsAuthenticatable`-Protokoll, dem du entsprechen musst. Damit kannst du dich über ein Formular anmelden. Zuerst musst du deinen "User" an dieses Protokoll anpassen: +Um einen Benutzer und bestehende Sitzungen zu authentifizieren, muss sich zuerst ein Benutzer anmelden. Vapor stellt uns für die Anmeldungsabwicklung das Protokoll _ModelCredentialsAuthenticatable_ zur Verfügung, mit das wir unser Objekt _User_ versehen. ```swift extension User: ModelCredentialsAuthenticatable { From ad15122b3162c594b279294d768f5b3f77806d3a Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:49:32 +0200 Subject: [PATCH 14/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 2e3b3d96b..af306ed42 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -736,7 +736,8 @@ Diese Middlewares tun Folgendes: ### Routen schützen -Wenn du Routen für eine API schützt, gibst du traditionell eine HTTP-Antwort mit einem Statuscode wie **401 Unautorisiert** zurück, wenn die Anfrage nicht authentifiziert ist. Das ist jedoch keine gute Benutzererfahrung für jemanden, der einen Browser benutzt. Vapor bietet eine `RedirectMiddleware` für jeden `Authenticatable` Typ, die in diesem Szenario verwendet werden kann: +Geschütze Anwendungsendpunkte, zum Beispiel einer API, geben traditionell bei fehlgeschlagener Authentifizierung eine Serverantwort mit entsprechenden Status wie **401 Unautorisiert** zurück. Das ist jedoch für jemanden, der einen Browser benutzt, keine gute Benutzererfahrung, weswegen Vapor für jedes Objekt vom Typ _Authenticatable_ eine _RedirectMiddleware_ anbietet: + ```swift let protectedRoutes = app.grouped(User.redirectMiddleware(path: "/login?loginRequired=true")) From bfdd38ba7ee50f2b3b6a9328cc6da8cdf7de7303 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:49:47 +0200 Subject: [PATCH 15/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index af306ed42..2da4d0015 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -734,7 +734,7 @@ Diese Middlewares tun Folgendes: * Die Sitzung-Middleware nimmt das Session-Cookie aus der Anfrage und wandelt es in eine Session um. * der Sitzungs Authenticator nimmt die Session und prüft, ob es einen authentifizierten Benutzer für diese Session gibt. Wenn ja, authentifiziert die Middleware die Anfrage. In der Antwort sieht der Session Authenticator, ob die Anfrage einen authentifizierten Benutzer hat und speichert ihn in der Session, damit er bei der nächsten Anfrage authentifiziert ist. -### Routen schützen +### Anwendungsendpunkte schützen Geschütze Anwendungsendpunkte, zum Beispiel einer API, geben traditionell bei fehlgeschlagener Authentifizierung eine Serverantwort mit entsprechenden Status wie **401 Unautorisiert** zurück. Das ist jedoch für jemanden, der einen Browser benutzt, keine gute Benutzererfahrung, weswegen Vapor für jedes Objekt vom Typ _Authenticatable_ eine _RedirectMiddleware_ anbietet: From a40da9dc0b71e345bbcce70e7c1a666ba60ec0c1 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:49:55 +0200 Subject: [PATCH 16/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 2da4d0015..34f0ad9ef 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -717,7 +717,8 @@ Vapor und Fluent bieten verschiedene Hilfsmittel, um dies nahtlos zu ermögliche ### Cookie-Authentifizierung -Die Sitzungsauthentifizierung funktioniert wie oben beschrieben. Du musst die Sitzungs-Middleware und den Sitzungsauthentifikator auf alle Routen anwenden, auf die dein Nutzer zugreifen wird. Dazu gehören alle geschützten Routen, alle Routen, die zwar öffentlich sind, auf die du aber trotzdem zugreifen willst, wenn der Benutzer eingeloggt ist (um z. B. einen Konto-Button anzuzeigen) **und** Login-Routen. +Die Sitzungsauthentifizierung funktioniert wie oben beschrieben. Wir müssen die Sitzungs-Middleware und den Sitzungsauthentifikator auf allen Anwendungsendpunkten anwenden, auf die unser Nutzer zugreifen wird. Dazu gehören sowohl alle geschützten Endpunkte, Endpunkte für die Anmeldung, sowie auch alle öffentlich zugänglichen Endpunkte auf die nach der Anmeldung zugegriffen wird. (um z. B. einen Konto-Button anzuzeigen). + Du kannst dies global in deiner App in **configure.swift** wie folgt aktivieren: From 0d1af551eac77876f54372afc9479d8014108925 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:50:59 +0200 Subject: [PATCH 17/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 34f0ad9ef..43b53d857 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -29,9 +29,9 @@ struct User: Authenticatable { } ``` -### Endpunkt +### Anwendungsendpunkt -Endpunkte können mit Authentikatoren versehen werden. +Anwendungsendpunkte können mit den eingangs erwähnten Authenticator versehen werden um sie entsprechend zu schützen. ```swift let protected = app.grouped(UserAuthenticator()) From edde55e17a60f5f6e94736b8b9b927dd9a2f997a Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:51:10 +0200 Subject: [PATCH 18/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 43b53d857..4605e00da 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -15,7 +15,8 @@ Die Authentifizierung erfolgt durch einen sogenannten `Authenticator`, der die e | [`BearerAuthenticator`/`AsyncBearerAuthenticator`](#bearer) |Authentifiziert den Bearer-Autorisierungs-Header. | | `CredentialsAuthenticator`/`AsyncCredentialsAuthenticator` |Authentifiziert einen Credentials Payload aus dem Request Body.| -Bei erfolgreicher Authentifizierung übergibt der Authenticator die Benutzeridentität an die Eigenschaft `req.auth`. Mit der Methode `get(_:)` können wir auf die Identität zugreifen. Wenn die Authentifizierung fehl schlägt wird keine Identität übergeben und jeglicher Versuch, darauf zuzugreifen, schlägt fehl. +Bei erfolgreicher Authentifizierung übergibt der Authenticator die Benutzeridentität an die Eigenschaft `req.auth`. Mit der Methode `get(_:)` können wir auf die Identität zugreifen. Wenn die Authentifizierung fehlschlägt wird keine Identität übergeben und jeglicher Versuch, darauf zuzugreifen, scheitert. + ## Authentifizierbar From e6db5bdb4d76cb7cc6db8120e6180dba37ce3a33 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:51:19 +0200 Subject: [PATCH 19/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 4605e00da..7a5e9f14c 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -7,7 +7,7 @@ Bei der Authentifizierung handelt es sich um die Überprüfung einer Benutzeride Vapor ermöglicht die [Basis](https://tools.ietf.org/html/rfc7617)- und [Bearer](https://tools.ietf.org/html/rfc6750) Authentifizierung mittels dem `Authorization` Header. Man kann auch einen User mit den Daten die in der [Content](../basics/content.de.md) API sind authentifizieren. -Die Authentifizierung erfolgt durch einen sogenannten `Authenticator`, der die eigentliche Logik beinhaltet und dazu verwendet wird um, einzelne Endpunkte oder auch die gesamte Anwendung zu sichern. Ein `Authenticator` kann entweder einzelne Routengruppen schützen oder auch die ganze App. Die folgenden Authenticator-Helfer werden mit Vapor ausgeliefert: +Die Authentifizierung erfolgt durch einen sogenannten `Authenticator`, der die eigentliche Logik beinhaltet und dazu verwendet wird, einzelne Anwendungsendpunkte oder auch die gesamte Anwendung zu schützen. Vapor besitzt bereits mehrere `Authenticator`, die dir bei der Implementierung helfen: | Protokoll | Beschreibung | |-------------------------------------------------------------|----------------------------------------------------------| | `RequestAuthenticator`/`AsyncRequestAuthenticator` |Basis Authentifizierung, der Middleware erstellen kann. | From 1201d08d6559ab3be8c97b41457c9eab79068632 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:53:19 +0200 Subject: [PATCH 20/30] fix index.de.md --- docs/index.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.de.md b/docs/index.de.md index d91166a56..7917a389a 100644 --- a/docs/index.de.md +++ b/docs/index.de.md @@ -25,4 +25,4 @@ Die Dokumentationen zu älteren Versionen von Vapor findest du unter [https://le ## Authoren -Das Vapor Kernteam und viele andere Mitglieder der Vapor Community. +Das Vapor-Kernteam und viele weitere Mitglieder der Vapor-Community. From 344e5380a165c2b1d70c6c177130cdd831e686c5 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:53:43 +0200 Subject: [PATCH 21/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 7a5e9f14c..1e6979f0d 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -56,7 +56,7 @@ Die Authentifizierung wird nicht von der Authentifikator-Middleware durchgeführ ## Basis -Die Basis Authentifizierung überträgt mittels Authorization-Header Benutzername und Passwort an den Server. Benutzername und Passwort werden dabei mit einem Doppelpunkt-verkettet (z.B. `test:secret`), base-64 kodiert und mit dem Präfix `"Basic"` versehen. Die folgende Beispielanfrage kodiert den Benutzernamen "test" mit dem Passwort "secret". +Die Basis-Authentifizierung überträgt mittels Authorization-Header Benutzername und Passwort an den Server. Die beiden Angaben werden dabei durch einen Doppelpunkt miteinander verkettet (z.B. `test:secret`), in eine Base64-Zeichenfolge umgewandelt und mit dem Präfix `"Basic "` versehen. Das folgende Beispiel einer Anfrage verschlüsselt den Benutzernamen "test" mit dem Passwort "secret". ```http GET /me HTTP/1.1 From 8d6abeff529f072ff8a6b89e8c43ecc4a33f23f9 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:53:58 +0200 Subject: [PATCH 22/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 1e6979f0d..24d3195e4 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -67,8 +67,7 @@ Die Basis Authentifizierung wird nur einmalig verwendet, um nach der erfolgreich Durch den Token wird die Häufigkeit einer notwendigen Übermittlung des Passwortes verringert. Zudem sollte die Basis Authentifizierung nie im Klartext oder über eine unverschlüsselte Verbindung erfolgen. - -Damit wir die Basis - Authentifizierung in unserer Anwendung verwenden können, müssen wir eine Struktur anlegen und diese mit dem Protokoll `BasicAuthenticator versehen. Nachfolgend ist ein Beispiel für einen Authenticator zu sehen, der fest programmiert ist, um die obige Anfrage zu verifizieren. +Damit wir die Basis-Authentifizierung in unserer Anwendung verwenden können, müssen wir zuerst eine Struktur anlegen und diese mit dem Protokoll `BasicAuthenticator` versehen. ```swift import Vapor From 1ba67e9933378c110dcb8437592efe8f061842a6 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:54:06 +0200 Subject: [PATCH 23/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 24d3195e4..27da6175d 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -63,7 +63,7 @@ GET /me HTTP/1.1 Authorization: Basic dGVzdDpzZWNyZXQ= ``` -Die Basis Authentifizierung wird nur einmalig verwendet, um nach der erfolgreichen Authentifizierung einen Token zu erzeugen. +Die Basis-Authentifizierung wird nur einmalig verwendet, um nach der erfolgreichen Authentifizierung einen Token zu erzeugen. Durch den Token wird die Häufigkeit einer notwendigen Übermittlung des Passwortes verringert. Zudem sollte die Basis Authentifizierung nie im Klartext oder über eine unverschlüsselte Verbindung erfolgen. From c0d972d83001e354d3d2556dc4e8959bc998b98d Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:54:23 +0200 Subject: [PATCH 24/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 27da6175d..d6ebbdb39 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -706,7 +706,7 @@ Damit wird die Standarddatenbank der Anwendung für die Auflösung des Benutzers User.sessionAuthenticator(.sqlite) ``` -## Website-Authentifizierung +## Webseiten-Authentifizierung Websites sind ein Sonderfall für die Authentifizierung, denn die Verwendung eines Browsers schränkt die Möglichkeit ein, Anmeldeinformationen mit einem Browser zu verknüpfen. Das führt zu zwei verschiedenen Authentifizierungsszenarien: From 710cbc5ddfd5230f2d15bb691e9d2318279423f2 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:54:41 +0200 Subject: [PATCH 25/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index d6ebbdb39..7c879afdc 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -708,7 +708,7 @@ User.sessionAuthenticator(.sqlite) ## Webseiten-Authentifizierung -Websites sind ein Sonderfall für die Authentifizierung, denn die Verwendung eines Browsers schränkt die Möglichkeit ein, Anmeldeinformationen mit einem Browser zu verknüpfen. Das führt zu zwei verschiedenen Authentifizierungsszenarien: +Webseiten sind im Bezug auf die Authentifizierung ein Sonderfall, denn die Verwendung eines Browsers schränkt die Möglichkeiten zur Verknüpfung von Anmeldeinformationen mit dem Browser ein. Was zu zwei verschiedenen Authentifizierungsszenarien führt: * die Erstanmeldung über ein Formular * nachfolgende Aufrufe, die mit einem Session-Cookie authentifiziert werden From 9ebdbe4a557b747a740cac2f06e27c1d4d668c3e Mon Sep 17 00:00:00 2001 From: Dominik K Date: Tue, 3 Oct 2023 11:56:18 +0200 Subject: [PATCH 26/30] fix: versuch --- docs/security/authentication.de.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 7c879afdc..5435bc48f 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -760,10 +760,6 @@ Achte darauf, einen Session Authenticator vor der `RedirectMiddleware` einzubind let protectedRoutes = app.grouped([User.SessionAuthenticator(), redirecteMiddleware]) ``` -### Formularanfrage - -Für die Authentifizierung und spätere Sitzungen, die Anmeldung erfolgt meistens über ein Formular. - Um einen Benutzer und bestehende Sitzungen zu authentifizieren, muss sich zuerst ein Benutzer anmelden. Vapor stellt uns für die Anmeldungsabwicklung das Protokoll _ModelCredentialsAuthenticatable_ zur Verfügung, mit das wir unser Objekt _User_ versehen. ```swift @@ -879,4 +875,4 @@ secure.post("validateLoggedInUser") { req -> HTTPStatus in print(sessionToken.userId) return .ok } -``` \ No newline at end of file +``` From 9f7928908ebcf01b333686183b71d434acebf781 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 1 Nov 2023 13:31:19 +0100 Subject: [PATCH 27/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 5435bc48f..7c4d36dc8 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -117,7 +117,7 @@ GET /me HTTP/1.1 Authorization: Bearer foo ``` -Die Bearerauthentifierzung wird für die Authentifizerung von API-Endpunkten verwendet. Dabei fragt der User nach einem Token, indem er Benutzername und Passwort an einen Login-Endpunkt schickt. Der Token ist anschließend für einen gewissen Zeitraum gültig. +Die Bearerauthentifizierung wird in der Regel für die Authentifizierung von API-Endpunkten verwendet. Dabei fragt der Benutzer nach einem Token, indem er Anmeldeinformationen wie z. B. Benutzername und Passwort an einen entsprechenden API-Endpunkt schickt und daraufhin eine Token zurück erhält. Der Token ist anschließend für einen gewissen Zeitraum gültig. Innerhalb der Gültigkeit kann der Benutzer den Token an Stelle der eigentlichen Anmeldeinformationen verwenden. Mit dem Ablauf des Tokens, muss über den Endpunkt einer neuer Token angefordert werden. From 45a4b0314089fbcb72bce97fb7b845bcf81695b2 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 1 Nov 2023 13:31:33 +0100 Subject: [PATCH 28/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 7c4d36dc8..8f22d9c1c 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -110,7 +110,8 @@ Das Protokoll verlangt, dass wir die Methode _authenticate(basic:for:)_ anlegen. ## Bearer -Die Bearerauthentifierzung sendet einen Token an den Server. Der Token wird mit dem Prefix `Bearer` versehen. +Die Bearerauthentifizierung sendet einen Token an den Server. Der Token wird mit dem Prefix `Bearer` versehen. + ```http GET /me HTTP/1.1 From 8b547f18cd763616e15a4e4c4a57c2caf4185a99 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 1 Nov 2023 13:31:42 +0100 Subject: [PATCH 29/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index 8f22d9c1c..b6a888b24 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -120,7 +120,8 @@ Authorization: Bearer foo Die Bearerauthentifizierung wird in der Regel für die Authentifizierung von API-Endpunkten verwendet. Dabei fragt der Benutzer nach einem Token, indem er Anmeldeinformationen wie z. B. Benutzername und Passwort an einen entsprechenden API-Endpunkt schickt und daraufhin eine Token zurück erhält. Der Token ist anschließend für einen gewissen Zeitraum gültig. -Innerhalb der Gültigkeit kann der Benutzer den Token an Stelle der eigentlichen Anmeldeinformationen verwenden. Mit dem Ablauf des Tokens, muss über den Endpunkt einer neuer Token angefordert werden. +Innerhalb der Gültigkeit kann der Benutzer den Token an Stelle der eigentlichen Anmeldeinformationen verwenden. Mit Ablauf des Tokens, muss über den Endpunkt einer neuer Token angefordert werden. + Zur Verwendung einer Bearerauthentifizierung, müssen wir eine Struktur erstellen und diese mit dem Protokoll `BearerAuthenticator` versehen. From 49cb8fcf0e0210a1ad73b1068cf631afdf2ed172 Mon Sep 17 00:00:00 2001 From: Dominik K Date: Wed, 1 Nov 2023 13:31:48 +0100 Subject: [PATCH 30/30] Update docs/security/authentication.de.md Co-authored-by: Mattes Mohr --- docs/security/authentication.de.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/security/authentication.de.md b/docs/security/authentication.de.md index b6a888b24..8c4b257c4 100644 --- a/docs/security/authentication.de.md +++ b/docs/security/authentication.de.md @@ -183,9 +183,7 @@ Im folgenden Beispiel folgt das Objekt _UserTokenAuthenticator_ dem _UserPasswor In diesem Beispiel wird von zwei Authentifikatoren `UserPasswordAuthenticator` und `UserTokenAuthenticator` ausgegangen, die beide `User` authentifizieren. Diese beiden Authentifikatoren werden der Routengruppe hinzugefügt. Schließlich wird `GuardMiddleware` nach den Authentifikatoren hinzugefügt, um sicherzustellen, dass `User` erfolgreich authentifiziert wurde. -Die Zusammenstellung der Authentikator macht es möglich, dass der Benutzer sich - -Diese Zusammensetzung von Authentifikatoren führt zu einer Route, auf die entweder mit einem Passwort oder einem Token zugegriffen werden kann. Ein solcher Weg könnte es einem Benutzer ermöglichen, sich anzumelden und ein Token zu generieren, das er dann weiter zur Generierung neuer Token verwenden kann. +Die Kombination aus den beiden oben genannten Authentifikatoren ermöglicht den Zugriff mit einem Passwort oder einem Token. Auf dieser Weise kann sich ein Benutzer anmelden um wiederum regelmäßig einen Token zu generieren. ### Kombinieren von Benutzern