Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new CLI command to assess a FusionAuth instance against key OAuth 2.1 (draft-ietf-oauth-v2-1-15) recommendations, with both human-readable and JSON output modes.
Changes:
- Introduces
check:oauth-2-1command to validate tenant-, instance-, and application-level settings relevant to OAuth 2.1 guidance. - Updates documentation to describe the new command, its options, and what is checked.
- Upgrades
@fusionauth/typescript-clientto support the new checks and updates lockfile accordingly.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/commands/index.ts | Exports the new check:oauth-2-1 command for auto-registration by the CLI. |
| src/commands/check-oauth-2-1.ts | Implements the OAuth 2.1 compliance checking logic and output formatting. |
| package.json | Bumps @fusionauth/typescript-client dependency version/range. |
| package-lock.json | Updates lockfile for new dependency versions and bumps package version. |
| README.md | Documents the new OAuth 2.1 compliance command and its behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (tenantId) { | ||
| tenants = tenants.filter(t => t.id === tenantId); | ||
| if (tenants.length === 0) { | ||
| errorAndExit(`Tenant with ID "${tenantId}" not found.`); | ||
| return; | ||
| } |
There was a problem hiding this comment.
When both --tenant-id and --application-id are provided, the code filters the tenants list but then retrieves and checks the application by ID without validating it belongs to the selected tenant. This can produce a mixed result set (tenant-level checks for one tenant, app-level checks for another). Consider either rejecting the combination as invalid or validating app.tenantId === tenantId and erroring if it doesn’t match.
| - Tenant issuer properly configured — not default "acme.com" | ||
|
|
||
| **WARNINGS (informational, does not cause exit 1):** | ||
| - DPoP (sender-constrained tokens) enabled on applications (§1.4.3) |
There was a problem hiding this comment.
The README states “DPoP … enabled on applications”, but the implementation treats DPoP as an instance-level capability with no per-application toggle (and only checks license/reactor status). Consider rewording this bullet to reflect what the command actually validates (e.g., DPoP availability/Enterprise licensing) to avoid implying an application-level setting exists.
| - DPoP (sender-constrained tokens) enabled on applications (§1.4.3) | |
| - DPoP (sender-constrained tokens) available on the FusionAuth instance / Enterprise-enabled (§1.4.3) |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Tenants | ||
| const tenantResponse = await client.retrieveTenants(); | ||
| if (!tenantResponse.wasSuccessful() || !tenantResponse.response.tenants) { | ||
| errorAndExit('Failed to retrieve tenants.'); | ||
| return; | ||
| } | ||
|
|
||
| let tenants = tenantResponse.response.tenants; | ||
| if (tenantId) { |
There was a problem hiding this comment.
When --application-id is provided without --tenant-id, tenants remains the full tenant list and the tenant-level checks (issuer / refresh token revocation / auth code lifetime) will run against all tenants. This can cause the command to fail due to unrelated tenant settings, even though the user asked to check a single application. Consider narrowing tenants to the application's tenantId when applicationId is set (or skipping tenant-level checks not applicable to the app scope).
|
|
||
| // -- Instance-level checks ------------------------------------------- | ||
|
|
||
| const dpopResult = checkDpop(dpopFeatureActive ?? false); |
There was a problem hiding this comment.
dpopFeatureActive has a tri-state (true/false/unknown) but the check currently coerces undefined to false via dpopFeatureActive ?? false, which reports DPoP as unavailable even when the status couldn't be determined (and JSON output has no way to represent the unknown state). Consider propagating an explicit unknown state into the result/output (e.g., passed: null or a distinct message) instead of treating unknown as unavailable.
| const dpopResult = checkDpop(dpopFeatureActive ?? false); | |
| const dpopResult = checkDpop(dpopFeatureActive); |
| return response.wasSuccessful !== undefined; | ||
| export const isClientResponse = (response: any): response is ClientResponseLike => { | ||
| return response !== null | ||
| && typeof response === 'object' |
There was a problem hiding this comment.
isClientResponse narrows to ClientResponseLike which requires a response property, but the runtime check only verifies wasSuccessful is a function. This makes the type guard unsound (it can return true for objects without response). Consider also checking that a response key exists (and optionally that it's an object) before returning true.
| && typeof response === 'object' | |
| && typeof response === 'object' | |
| && 'response' in response |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…usionauth-node-cli into mooreds/add-oauth-2-1-check
This checks against the OAuth 2.1 recommendations for a given FusionAuth installation.