Download the PHP package gimucco/atproto-php without Composer

On this page you can find all versions of the php package gimucco/atproto-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package atproto-php

gimucco/atproto-php

AT Protocol OAuth 2.1 client for PHP — PKCE, DPoP, and PAR support for authenticating with Bluesky and other atproto services.

Latest Version PHP Version License CI


What this is (and isn't)

This library handles OAuth 2.1 authentication with any AT Protocol Personal Data Server (PDS). It gives you an authenticated session you can use to make API calls.

This is OAuth only. It does not implement Bluesky-specific operations like posting, fetching feeds, or managing profiles. For that, see the companion library gimucco/bluesky-php.

Why use this

Existing PHP libraries for AT Protocol only support the deprecated App Password flow. App Passwords are being phased out. The AT Protocol mandates a strict OAuth 2.1 profile that combines several features most OAuth libraries don't handle together:

This library handles all of it.

Requirements

Installation

Quickstart

Concepts

Client Metadata Document

AT Protocol OAuth uses a URL as the client_id. The authorization server fetches this URL to learn about your application. You host a JSON document containing your app name, redirect URIs, and public key. Use ClientMetadataBuilder::fromConfig() to generate it.

JWKS (JSON Web Key Set)

Confidential clients authenticate using private_key_jwt — signing a JWT with an ES256 private key. The corresponding public key is published as a JWKS document. Use ClientMetadataBuilder::jwksFromConfig() to generate it.

DPoP (Demonstrating Proof of Possession)

Every token and API request includes a DPoP proof — a short-lived JWT proving the request came from the holder of a specific key. This library handles DPoP automatically, including the mandatory server nonce exchange (the "double-call" pattern).

Session Storage

Sessions hold access tokens, refresh tokens, and DPoP keys. This library provides three storage backends. See Session Storage below.

For deeper reading, see the AT Protocol OAuth specification and the OAuth client implementation guide.

Generating your client keypair

Generate an ES256 (P-256) private key:

This key is used for two things:

  1. Client assertion — authenticating to the token endpoint
  2. JWKS — publishing the public key for the authorization server to verify

Keep private.pem secret. Never commit it to version control.

Hosting client metadata and JWKS

You need to serve two JSON documents at stable HTTPS URLs: client-metadata.json and jwks.json. Their contents are static for any given app, derived from your config and key.

Generate them with the bundled CLI tool:

This writes client-metadata.json and jwks.json to the output directory. Re-run after any config or key change. The output files are static — serve them directly via Nginx, Apache, or any CDN. No PHP needed at request time.

For example

Important: The client_id value in your config must exactly match the URL where client-metadata.json is hosted.

If you'd rather generate them in your own application code (e.g., during a deploy hook), the underlying API is ClientMetadataBuilder::fromConfig($config) and ClientMetadataBuilder::jwksFromConfig($config) — both return associative arrays you can json_encode and write wherever you like.

Multiple redirect URIs (one client_id, multiple flows)

A single client_id can declare multiple redirect_uris — useful when one app needs distinct callback URLs for separate flows (e.g., login vs. account-linking, or web vs. mobile). The CLI accepts an array:

At runtime, create one ClientConfig per flow — same clientId, privateKey, and encryptionPassphrase, different redirectUri. Sessions are keyed by DID and refreshable through any config that shares those three fields, so a session minted by the login flow is fully usable from the link flow:

If you generate the metadata document programmatically (not via the CLI), pass the extra URIs through additionalRedirectUris:

additionalRedirectUris is purely declarative — it only affects the metadata JSON. At runtime, each ClientConfig still uses its own redirectUri for PAR and token exchange.

The full OAuth flow

Step 1: Start authorization

The library supports two flows:

Identity-first — the user enters their handle, you pre-fill the auth server's identifier field:

The library resolves the handle → DID → PDS → auth server, then sends the PAR with login_hint set so the auth server pre-fills the identifier on its sign-in page.

Server-first — the user picks their account on the auth server's own page:

This skips identity resolution entirely and redirects to the auth server configured by ClientConfig::$defaultAuthorizationServer (default: https://bsky.social). The user's actual identity is determined post-auth from the sub claim in the token response, then resolved.

To target a specific atproto host (e.g., a self-hosted PDS) without entering a handle, override per-call or in config:

Step 2: Handle the callback

The library validates:

Making authenticated requests

Every request automatically:

Raw / binary uploads

For endpoints that accept binary input — e.g. com.atproto.repo.uploadBlob for images and videos — use authenticatedRawRequest(). The body is sent verbatim with a caller-controlled Content-Type:

Same guarantees as authenticatedRequest(): DPoP proof, nonce retry, auto-refresh. The body is passed through unchanged — no JSON encoding, no transformation. If you need to override Content-Type after the fact (rare), an entry in $headers wins (case-insensitive).

authenticatedRequest() (array body, JSON-encoded) and authenticatedRawRequest() (string body, caller-typed) are the two primitives. Use the former for typed XRPC procedures, the latter for binary uploads.

Session storage

InMemory (testing)

File-based

PDO (MySQL, PostgreSQL, SQLite)

Schema supports MySQL, PostgreSQL, and SQLite:

Encryption at rest

When you provide a passphrase, access tokens, refresh tokens, and DPoP private keys are encrypted using sodium_crypto_secretbox before storage. If you don't provide one, a warning is logged but storage works in plaintext.

Token refresh

Automatic

When you call $session->authenticatedRequest(), the library checks if the access token is near expiry (within 60 seconds) and refreshes it automatically.

Manual

Checking expiry

Error handling

All exceptions extend Gimucco\Atproto\Exception\AtprotoException:

Exception hierarchy

Logging

Inject any PSR-3 logger:

The library logs:

Security

The library applies several protections by default: SSRF blocking on outbound requests, sub-claim and issuer validation on the OAuth callback, and optional libsodium encryption of tokens and DPoP keys at rest.

See SECURITY.md for the full security model, threat model, vulnerability reporting, and guidance on storing the client private key, choosing an encryption passphrase, and the SSRF guard's TOCTOU window.

Troubleshooting

"use_dpop_nonce" errors

This is normal. The AT Protocol requires DPoP nonces, and the first request to any server will fail with use_dpop_nonce. The library retries automatically. If you see this in logs, it's working correctly.

client_id URL must match exactly

The URL in your ClientConfig::clientId must match the URL where you host the client metadata document exactly — same scheme, host, path, and no trailing slash differences.

Clock skew on DPoP iat

DPoP proofs include an iat (issued-at) timestamp. If your server clock is off by more than a few seconds, the authorization server may reject them. Use NTP to keep your clock synced.

"Sub mismatch" error

After token exchange, the library verifies the sub claim in the token response matches the DID resolved during beginAuthorization(). If they don't match, this is a security check failure — the authorization server returned tokens for a different user than expected.

SSL certificate issues in development

If you're testing locally, you may need to configure your HTTP client to accept self-signed certificates. With Guzzle:

Never do this in production.

Testing your integration

See the examples/ directory for a complete working example you can run locally:

Roadmap

Planned for future releases (not yet implemented):

Contributing

See CONTRIBUTING.md for development setup, testing, and submission guidelines.

License

This project is licensed under GPL-2.0-or-later. See LICENSE for the full text.

Attribution

Portions of this library are adapted from Automattic/wordpress-atmosphere, licensed under GPL-2.0-or-later. Original copyright Automattic Inc.

Acknowledgments


All versions of atproto-php with dependencies

PHP Build Version
Package Version
Requires php Version >=8.2
ext-json Version *
ext-curl Version *
ext-openssl Version *
ext-sodium Version *
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.1 || ^2.0
psr/log Version ^3.0
web-token/jwt-library Version ^4.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package gimucco/atproto-php contains the following files

Loading the files please wait ...