2 Commits
Author SHA1 Message Date
Andy Dixon 986dc95646 Updated to enforce nonce in example and documentaion 2026-03-10 09:50:34 +00:00
Andy Dixon 6b67bf574d typo 2026-02-26 13:40:48 +00:00
5 changed files with 22 additions and 13 deletions
+4 -2
View File
@@ -40,7 +40,7 @@ In the consuming application's `composer.json`:
}
],
"require": {
"dixon/blackwall-auth-sdk": "*"
"andydixon/blackwall-auth-sdk": "*"
}
}
```
@@ -79,7 +79,7 @@ $client = new AuthClient($config);
// Step 1: redirect user to provider
$auth = $client->buildAuthorisationUrl([
'extra' => [
// Some providers require nonce for OIDC requests.
// Include nonce in the authorisation request for OIDC.
'nonce' => rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '='),
],
]);
@@ -87,6 +87,8 @@ header('Location: ' . $auth['url']);
exit;
```
The generated authorisation request URL will include `nonce=...` alongside `state`, `scope`, and the PKCE parameters.
For callback handling, see `docs/INTEGRATION_GUIDE.md`.
For provider-side threat/invariant assumptions, see `docs/SECURITY_MODEL.md`.
+11 -9
View File
@@ -27,7 +27,7 @@ $client = new AuthClient(Config::fromArray([
if (!isset($_SESSION['user'])) {
$auth = $client->buildAuthorisationUrl([
'extra' => [
// Some providers require nonce for OIDC requests.
// Include nonce in the authorisation request for OIDC.
'nonce' => rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '='),
],
]);
@@ -41,6 +41,8 @@ if (!isset($_SESSION['user'])) {
echo 'Already signed in.';
```
The resulting redirect request includes `nonce=...` in the provider authorisation URL, together with `state`, `code_challenge`, and the rest of the OAuth/OIDC query parameters.
## 2. Handle callback
```php
@@ -69,7 +71,7 @@ if (isset($_GET['error'])) {
// revoked, privilege changed, or user denied consent between request and submit).
// invalid_scope usually means the app requested scopes not enabled on the provider client.
http_response_code(in_array($error, ['access_denied', 'invalid_scope'], true) ? 403 : 400);
exit('Authorization failed: ' . $description);
exit('Authorisation failed: ' . $description);
}
$result = $client->handleCallback($_GET);
@@ -140,11 +142,11 @@ try {
Token introspection can return `active=false` when the token subject (user/project) or client has since been disabled.
Provider JWT access tokens are now revocation-aware at `userinfo`; revoked JWTs can fail before natural expiry.
Refresh-token exchange can return `invalid_grant` when provider client scope policy has been tightened and stored refresh scopes are no longer allowed.
Provider login/authorization steps can also fail with `access_denied` when account status is disabled before completion.
Provider login/authorisation steps can also fail with `access_denied` when account status is disabled before completion.
WebAuthn-based login verification can return credential-style failures for disabled accounts even when authenticator assertions are otherwise valid.
Existing authenticated sessions may also be invalidated when account status changes to disabled.
OAuth authorization consent submission can return `access_denied` if the account becomes inactive between session establishment and consent completion.
OAuth authorization can also return `invalid_scope` if requested scopes are not explicitly allowed on the provider client configuration.
OAuth authorisation consent submission can return `access_denied` if the account becomes inactive between session establishment and consent completion.
OAuth authorisation can also return `invalid_scope` if requested scopes are not explicitly allowed on the provider client configuration.
Provider user/project assignment views may exclude disabled projects even if historical assignments exist.
## Operational guidance
@@ -156,13 +158,13 @@ Provider user/project assignment views may exclude disabled projects even if his
- For token exchange and refresh, apply bounded retry/backoff on transient provider failures instead of immediate repeated retries.
- Use exactly one client authentication method per token/control request (do not send both HTTP Basic and `client_secret` form fields together).
- If you call provider WebAuthn login challenge/verify endpoints directly, use `POST` only.
- Treat admin enrollment URL export as a state-changing operation: call it with `POST` and include a valid CSRF token.
- Treat admin enrolment URL export as a state-changing operation: call it with `POST` and include a valid CSRF token.
- Treat provider CSV exports as untrusted input in spreadsheet tools; prefer importing into systems that neutralise formula cells.
- Treat enrollment URLs as sensitive bearer material: do not place them in redirect query parameters, logs, or analytics tags; keep them in one-time server-side flash/session state.
- Treat enrolment URLs as sensitive bearer material: do not place them in redirect query parameters, logs, or analytics tags; keep them in one-time server-side flash/session state.
- If your deployment runs behind reverse proxies, ensure trusted-proxy configuration is strict so spoofed forwarding headers cannot bypass IP-based abuse controls.
- Trusted proxy allowlists may be expressed as explicit IPs or CIDR ranges; avoid broad ranges and keep proxy chains minimal.
- For approval-driven admin mutations, assume provider-side execution is serialized per approval item; client retries should still be idempotent and bounded.
- This serialization applies across approval actions (approve/reject/cancel), so clients should avoid parallel decision submissions for the same request ID.
- For approval-driven admin mutations, assume provider-side execution is serialised per approval item; client retries should still be idempotent and bounded.
- This serialisation applies across approval actions (approve/reject/cancel), so clients should avoid parallel decision submissions for the same request ID.
- For provider CSV-based user import operations, enforce strict file-size and row-count limits in automation tooling and surface clear operator errors on limit breaches.
- Configure OAuth client redirect URIs as HTTPS in production; reserve HTTP for localhost loopback testing only.
- Assume provider rate limits are enforced per source identity (for example IP) and shared across related auth endpoints.
+1
View File
@@ -26,6 +26,7 @@ $user = $client->getUserInfo($tokens->accessToken);
## Key differences
- Method spelling uses British English in the new API: `buildAuthorisationUrl()`.
- The legacy method name `getAuthorizationUrl()` is unchanged for backwards compatibility.
- Token responses are strongly typed via `TokenSet`.
- Errors are represented by specific exception classes.
- HTTP transport is swappable via `HttpClientInterface`.
+1 -1
View File
@@ -23,5 +23,5 @@ This document summarises provider-side security guarantees that SDK integrators
- Keep requested scopes minimal and aligned to the provider client configuration.
- Treat `access_denied`, `invalid_scope`, and `invalid_grant` as expected security outcomes, not transport errors.
- Build retries only for transient failures; do not blindly retry authz/authn denials.
- Keep enrollment URLs/tokens and OAuth tokens out of URLs, logs, and analytics tags.
- Keep enrolment URLs/tokens and OAuth tokens out of URLs, logs, and analytics tags.
- Use strict HTTPS and secure session-cookie handling in the relying party app.
+5 -1
View File
@@ -39,7 +39,11 @@ if (isset($_GET['logout'])) {
}
if (!isset($_SESSION['user'])) {
$authData = $auth->getAuthorizationUrl();
$authData = $auth->getAuthorizationUrl([
'extra' => [
'nonce' => rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '='),
],
]);
header('Location: ' . $authData['url']);
exit;
}