> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Vergleich der Authentifizierungsmethoden - Laravel Bluesky

> Erläutert die Unterschiede zwischen App Password (LegacyAgent) und OAuth (OAuthAgent) in Laravel Bluesky, ihre interne Architektur und Codebeispiele.

## Überblick

Laravel Bluesky unterstützt zwei Authentifizierungsmethoden. Die API-Aufrufe nach der Authentifizierung sind bei beiden Methoden identisch.

| Punkt                     | App Password                                       | OAuth                                              |
| ------------------------- | -------------------------------------------------- | -------------------------------------------------- |
| Interne Klassen           | `LegacyAgent` / `LegacySession`                    | `OAuthAgent` / `OAuthSession`                      |
| Einstiegspunkt            | `Bluesky::login()`                                 | `Bluesky::withToken(OAuthSession)`                 |
| Privater Schlüssel        | Nicht erforderlich                                 | `BLUESKY_OAUTH_PRIVATE_KEY` erforderlich           |
| Nutzer-Autorisierung      | Nicht erforderlich                                 | Erforderlich (Bestätigung im Browser)              |
| Ausführung im Hintergrund | ✅ Gut geeignet                                     | ✅ Möglich (refresh\_token speichern)               |
| Session-Schlüssel         | `accessJwt` / `refreshJwt`                         | `access_token` / `refresh_token`                   |
| Abkündigung geplant       | **Nein**                                           | —                                                  |
| Hauptanwendung            | Auto-Posts, Benachrichtigungen, Batch-Verarbeitung | Aktionen im Namen von Nutzern, Socialite-Anbindung |

<Info>
  Der Name `LegacyAgent` bedeutet „Authentifizierungsmethode vor OAuth", App Password selbst ist jedoch nicht als deprecated markiert. In Szenarien ohne Nutzerinteraktion, wie Benachrichtigungen und automatisierten Posts, ist App Password einfacher und passender.
</Info>

## Architektur

```mermaid theme={null}
classDiagram
    class BlueskyManager {
        +login(identifier, password) Factory
        +withToken(session) Factory
        +agent() Agent
        +check() bool
        +refreshSession() Factory
    }
    class LegacyAgent {
        +session LegacySession
        +http() PendingRequest
        +refreshSession() self
    }
    class OAuthAgent {
        +session OAuthSession
        +http() PendingRequest
        +refreshSession() self
    }
    class LegacySession {
        +accessJwt
        +refreshJwt
        +did
        +handle
        +token() string
        +refresh() string
    }
    class OAuthSession {
        +access_token
        +refresh_token
        +did
        +iss
        +token() string
        +refresh() string
        +issuer() string
    }

    BlueskyManager --> LegacyAgent : login()
    BlueskyManager --> OAuthAgent : withToken(OAuthSession)
    BlueskyManager --> LegacyAgent : withToken(LegacySession)
    LegacyAgent --> LegacySession : holds
    OAuthAgent --> OAuthSession : holds
```

`BlueskyManager` ist die Implementierung hinter der Facade `Bluesky`. Mit `login()` oder `withToken()` konfigurieren Sie den Agent, danach nutzen die API-Aufrufe unabhängig von der Authentifizierungsmethode dieselben Methoden.

## App Password (LegacyAgent)

### Authentifizierungsfluss

```mermaid theme={null}
sequenceDiagram
    participant App as Laravel-Anwendung
    participant Bluesky as Bluesky-Server

    App->>Bluesky: createSession(identifier, password)
    Bluesky-->>App: LegacySession (accessJwt + refreshJwt)
    App->>App: LegacyAgent::create(session)
    App->>Bluesky: API-Aufruf (Bearer accessJwt)
    Bluesky-->>App: Response
    Note over App: Wenn accessJwt abgelaufen ist
    App->>Bluesky: refreshSession (refreshJwt)
    Bluesky-->>App: Neue accessJwt + refreshJwt
```

### Bluesky::login()

Setzen Sie das App Password in `.env` und rufen Sie `login()` auf.

```dotenv theme={null}
BLUESKY_IDENTIFIER=your-handle.bsky.social
BLUESKY_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx
```

```php theme={null}
use Revolution\Bluesky\Facades\Bluesky;

$response = Bluesky::login(
    identifier: config('bluesky.identifier'),
    password: config('bluesky.password'),
)->post('Hello Bluesky');
```

### Wiederverwendung der LegacySession

Wenn Sie jedes Mal `login()` aufrufen, entsteht jedes Mal eine API-Anfrage. Es ist effizienter, die Session zu cachen und wiederzuverwenden.

```php theme={null}
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Session\LegacySession;

// Erstes Login und Session speichern
Bluesky::login(
    identifier: config('bluesky.identifier'),
    password: config('bluesky.password'),
);
cache()->put('bluesky_session', Bluesky::agent()->session()->toArray(), now()->addDay());

// Beim nächsten Mal aus dem Cache wiederherstellen
$session = LegacySession::create(cache('bluesky_session', []));
Bluesky::withToken($session);

// Access Token bei Ablauf aktualisieren
if (! Bluesky::check()) {
    Bluesky::refreshSession();
}

$response = Bluesky::post('Hello from cached session');
```

### Wichtige Schlüssel der LegacySession

| Schlüssel    | Inhalt                 | Methode     |
| ------------ | ---------------------- | ----------- |
| `accessJwt`  | Access Token           | `token()`   |
| `refreshJwt` | Refresh Token          | `refresh()` |
| `did`        | Bluesky-DID            | `did()`     |
| `handle`     | Handle                 | `handle()`  |
| `email`      | E-Mail-Adresse         | `email()`   |
| `active`     | Ob das Konto aktiv ist | `active()`  |

### Geeignete Anwendungsfälle

* Auto-Posts in Background-Jobs / Queues
* Benachrichtigungen über einen Laravel-Notification-Kanal
* Batch-Verarbeitung und Scheduling
* Posten unter dem eigenen Konto der Anwendung

## OAuth (OAuthAgent)

### Authentifizierungsfluss

```mermaid theme={null}
sequenceDiagram
    participant User as Nutzer
    participant App as Laravel-Anwendung
    participant Bluesky as Bluesky-Server

    User->>App: Login-Formular abschicken (Handle eingeben)
    App->>Bluesky: PAR-Request (inkl. login_hint)
    Bluesky-->>App: request_uri
    App->>Bluesky: Redirect zum Authorization Endpoint
    User->>Bluesky: Login bei Bluesky bestätigen
    Bluesky-->>App: Callback (code + iss)
    App->>Bluesky: Token-Austausch mit DPoP
    Bluesky-->>App: OAuthSession (access_token + refresh_token)
    App->>User: Login abgeschlossen
    App->>Bluesky: API-Aufruf (DPoP access_token)
    Bluesky-->>App: Response
```

### Bluesky::withToken()

Übergeben Sie die per Socialite erhaltene `OAuthSession` an `withToken()`.

```php theme={null}
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Session\OAuthSession;

// Aus Laravel-Session wiederherstellen (Web-Request)
$session = OAuthSession::create(session('bluesky_session'));
$timeline = Bluesky::withToken($session)->getTimeline();
```

Auch in Background-Jobs oder in der Konsole können Sie die `OAuthSession` aus in der DB gespeicherten Werten zusammenbauen.

```php theme={null}
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Session\OAuthSession;

$session = OAuthSession::create([
    'did'           => $user->did,
    'refresh_token' => $user->refresh_token,
    // Für Konten außerhalb von bsky.social auch iss angeben
    // 'iss'        => $user->iss,
]);

$response = Bluesky::withToken($session)
                   ->refreshSession()
                   ->post('Hello from OAuth');
```

### Wichtige Schlüssel der OAuthSession

| Schlüssel             | Inhalt                                | Methode         |
| --------------------- | ------------------------------------- | --------------- |
| `access_token`        | Access Token                          | `token()`       |
| `refresh_token`       | Refresh Token (nur einmal verwendbar) | `refresh()`     |
| `did` / `sub`         | Bluesky-DID                           | `did()`         |
| `iss`                 | URL des Authorization Servers         | `issuer()`      |
| `profile.handle`      | Handle                                | `handle()`      |
| `profile.displayName` | Anzeigename                           | `displayName()` |

<Warning>
  Der OAuth-refresh\_token kann nur einmal verwendet werden. Aktualisieren Sie mithilfe des Events `OAuthSessionUpdated` nach jedem Token-Refresh unbedingt die DB. Details siehe [Socialite](/de/packages/laravel-bluesky/socialite).
</Warning>

### Geeignete Anwendungsfälle

* Nutzer-Login mittels Socialite
* API-Operationen im Namen des Nutzers
* Wenn Operationen mit unterschiedlichen Konten pro Nutzer erforderlich sind

## API-Aufrufe nach der Authentifizierung sind gemeinsam

Nach `withToken()` verwenden Sie unabhängig von der Authentifizierungsmethode dieselben API-Methoden.

```php theme={null}
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Session\LegacySession;
use Revolution\Bluesky\Session\OAuthSession;

// App Password
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'));

// oder OAuth
$session = OAuthSession::create(session('bluesky_session'));
Bluesky::withToken($session);

// ↓ Die nachfolgenden API-Aufrufe sind vollständig gleich ↓

Bluesky::post('Hello Bluesky');
Bluesky::getTimeline();
Bluesky::getProfile();
Bluesky::searchPosts(q: '#laravel');
```

`BlueskyManager` verwendet intern je nach Bedarf `LegacyAgent` oder `OAuthAgent`, für den aufrufenden Code macht das keinen Unterschied.

## Welche Methode wählen?

```mermaid theme={null}
flowchart TD
    A["Welche Authentifizierungsmethode verwenden?"] --> B{"Muss sich der Nutzer<br>mit seinem Bluesky-Konto anmelden?"}
    B -->|"Ja"| C["OAuth (OAuthAgent)<br>Socialite-Integration"]
    B -->|"Nein"| D{"Wird unter dem<br>eigenen App-Konto agiert?"}
    D -->|"Ja"| E["App Password (LegacyAgent)<br>einfach zu betreiben"]
    D -->|"Aktionen im Auftrag mehrerer Nutzer"| C
```

| Situation                                       | Empfehlung   |
| ----------------------------------------------- | ------------ |
| Auto-Posts, Benachrichtigungen, Batch           | App Password |
| Login-Funktion für Nutzer                       | OAuth        |
| Nur Background-Jobs                             | App Password |
| Aktionen im Namen von Nutzern nötig             | OAuth        |
| Einfachen Betrieb priorisieren                  | App Password |
| Fokus auf Sicherheit und Berechtigungssteuerung | OAuth        |

<Tip>
  Bei Unsicherheit ist die Aufteilung nach Zweck am einfachsten: „Die App agiert selbst" → App Password, „Der Nutzer bedient sie" → OAuth. Beide lassen sich auch kombinieren – ein gängiger Aufbau ist App Password für Benachrichtigungen und OAuth für Nutzer-Login.
</Tip>

## Weiterführende Links

* [Basic client](/de/packages/laravel-bluesky/basic-client) – API-Operationen nach der Authentifizierung
* [Socialite](/de/packages/laravel-bluesky/socialite) – Details zum OAuth-Ablauf
* [Notification-Kanal](/de/packages/laravel-bluesky/notification) – Benachrichtigungen über App Password / OAuth
* Source: [invokable/laravel-bluesky](https://github.com/invokable/laravel-bluesky)


## Related topics

- [BlueskyManager und HasShortHand](/de/packages/laravel-bluesky/bluesky-manager.md)
- [Laravel Sentinel – Analyse der Route-Schutz-Middleware](/de/blog/sentinel-introduction.md)
- [Authentifizierung - GitHub Copilot SDK für Laravel](/de/packages/laravel-copilot-sdk/auth.md)
- [Erste Schritte - VOICEVOX für Laravel](/de/packages/laravel-voicevox/getting-started.md)
- [Hashing](/de/hashing.md)
