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

# Comparativa de métodos de autenticación - Laravel Bluesky

> Explica las diferencias entre App Password (LegacyAgent) y OAuth (OAuthAgent) de Laravel Bluesky, su arquitectura interna y ejemplos de código.

## Descripción general

Laravel Bluesky admite dos métodos de autenticación. Las llamadas a la API tras autenticarse son comunes en ambos.

| Elemento                   | App Password                                                  | OAuth                                                   |
| -------------------------- | ------------------------------------------------------------- | ------------------------------------------------------- |
| Clases internas            | `LegacyAgent` / `LegacySession`                               | `OAuthAgent` / `OAuthSession`                           |
| Punto de entrada           | `Bluesky::login()`                                            | `Bluesky::withToken(OAuthSession)`                      |
| Clave privada              | No necesaria                                                  | Se requiere `BLUESKY_OAUTH_PRIVATE_KEY`                 |
| Autorización del usuario   | No necesaria                                                  | Necesaria (aprobación en el navegador)                  |
| Ejecución en segundo plano | ✅ Muy adecuada                                                | ✅ Posible (guardando refresh\_token)                    |
| Claves de sesión           | `accessJwt` / `refreshJwt`                                    | `access_token` / `refresh_token`                        |
| Desaprobación              | **Ninguna**                                                   | —                                                       |
| Usos principales           | Publicaciones automáticas, notificaciones, procesos por lotes | Actuar en nombre del usuario, integración con Socialite |

<Info>
  El nombre `LegacyAgent` significa "método de autenticación anterior a OAuth", pero App Password en sí no está marcado como obsoleto. En escenarios sin interacción del usuario, como notificaciones o publicaciones automáticas, App Password suele ser más sencillo y adecuado.
</Info>

## Arquitectura

```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` es la implementación real del Facade `Bluesky`. Configuras un agente con `login()` o `withToken()` y, a partir de ahí, las llamadas a la API usan los mismos métodos en cualquiera de los dos métodos de autenticación.

## App Password (LegacyAgent)

### Flujo de autenticación

```mermaid theme={null}
sequenceDiagram
    participant App as Aplicación Laravel
    participant Bluesky as Servidor de Bluesky

    App->>Bluesky: createSession(identifier, password)
    Bluesky-->>App: LegacySession (accessJwt + refreshJwt)
    App->>App: LegacyAgent::create(session)
    App->>Bluesky: Llamada a la API (Bearer accessJwt)
    Bluesky-->>App: Respuesta
    Note over App: Si accessJwt ha caducado
    App->>Bluesky: refreshSession (refreshJwt)
    Bluesky-->>App: Nuevos accessJwt + refreshJwt
```

### Bluesky::login()

Solo tienes que configurar el App Password en `.env` y llamar a `login()`.

```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');
```

### Reutilizar LegacySession

Llamar a `login()` cada vez implica una petición a la API en cada ocasión. Cachear la sesión y reutilizarla es más eficiente.

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

// Login inicial y guardado de la sesión
Bluesky::login(
    identifier: config('bluesky.identifier'),
    password: config('bluesky.password'),
);
cache()->put('bluesky_session', Bluesky::agent()->session()->toArray(), now()->addDay());

// A partir de aquí, restaura desde la caché
$session = LegacySession::create(cache('bluesky_session', []));
Bluesky::withToken($session);

// Si el access token ha caducado, refréscalo
if (! Bluesky::check()) {
    Bluesky::refreshSession();
}

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

### Claves principales de LegacySession

| Clave        | Contenido                | Método      |
| ------------ | ------------------------ | ----------- |
| `accessJwt`  | Access token             | `token()`   |
| `refreshJwt` | Refresh token            | `refresh()` |
| `did`        | DID de Bluesky           | `did()`     |
| `handle`     | Handle                   | `handle()`  |
| `email`      | Correo electrónico       | `email()`   |
| `active`     | Si la cuenta está activa | `active()`  |

### Casos de uso adecuados

* Publicaciones automáticas en jobs de segundo plano y en la cola
* Notificaciones mediante los canales de Laravel Notification
* Procesos por lotes y tareas programadas
* Publicar desde la propia cuenta de la aplicación

## OAuth (OAuthAgent)

### Flujo de autenticación

```mermaid theme={null}
sequenceDiagram
    participant User as Usuario
    participant App as Aplicación Laravel
    participant Bluesky as Servidor de Bluesky

    User->>App: Envía formulario de login (introduce el handle)
    App->>Bluesky: Petición PAR (incluye login_hint)
    Bluesky-->>App: request_uri
    App->>Bluesky: Redirige al endpoint de autorización
    User->>Bluesky: Aprueba el login en Bluesky
    Bluesky-->>App: Callback (code + iss)
    App->>Bluesky: Intercambio de tokens usando DPoP
    Bluesky-->>App: OAuthSession (access_token + refresh_token)
    App->>User: Login completado
    App->>Bluesky: Llamada a la API (DPoP access_token)
    Bluesky-->>App: Respuesta
```

### Bluesky::withToken()

Pasas a `withToken()` el `OAuthSession` obtenido con Socialite.

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

// Restaurar desde la sesión de Laravel (petición web)
$session = OAuthSession::create(session('bluesky_session'));
$timeline = Bluesky::withToken($session)->getTimeline();
```

Incluso en jobs de segundo plano o en la consola, puedes construir `OAuthSession` a partir de valores guardados en la base de datos.

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

$session = OAuthSession::create([
    'did'           => $user->did,
    'refresh_token' => $user->refresh_token,
    // Para cuentas que no son de bsky.social, indica también iss
    // 'iss'        => $user->iss,
]);

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

### Claves principales de OAuthSession

| Clave                 | Contenido                           | Método          |
| --------------------- | ----------------------------------- | --------------- |
| `access_token`        | Access token                        | `token()`       |
| `refresh_token`       | Refresh token (usable una sola vez) | `refresh()`     |
| `did` / `sub`         | DID de Bluesky                      | `did()`         |
| `iss`                 | URL del servidor de autorización    | `issuer()`      |
| `profile.handle`      | Handle                              | `handle()`      |
| `profile.displayName` | Nombre mostrado                     | `displayName()` |

<Warning>
  El refresh\_token de OAuth solo se puede usar una vez. Usa el evento `OAuthSessionUpdated` para actualizar siempre la base de datos tras un refresh de tokens. Consulta los detalles en [Socialite](/es/packages/laravel-bluesky/socialite).
</Warning>

### Casos de uso adecuados

* Login de usuarios mediante Socialite
* Operaciones a la API en nombre del usuario
* Cuando cada usuario debe operar con una cuenta distinta

## Las llamadas a la API tras autenticarse son comunes

Con cualquiera de los dos métodos de autenticación, tras `withToken()` se utilizan los mismos métodos de la API.

```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'));

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

// ↓ A partir de aquí, las llamadas a la API son completamente comunes ↓

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

`BlueskyManager` alterna internamente entre `LegacyAgent` y `OAuthAgent`, pero el código que llama a la API no se ve afectado.

## ¿Cuál elegir?

```mermaid theme={null}
flowchart TD
    A["¿Qué método de autenticación usar?"] --> B{"¿El usuario debe<br>iniciar sesión con su cuenta de Bluesky?"}
    B -->|"Sí"| C["OAuth (OAuthAgent)<br>Integración con Socialite"]
    B -->|"No"| D{"¿Se opera con la propia cuenta<br>de la aplicación?"}
    D -->|"Sí"| E["App Password (LegacyAgent)<br>Simple y fácil de operar"]
    D -->|"Se actúa en nombre de varios usuarios"| C
```

| Situación                                        | Recomendación |
| ------------------------------------------------ | ------------- |
| Publicaciones automáticas, notificaciones, lotes | App Password  |
| Función de login de usuarios                     | OAuth         |
| Solo jobs de segundo plano                       | App Password  |
| Necesidad de actuar en nombre del usuario        | OAuth         |
| Prioridad a la simplicidad operativa             | App Password  |
| Prioridad a seguridad y control de permisos      | OAuth         |

<Tip>
  Cuando dudes, lo más claro es distinguir por el objetivo. Si "la aplicación actúa por sí sola", usa App Password; si "el usuario opera", usa OAuth. También es habitual combinar ambos: App Password para notificaciones y OAuth para el login de usuarios.
</Tip>

## Enlaces de referencia

* [Basic client](/es/packages/laravel-bluesky/basic-client) — operaciones de API tras autenticarse
* [Socialite](/es/packages/laravel-bluesky/socialite) — detalles del flujo OAuth
* [Canal de notificaciones](/es/packages/laravel-bluesky/notification) — notificaciones con App Password / OAuth
* Source: [invokable/laravel-bluesky](https://github.com/invokable/laravel-bluesky)


## Related topics

- [Canal de notificaciones - Laravel Bluesky](/es/packages/laravel-bluesky/notification.md)
- [Autenticación - GitHub Copilot SDK for Laravel](/es/packages/laravel-copilot-sdk/auth.md)
- [Tutorial de bots - Laravel Bluesky](/es/packages/laravel-bluesky/bot-tutorial.md)
- [BlueskyManager y HasShortHand](/es/packages/laravel-bluesky/bluesky-manager.md)
- [Socialite - Laravel Bluesky](/es/packages/laravel-bluesky/socialite.md)
