From 6ddbcaec70a6278b51f8b2071e866775d6c6c74d Mon Sep 17 00:00:00 2001 From: Andy Dixon Date: Thu, 26 Feb 2026 11:11:47 +0000 Subject: [PATCH] docs: add OIDC nonce guidance and callback error handling --- README.md | 8 +++++++- docs/INTEGRATION_GUIDE.md | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6a32b6e..c34c0c9 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,12 @@ $config = Config::fromArray([ $client = new AuthClient($config); // Step 1: redirect user to provider -$auth = $client->buildAuthorisationUrl(); +$auth = $client->buildAuthorisationUrl([ + 'extra' => [ + // Some providers require nonce for OIDC requests. + 'nonce' => rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '='), + ], +]); header('Location: ' . $auth['url']); exit; ``` @@ -123,6 +128,7 @@ This wrapper now delegates to `BlackWall\Auth\AuthClient`. ## Security notes - Always validate OAuth `state` in callback handlers. +- For OIDC providers, include a per-request `nonce` in authorisation requests. - Always use HTTPS in production. - Store refresh tokens securely. - Keep access tokens out of logs and browser-visible output. diff --git a/docs/INTEGRATION_GUIDE.md b/docs/INTEGRATION_GUIDE.md index 1c45994..eff61a5 100644 --- a/docs/INTEGRATION_GUIDE.md +++ b/docs/INTEGRATION_GUIDE.md @@ -25,7 +25,15 @@ $client = new AuthClient(Config::fromArray([ ])); if (!isset($_SESSION['user'])) { - $auth = $client->buildAuthorisationUrl(); + $auth = $client->buildAuthorisationUrl([ + 'extra' => [ + // Some providers require nonce for OIDC requests. + 'nonce' => rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '='), + ], + ]); + // Prevent stale redirects from being reused from cache. + header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); + header('Pragma: no-cache'); header('Location: ' . $auth['url']); exit; } @@ -54,6 +62,12 @@ $client = new AuthClient(Config::fromArray([ 'redirectUri' => 'https://your-app.example/callback.php', ])); +if (isset($_GET['error'])) { + $description = isset($_GET['error_description']) ? (string) $_GET['error_description'] : 'Unknown provider error'; + http_response_code(400); + exit('Authorization failed: ' . $description); +} + $result = $client->handleCallback($_GET); $_SESSION['user'] = [ @@ -122,6 +136,7 @@ try { - Keep provider URLs in environment variables, not hard-coded. - Avoid printing tokens in production pages. - Rotate client secrets for confidential clients. +- Add a unique `nonce` to each OIDC authorisation request. - Validate `state` on every callback request. - Use secure session cookies (`Secure`, `HttpOnly`, `SameSite=Lax` or stricter). - HTTPS URLs are enforced by default in `Config::fromArray()`.