Skip to content

feat(oidc-client): add RAR support [SDKS-5435] - #871

Open
ancheetah wants to merge 1 commit into
mainfrom
SDKS-5435-rar
Open

ancheetah wants to merge 1 commit into
mainfrom
SDKS-5435-rar

Conversation

@ancheetah

@ancheetah ancheetah commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

JIRA Ticket

https://pingidentity.atlassian.net/browse/SDKS-5435

Description

Adds support for RAR in Ping AM. See oidc-client README. While there are new RAR test pages in the e2e app, no test suites were added since this will require manual testing due to the Remote Consent Service needing to be run through a tunnel.

@changeset-bot

changeset-bot Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1e808ba

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@forgerock/oidc-client Minor
@forgerock/sdk-oidc Minor
@forgerock/sdk-types Minor
@forgerock/davinci-client Minor
@forgerock/journey-client Minor
@forgerock/device-client Minor
@forgerock/sdk-utilities Minor
@forgerock/sdk-logger Minor
@forgerock/storage Minor
@forgerock/protect Minor
@forgerock/recognize Minor
@forgerock/iframe-manager Minor
@forgerock/sdk-request-middleware Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 661665fc-8a27-49df-b2b1-81aa0b49a665
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@nx-cloud

nx-cloud Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 1e808ba

Command Status Duration Result
nx affected -t build lint test typecheck e2e-ci ❌ Failed 2m 52s View ↗

💡 Dealing with memory or CPU issues? See memory and CPU details with the resource usage add-on ↗.


☁️ Nx Cloud last updated this comment at 2026-11-11 18:30:16 UTC

@pkg-pr-new

pkg-pr-new Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@forgerock/davinci-client

pnpm add https://pkg.pr.new/@forgerock/davinci-client@871

@forgerock/device-client

pnpm add https://pkg.pr.new/@forgerock/device-client@871

@forgerock/journey-client

pnpm add https://pkg.pr.new/@forgerock/journey-client@871

@forgerock/oidc-client

pnpm add https://pkg.pr.new/@forgerock/oidc-client@871

@forgerock/protect

pnpm add https://pkg.pr.new/@forgerock/protect@871

@forgerock/recognize

pnpm add https://pkg.pr.new/@forgerock/recognize@871

@forgerock/sdk-types

pnpm add https://pkg.pr.new/@forgerock/sdk-types@871

@forgerock/sdk-utilities

pnpm add https://pkg.pr.new/@forgerock/sdk-utilities@871

@forgerock/iframe-manager

pnpm add https://pkg.pr.new/@forgerock/iframe-manager@871

@forgerock/sdk-logger

pnpm add https://pkg.pr.new/@forgerock/sdk-logger@871

@forgerock/sdk-oidc

pnpm add https://pkg.pr.new/@forgerock/sdk-oidc@871

@forgerock/sdk-request-middleware

pnpm add https://pkg.pr.new/@forgerock/sdk-request-middleware@871

@forgerock/storage

pnpm add https://pkg.pr.new/@forgerock/storage@871

commit: 4c1f1a1

@codecov-commenter

codecov-commenter commented Nov 5, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.29%. Comparing base (eafe277) to head (4c1f1a1).
⚠️ Report is 180 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main     #871       +/-   ##
===========================================
+ Coverage   18.07%   96.29%   +78.22%     
===========================================
  Files         155        1      -154     
  Lines       24398       81    -24317     
  Branches     1203       17     -1186     
===========================================
- Hits         4410       78     -4332     
+ Misses      19988        3    -19985     

see 155 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Deployed 8dc8ce1 to https://ForgeRock.github.io/ping-javascript-sdk/pr-871/8dc8ce1f02c8183461df9a88599249e0ae3bbdbc branch gh-pages in ForgeRock/ping-javascript-sdk

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Interface Mapping Out of Date

The interface_mapping.md document is out of sync with the SDK exports.

Drift report
Extracting legacy SDK exports...
  Found 79 legacy exports
Extracting new SDK exports...
  Found 432 new SDK exports
Parsing interface_mapping.md...
  Found 143 documented mappings

Interface Mapping Drift Report
══════════════════════════════

Missing Callbacks (1)
  ✗ Callback "PingOneRecognizeCallback" from ./types is not documented in Callback Type Mapping

Undocumented New Exports (163)
  ⚠ New SDK export "makeJourneyConfig" from . is not referenced in the documentation
  ⚠ New SDK export "JourneyClient" from . is not referenced in the documentation
  ⚠ New SDK export "LogLevel" from . is not referenced in the documentation
  ⚠ New SDK export "CustomLogger" from . is not referenced in the documentation
  ⚠ New SDK export "RequestMiddleware" from . is not referenced in the documentation
  ⚠ New SDK export "ActionTypes" from . is not referenced in the documentation
  ⚠ New SDK export "GenericError" from . is not referenced in the documentation
  ⚠ New SDK export "WellknownResponse" from . is not referenced in the documentation
  ⚠ New SDK export "FailedPolicyRequirement" from . is not referenced in the documentation
  ⚠ New SDK export "PolicyParams" from . is not referenced in the documentation
  ⚠ New SDK export "isValidWellknownUrl" from . is not referenced in the documentation
  ⚠ New SDK export "createWellknownError" from . is not referenced in the documentation
  ⚠ New SDK export "DeviceProfileData" from . is not referenced in the documentation
  ⚠ New SDK export "Geolocation" from . is not referenced in the documentation
  ⚠ New SDK export "JourneyResult" from . is not referenced in the documentation
  ⚠ New SDK export "ResolvedServerConfig" from . is not referenced in the documentation
  ⚠ New SDK export "JourneyServerConfig" from . is not referenced in the documentation
  ⚠ New SDK export "JourneyClientConfig" from . is not referenced in the documentation
  ⚠ New SDK export "LegacyServerConfig" from . is not referenced in the documentation
  ⚠ New SDK export "InternalJourneyClientConfig" from . is not referenced in the documentation
  ⚠ New SDK export "StartParam" from . is not referenced in the documentation
  ⚠ New SDK export "ResumeOptions" from . is not referenced in the documentation
  ⚠ New SDK export "NextOptions" from . is not referenced in the documentation
  ⚠ New SDK export "CallbackFactory" from . is not referenced in the documentation
  ⚠ New SDK export "PingOneRecognizeOperationType" from . is not referenced in the documentation
  ⚠ New SDK export "PingOneRecognizeCallback" from . is not referenced in the documentation
  ⚠ New SDK export "CollectParameters" from ./device is not referenced in the documentation
  ⚠ New SDK export "DeviceProfileData" from ./device is not referenced in the documentation
  ⚠ New SDK export "Geolocation" from ./device is not referenced in the documentation
  ⚠ New SDK export "ProfileConfigOptions" from ./device is not referenced in the documentation
  ⚠ New SDK export "FailedPolicyRequirement" from ./policy is not referenced in the documentation
  ⚠ New SDK export "QRCodeData" from ./qr-code is not referenced in the documentation
  ⚠ New SDK export "LogLevel" from ./types is not referenced in the documentation
  ⚠ New SDK export "CustomLogger" from ./types is not referenced in the documentation
  ⚠ New SDK export "RequestMiddleware" from ./types is not referenced in the documentation
  ⚠ New SDK export "ActionTypes" from ./types is not referenced in the documentation
  ⚠ New SDK export "GenericError" from ./types is not referenced in the documentation
  ⚠ New SDK export "WellknownResponse" from ./types is not referenced in the documentation
  ⚠ New SDK export "FailedPolicyRequirement" from ./types is not referenced in the documentation
  ⚠ New SDK export "PolicyParams" from ./types is not referenced in the documentation
  ⚠ New SDK export "isValidWellknownUrl" from ./types is not referenced in the documentation
  ⚠ New SDK export "createWellknownError" from ./types is not referenced in the documentation
  ⚠ New SDK export "DeviceProfileData" from ./types is not referenced in the documentation
  ⚠ New SDK export "Geolocation" from ./types is not referenced in the documentation
  ⚠ New SDK export "JourneyResult" from ./types is not referenced in the documentation
  ⚠ New SDK export "ResolvedServerConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "JourneyClient" from ./types is not referenced in the documentation
  ⚠ New SDK export "JourneyServerConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "JourneyClientConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "LegacyServerConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "InternalJourneyClientConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "StartParam" from ./types is not referenced in the documentation
  ⚠ New SDK export "ResumeOptions" from ./types is not referenced in the documentation
  ⚠ New SDK export "NextOptions" from ./types is not referenced in the documentation
  ⚠ New SDK export "CallbackFactory" from ./types is not referenced in the documentation
  ⚠ New SDK export "PingOneRecognizeOperationType" from ./types is not referenced in the documentation
  ⚠ New SDK export "PingOneRecognizeCallback" from ./types is not referenced in the documentation
  ⚠ New SDK export "OutcomeWithName" from ./webauthn is not referenced in the documentation
  ⚠ New SDK export "AttestationType" from ./webauthn is not referenced in the documentation
  ⚠ New SDK export "UserVerificationType" from ./webauthn is not referenced in the documentation
  ⚠ New SDK export "makeOidcConfig" from . is not referenced in the documentation
  ⚠ New SDK export "PushAuthorizationResponse" from . is not referenced in the documentation
  ⚠ New SDK export "AuthorizationDetail" from . is not referenced in the documentation
  ⚠ New SDK export "CustomStorageObject" from . is not referenced in the documentation
  ⚠ New SDK export "GenericError" from . is not referenced in the documentation
  ⚠ New SDK export "WellknownResponse" from . is not referenced in the documentation
  ⚠ New SDK export "ActionTypes" from . is not referenced in the documentation
  ⚠ New SDK export "RequestMiddleware" from . is not referenced in the documentation
  ⚠ New SDK export "CustomLogger" from . is not referenced in the documentation
  ⚠ New SDK export "LogLevel" from . is not referenced in the documentation
  ⚠ New SDK export "BrowserStorageConfig" from . is not referenced in the documentation
  ⚠ New SDK export "CustomStorageConfig" from . is not referenced in the documentation
  ⚠ New SDK export "StorageConfig" from . is not referenced in the documentation
  ⚠ New SDK export "createClientStore" from . is not referenced in the documentation
  ⚠ New SDK export "OidcClient" from . is not referenced in the documentation
  ⚠ New SDK export "ClientStore" from . is not referenced in the documentation
  ⚠ New SDK export "RootState" from . is not referenced in the documentation
  ⚠ New SDK export "AppDispatch" from . is not referenced in the documentation
  ⚠ New SDK export "RevokeSuccessResult" from . is not referenced in the documentation
  ⚠ New SDK export "RevokeErrorResult" from . is not referenced in the documentation
  ⚠ New SDK export "LogoutSuccessResult" from . is not referenced in the documentation
  ⚠ New SDK export "LogoutErrorResult" from . is not referenced in the documentation
  ⚠ New SDK export "UserInfoResponse" from . is not referenced in the documentation
  ⚠ New SDK export "OidcConfig" from . is not referenced in the documentation
  ⚠ New SDK export "BuildAuthorizationData" from . is not referenced in the documentation
  ⚠ New SDK export "OptionalAuthorizeOptions" from . is not referenced in the documentation
  ⚠ New SDK export "AuthorizeErrorResponse" from . is not referenced in the documentation
  ⚠ New SDK export "AuthorizeSuccessResponse" from . is not referenced in the documentation
  ⚠ New SDK export "AuthorizationSuccess" from . is not referenced in the documentation
  ⚠ New SDK export "AuthorizationError" from . is not referenced in the documentation
  ⚠ New SDK export "TokenExchangeResponse" from . is not referenced in the documentation
  ⚠ New SDK export "TokenExchangeErrorResponse" from . is not referenced in the documentation
  ⚠ New SDK export "TokenRequestOptions" from . is not referenced in the documentation
  ⚠ New SDK export "SessionCheckResponseType" from . is not referenced in the documentation
  ⚠ New SDK export "SessionCheckOptions" from . is not referenced in the documentation
  ⚠ New SDK export "SessionCheckSuccess" from . is not referenced in the documentation
  ⚠ New SDK export "PushAuthorizationResponse" from ./types is not referenced in the documentation
  ⚠ New SDK export "AuthorizationDetail" from ./types is not referenced in the documentation
  ⚠ New SDK export "CustomStorageObject" from ./types is not referenced in the documentation
  ⚠ New SDK export "GenericError" from ./types is not referenced in the documentation
  ⚠ New SDK export "WellknownResponse" from ./types is not referenced in the documentation
  ⚠ New SDK export "ActionTypes" from ./types is not referenced in the documentation
  ⚠ New SDK export "RequestMiddleware" from ./types is not referenced in the documentation
  ⚠ New SDK export "CustomLogger" from ./types is not referenced in the documentation
  ⚠ New SDK export "LogLevel" from ./types is not referenced in the documentation
  ⚠ New SDK export "BrowserStorageConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "CustomStorageConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "StorageConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "createClientStore" from ./types is not referenced in the documentation
  ⚠ New SDK export "OidcClient" from ./types is not referenced in the documentation
  ⚠ New SDK export "ClientStore" from ./types is not referenced in the documentation
  ⚠ New SDK export "RootState" from ./types is not referenced in the documentation
  ⚠ New SDK export "AppDispatch" from ./types is not referenced in the documentation
  ⚠ New SDK export "RevokeSuccessResult" from ./types is not referenced in the documentation
  ⚠ New SDK export "RevokeErrorResult" from ./types is not referenced in the documentation
  ⚠ New SDK export "LogoutSuccessResult" from ./types is not referenced in the documentation
  ⚠ New SDK export "LogoutErrorResult" from ./types is not referenced in the documentation
  ⚠ New SDK export "UserInfoResponse" from ./types is not referenced in the documentation
  ⚠ New SDK export "OidcConfig" from ./types is not referenced in the documentation
  ⚠ New SDK export "BuildAuthorizationData" from ./types is not referenced in the documentation
  ⚠ New SDK export "OptionalAuthorizeOptions" from ./types is not referenced in the documentation
  ⚠ New SDK export "AuthorizeErrorResponse" from ./types is not referenced in the documentation
  ⚠ New SDK export "AuthorizeSuccessResponse" from ./types is not referenced in the documentation
  ⚠ New SDK export "AuthorizationSuccess" from ./types is not referenced in the documentation
  ⚠ New SDK export "AuthorizationError" from ./types is not referenced in the documentation
  ⚠ New SDK export "TokenExchangeResponse" from ./types is not referenced in the documentation
  ⚠ New SDK export "TokenExchangeErrorResponse" from ./types is not referenced in the documentation
  ⚠ New SDK export "TokenRequestOptions" from ./types is not referenced in the documentation
  ⚠ New SDK export "SessionCheckResponseType" from ./types is not referenced in the documentation
  ⚠ New SDK export "SessionCheckOptions" from ./types is not referenced in the documentation
  ⚠ New SDK export "SessionCheckSuccess" from ./types is not referenced in the documentation
  ⚠ New SDK export "DeviceClient" from . is not referenced in the documentation
  ⚠ New SDK export "OathDevice" from . is not referenced in the documentation
  ⚠ New SDK export "DeleteOathQuery" from . is not referenced in the documentation
  ⚠ New SDK export "RetrieveOathQuery" from . is not referenced in the documentation
  ⚠ New SDK export "OathResponse" from . is not referenced in the documentation
  ⚠ New SDK export "DeletedOathDevice" from . is not referenced in the documentation
  ⚠ New SDK export "WebAuthnQuery" from . is not referenced in the documentation
  ⚠ New SDK export "WebAuthnBody" from . is not referenced in the documentation
  ⚠ New SDK export "WebAuthnDevice" from . is not referenced in the documentation
  ⚠ New SDK export "UpdatedWebAuthnDevice" from . is not referenced in the documentation
  ⚠ New SDK export "WebAuthnCredential" from . is not referenced in the documentation
  ⚠ New SDK export "GetProfileDevices" from . is not referenced in the documentation
  ⚠ New SDK export "ProfileDevicesQuery" from . is not referenced in the documentation
  ⚠ New SDK export "ProfileDevice" from . is not referenced in the documentation
  ⚠ New SDK export "PushDeviceQuery" from . is not referenced in the documentation
  ⚠ New SDK export "PushDeviceBody" from . is not referenced in the documentation
  ⚠ New SDK export "DeleteDeviceQuery" from . is not referenced in the documentation
  ⚠ New SDK export "DeviceInfoResponse" from . is not referenced in the documentation
  ⚠ New SDK export "DeviceInfo" from . is not referenced in the documentation
  ⚠ New SDK export "PushDevice" from . is not referenced in the documentation
  ⚠ New SDK export "DeletedPushDevice" from . is not referenced in the documentation
  ⚠ New SDK export "GetBoundDevicesQuery" from . is not referenced in the documentation
  ⚠ New SDK export "BoundDeviceQuery" from . is not referenced in the documentation
  ⚠ New SDK export "DeviceResponse" from . is not referenced in the documentation
  ⚠ New SDK export "DeviceMetadata" from . is not referenced in the documentation
  ⚠ New SDK export "Hardware" from . is not referenced in the documentation
  ⚠ New SDK export "Browser" from . is not referenced in the documentation
  ⚠ New SDK export "Bluetooth" from . is not referenced in the documentation
  ⚠ New SDK export "Network" from . is not referenced in the documentation
  ⚠ New SDK export "Telephony" from . is not referenced in the documentation
  ⚠ New SDK export "Metadata" from . is not referenced in the documentation
  ⚠ New SDK export "DeviceProfile" from . is not referenced in the documentation

Summary: 1 error, 163 warnings

To fix, run:

pnpm mapping:generate

Then commit the updated interface_mapping.md.

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

📦 Bundle Size Analysis

📦 Bundle Size Analysis

🚨 Significant Changes

🔺 @forgerock/sdk-oidc - 6.1 KB (+0.3 KB, +5.7%)
🔻 @forgerock/journey-client - 0.0 KB (-95.4 KB, -100.0%)
🔻 @forgerock/device-client - 0.0 KB (-10.3 KB, -100.0%)

📊 Minor Changes

📈 @forgerock/oidc-client - 36.1 KB (+0.2 KB)
📈 @forgerock/sdk-types - 9.5 KB (+0.4 KB)

➖ No Changes

➖ @forgerock/protect - 149.5 KB
➖ @forgerock/sdk-utilities - 18.8 KB
➖ @forgerock/recognize - 5605.5 KB
➖ @forgerock/iframe-manager - 3.2 KB
➖ @forgerock/storage - 1.5 KB
➖ @forgerock/sdk-logger - 1.6 KB
➖ @forgerock/sdk-request-middleware - 4.6 KB
➖ @forgerock/journey-client - 95.4 KB
➖ @forgerock/davinci-client - 59.7 KB
➖ @forgerock/device-client - 10.3 KB


15 packages analyzed • Baseline from latest main build

Legend

🆕 New package
🔺 Size increased
🔻 Size decreased
➖ No change

ℹ️ How bundle sizes are calculated
  • Current Size: Total gzipped size of all files in the package's dist directory
  • Baseline: Comparison against the latest build from the main branch
  • Files included: All build outputs except source maps and TypeScript build cache
  • Exclusions: .map, .tsbuildinfo, and .d.ts.map files

🔄 Updated automatically on each push to this PR

@vatsalparikh vatsalparikh left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add authorization_details to TokenExchangeResponse and OauthTokens as mentioned in the acceptance criteria, so we can support both requested resource (we already support request side) and the response received back from AM (this is what I am talking about)

"A token response containing authorization_details decodes onto the public token object and survives the localStorage round-trip."

@ancheetah

Copy link
Copy Markdown
Collaborator Author

I think we should add authorization_details to TokenExchangeResponse and OauthTokens as mentioned in the acceptance criteria, so we can support both requested resource (we already support request side) and the response received back from AM (this is what I am talking about)

"A token response containing authorization_details decodes onto the public token object and survives the localStorage round-trip."

Good catch. AM returns the auth details both encoded in the token and explicitly stated in the response. Native mimics this so I’ll align with them.

@vatsalparikh vatsalparikh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just one comment on type.

* not modeled below can be added to the catch-all `additionalFields` parameter,
* whose entries are flattened onto the object before sending the request.
*/
export interface AuthorizationDetail {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are defining a new type AuthorizationDetail here. Just a suggestion, I think we should re-export from packages/oidc-client/src/types.ts so the sdk consumers can use this type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ancheetah — really nice work on this! The request-side mechanics line up closely with the iOS implementation of RAR (SDKS-5423): single-send authorization_details, PAR body flow, per-call-over-config precedence, and modeled-wins-over-additionalFields all match, and the new unit tests cover those paths well. I also verified the changeset: the minor bump is correct — the api-report churn is an indent reformat with no exports removed.

Just two inline comments, both about hardening what's already there rather than changing the approach.

* is flattened onto the detail; entries in `additionalFields` that shadow a
* modeled property are overridden by the modeled entry.
*/
export function serializeRarAuthDetails(authDetails: AuthorizationDetail[]): string {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the flattening semantics here — modeled property wins over additionalFields, exactly matching iOS.

One parity gap worth closing: iOS validates authorizationDetails at client creation (throws on a missing/non-string type, non-object entries, malformed arrays), while this path is compile-time-only. Since the package ships to plain-JS consumers too, two rough edges get through at runtime:

  • authorizationDetails: 'x' passes the ?.length guard and then crashes with authDetails.map is not a function inside this function
  • [{ foo: 1 }] serializes happily and goes on the wire without the type member that RFC 9396 §2 requires — the AS will reject it, or worse, partially honor it

Would you consider a small runtime guard at the top of serializeRarAuthDetails? Something like:

authDetails.forEach((detail, index) => {
  if (typeof detail !== 'object' || detail === null || Array.isArray(detail)) {
    throw new TypeError(`authorizationDetails[${index}] must be an object`);
  }
  if (typeof detail.type !== 'string' || detail.type.length === 0) {
    throw new TypeError(`authorizationDetails[${index}].type is required (RFC 9396 §2)`);
  }
});

That would also let us add the malformed-input test cases iOS covers in OidcClientConfigTests. Happy to discuss the error shape if you'd prefer the SDK's own error types over TypeError.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JS SDK doesn't typically validate the config options. To me this would be more like user error and we would rely on the AS to error. However, it is valid that map can crash if the auth details are not an array. So I can harden the conditional to check for arrays in buildAuthorizeParams before serializing.

...(data.refresh_token && { refreshToken: data.refresh_token }),
...(data.expires_in && { expiresAt: data.expires_in }),
...(data.expires_in && { expiryTimestamp: Date.now() + data.expires_in * 1000 }),
...(data.authorization_details && { authorizationDetails: data.authorization_details }),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mapping is exactly what AC 1 of SDKS-5435 calls for — nice. One ask: it currently has no test coverage (no references to authorization_details in the test files yet), and this is arguably the most security-relevant line of the PR: per RFC 9396 §7 the AS echoes the granted authorization_details in the token response, and §9 is why clients need to carry them to the resource server.

iOS locks this down from three directions (testAuthorizationDetailsSurvivesEncodingDecoding for decode + storage round-trip, plus refresh-token and device-flow tests). A minimal equivalent here would be one client.store.test.ts case built on a mocked, pre-fetched token response:

it('token.exchange maps authorization_details from the token response onto stored tokens', async () => {
  const state = 'NzUyNDUyMDAxOTMyNDUxNzI1NjkxNDc2MjEyMzUwMjQzMzQyMjE4OQ';
  const grantedDetails = [
    {
      type: 'payment_initiation',
      locations: ['https://example.com/payments'],
      action: ['initiate'],
      instructedAmount: { amount: '250.00', currency: 'USD' },
    },
  ];

  server.use(
    http.post('*/as/token', async () =>
      HttpResponse.json({
        access_token: 'abcdefghijklmnop',
        id_token: '0987654321',
        authorization_details: grantedDetails,
      }),
    ),
  );

  const oidcClient = await oidc({ config, storage: customStorageConfig });
  if ('error' in oidcClient) throw new Error('Error creating OIDC Client');

  await oidcClient.authorize.url(); // seeds state/verifier via the file's sessionStorage stub

  const tokens = await oidcClient.token.exchange('abc123', state);
  if ('error' in tokens || !('authorizationDetails' in tokens)) expect.fail();
  expect(tokens.authorizationDetails).toStrictEqual(grantedDetails);

  // Round-trip: the persisted tokens carry the granted details (AC 1)
  const stored = await oidcClient.token.get();
  if ('error' in stored || !('authorizationDetails' in stored)) expect.fail();
  expect(stored.authorizationDetails).toStrictEqual(grantedDetails);
});

This reuses the file's existing msw server and sessionStorage stub (which has a known state), so it should drop in with minimal fuss — adjust fixtures as you see fit. One case here closes the whole AC.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

@ryanbas21 ryanbas21 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a generic question. I see us setting the AuthorizationDetails at the config level. Is there any desire for a customer to want to set this at a request level? Like, couldn't different requests need to set different authorize actions?

In the README.md we have an example of:

 authorizationDetails: [
    {
      type: 'payment_initiation',
      actions: ['initiate', 'status'],
      locations: ['https://example.com/payments'],
      instructedAmount: { currency: 'EUR', amount: '123.50' },
      creditorName: 'Merchant A',
    },
  ],

Is it the standard pattern to define what the Authorization Server can accept up front in the config, then per request you can send what actions for example, are needed for that? What if a customer wants more fine grained control of that? Not sure if what i'm asking is actually useful though, just thinking it out loud so to speak

@ancheetah

Copy link
Copy Markdown
Collaborator Author

I have a generic question. I see us setting the AuthorizationDetails at the config level. Is there any desire for a customer to want to set this at a request level? Like, couldn't different requests need to set different authorize actions?

@ryanbas21 yes it is overridable at the request level as well. Take a look at GetAuthorizationUrlOptions.


const urlParams = new URLSearchParams(window.location.search);
const wellknown = urlParams.get('wellknown');
const AM_BASE = 'https://openam-sdks.forgeblocks.com/am';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any consequences to hardcoding the AM URL here? Does it reduce configurability of running tests in CI?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The oidc-app is not set up like some of our other apps where there are server-config objects that make for easy configuration. Each test path is tied to a hardcoded configuration which is often necessary to complete the e2e redirect-based token exchange flow. After the user is redirected back to the application, it is redirected without any query params. Therefore we cannot set things like clientId, authorizationDetails, par, wellknown, etc through query params because they will be dropped after redirect and token exchange will fail with a different configuration than what initiated the OAuth flow.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ancheetah

ancheetah commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator Author

Added e2e tests for RAR that can be run manually. They are currently ignored in the Playwright config.

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud has identified a possible root cause for your failed CI:

We looked at the failing davinci-suites form-image e2e test and found nothing in our changes that explains it. Our PR adds RAR support to oidc-client and OIDC e2e pages, and does not touch the DaVinci client, app or this test. The form likely failed to render because of the external PingOne DaVinci flow or its configuration, so we are not proposing a code change.

No code changes were suggested for this issue.

Trigger a rerun:

Rerun CI

Nx Cloud View detailed reasoning on Nx Cloud ↗


🎓 Learn more about Self-Healing CI on nx.dev

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

6 participants