Skip to content

feat(docs): update JS SDK examples to interceptor auth pattern#270

Merged
marythought merged 14 commits intomainfrom
feat/docs-interceptor-auth-pattern
Apr 7, 2026
Merged

feat(docs): update JS SDK examples to interceptor auth pattern#270
marythought merged 14 commits intomainfrom
feat/docs-interceptor-auth-pattern

Conversation

@marythought
Copy link
Copy Markdown
Contributor

@marythought marythought commented Apr 1, 2026

Summary

Updates all JavaScript/TypeScript code examples across SDK documentation to use the new Connect RPC interceptor-based authentication pattern with built-in token provider factories, replacing the deprecated AuthProvider approach and manual token fetching.

Dependencies: opentdf/web-sdk#899 (interceptor pattern) and opentdf/web-sdk#906 (token provider factories) — both merged to main.

What changed

Auth pattern migration

  • Manual getAccessToken() implementations replaced with clientCredentialsTokenProvider(), refreshTokenProvider(), externalJwtTokenProvider() factory functions
  • AuthProviders.clientSecretAuthProvider() replaced with authTokenInterceptor() + token provider factories as the primary JS auth pattern
  • "Define once, pass everywhere" idiom: create an auth config object once, reuse for OpenTDF, PlatformClient, and standalone functions
  • Removed all await client.ready — no longer needed with interceptors
  • AuthProvider examples preserved in Legacy sections for backwards compatibility

Browser-first messaging

  • Added shared admonition (code_samples/js_auth_note.mdx) across all SDK pages clarifying that clientCredentialsTokenProvider is for learning/server-side only — the JS SDK is designed for browser apps
  • Authentication page tip now leads with browser guidance, pointing to refreshTokenProvider() as the primary JS path
  • Client credentials warning strengthened: "Server-side only — not for browsers"
  • Quickstart frames Node.js as a convenience for learning, not the intended runtime
  • Certificate exchange (mTLS) section updated: browsers handle client certs at the OS level, no SDK config needed

Developer experience improvements

  • Quickstart uses attributeExists() and attributeValueExists() discovery helpers instead of manual list+filter patterns
  • Subject condition set code collapsed from pyramid nesting to [{ style with explanatory comments
  • getMyToken() in Custom Token Source section now has a concrete definition with OIDC library examples
  • DPoP section expanded with Go and Java tabs (was JS-only)
  • CreateTDF and LoadTDF parameter tables split into per-SDK tabs matching actual signatures
  • Troubleshooting "Getting Help" links to all 3 SDK repos
  • Platform client Go example shows service usage with authorization v2

Files modified

New:

  • code_samples/js_auth_note.mdx — shared browser-use admonition partial

Docs (9 files):

  • docs/sdks/authentication.mdx — all 4 auth patterns + DPoP tabs + mTLS fix + legacy in tabs
  • docs/sdks/quickstart/javascript.mdx — browser-first framing, discovery helpers, cleaner code
  • docs/sdks/discovery.mdx — shared admonition replaces old tip
  • docs/sdks/tdf.mdx — per-SDK parameter tables, shared admonition
  • docs/sdks/authorization.mdx — shared admonition
  • docs/sdks/platform-client.mdx — shared admonition, Go service usage example
  • docs/sdks/policy.mdx — shared admonition
  • docs/sdks/troubleshooting.mdx — shared admonition, SDK repo links
  • docs/guides/authentication-guide.mdx — decision guide references to factory functions

Code samples (7 files):

  • All files in code_samples/policy_code/ — inline interceptor + clientCredentialsTokenProvider pattern

Follow-up

Sidebar reordering, example placement, and JS/TS tab naming consistency tracked in #274.

Test plan

  • npm run build passes
  • Surge preview renders admonitions correctly across all pages
  • Code examples are copy-pasteable with correct imports
  • Legacy AuthProvider section still present and accurate

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Updated SDK guides and examples to use a unified interceptor-based authentication approach
    • Added JavaScript-specific auth callouts clarifying client-credentials are server-only and browser apps should use OIDC/refresh-token flows
    • Revised quickstarts, samples, and troubleshooting with explicit token-provider guidance and token lifecycle notes
    • Added legacy deprecation guidance while noting backward compatibility remains intact

Updates all JavaScript/TypeScript code examples to use the new
Connect RPC interceptor-based authentication introduced in
opentdf/web-sdk#899, replacing the deprecated AuthProvider pattern.

Key changes:
- authTokenInterceptor as primary auth mechanism
- "define once, pass everywhere" pattern for shared auth config
- Remove await client.ready (no longer needed with interceptors)
- AuthProvider examples moved to legacy sections
- Standalone functions (listAttributes, etc.) use AuthConfig

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 041468fd-3307-4254-a3bd-4d584bed997a

📥 Commits

Reviewing files that changed from the base of the PR and between 5b19bde and d2afc59.

📒 Files selected for processing (3)
  • docs/guides/authentication-guide.mdx
  • docs/sdks/authentication.mdx
  • docs/sdks/quickstart/javascript.mdx
✅ Files skipped from review due to trivial changes (2)
  • docs/guides/authentication-guide.mdx
  • docs/sdks/quickstart/javascript.mdx
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/sdks/authentication.mdx

📝 Walkthrough

Walkthrough

This pull request migrates JavaScript SDK examples and documentation from a legacy AuthProvider pattern to an interceptor-based authentication model using token providers (e.g., clientCredentialsTokenProvider, refreshTokenProvider) and adds a JS-specific auth callout component used across multiple docs.

Changes

Cohort / File(s) Summary
New JS Auth Callout Component
code_samples/js_auth_note.mdx
Added an MDX callout noting examples use clientCredentialsTokenProvider for simplicity, warning that it requires a client secret and must not be used in browser production; advises OIDC login + refreshTokenProvider() for browser apps.
Policy Code Examples
code_samples/policy_code/create_*.mdx, code_samples/policy_code/list_*.mdx
Replaced authProvider usage with interceptors using authTokenInterceptor(clientCredentialsTokenProvider({...})) across TypeScript examples (namespace, attribute, subject mapping/listing samples).
Authentication & Guides
docs/guides/authentication-guide.mdx, docs/sdks/authentication.mdx
Expanded decision guide and SDK auth reference to name specific token providers, separate browser vs backend flows, add DPoP/interceptor examples, and introduce a legacy AuthProvider deprecation note.
SDK Documentation Updates
docs/sdks/authorization.mdx, docs/sdks/discovery.mdx, docs/sdks/platform-client.mdx, docs/sdks/policy.mdx
Updated JavaScript client setup snippets to use interceptor-based auth (authTokenInterceptor + token providers), removed legacy AuthProvider patterns, and embedded the new JsAuthNote component in multiple pages.
Reference Guides
docs/sdks/tdf.mdx, docs/sdks/troubleshooting.mdx
Updated TDF quick start and troubleshooting JS examples to use interceptor-based auth; refactored parameter tables to per-language tabs and adjusted token expiry/refresh guidance.
Quickstart Documentation
docs/sdks/quickstart/javascript.mdx
Switched quickstart to clientCredentialsTokenProvider() + authTokenInterceptor() (with a "Local development only" note), refactored attribute/policy setup to use helper functions (attributeExists, attributeValueExists), and removed AuthProviders.

Sequence Diagram(s)

sequenceDiagram
    participant App as Browser/Server App
    participant SDK as JS SDK (Interceptor)
    participant OIDC as OIDC Token Server
    participant Platform as Platform API

    App->>SDK: Make API request
    SDK->>OIDC: Request access token (via TokenProvider)
    OIDC-->>SDK: Return access token
    SDK->>Platform: Forward request with Authorization: Bearer <token>
    Platform-->>SDK: Respond (200/..)
    SDK-->>App: Return response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • elizabethhealy
  • pflynn-virtru

Poem

🐰 I hopped from AuthProvider to a shiny new hook,
Interceptors and tokens — now that’s the new look!
Client secrets for dev, OIDC for the web,
Refresh and renew, no secrets misfed.
A carrot for docs — happy hopping ahead!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately describes the main change: updating JavaScript SDK documentation examples to use the interceptor-based authentication pattern instead of the deprecated AuthProvider approach.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/docs-interceptor-auth-pattern

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the JavaScript SDK documentation to replace the deprecated AuthProvider interface with a new interceptor-based authentication model. Changes include updating code samples across multiple files to use authTokenInterceptor, introducing authTokenDPoPInterceptor, and adding a SortDirection enum to the policy OpenAPI specification. Reviewer feedback focuses on improving the provided getAccessToken examples by recommending the use of URLSearchParams for more robust request body encoding and emphasizing the need for token caching in production environments to prevent performance issues.

Comment thread docs/sdks/authentication.mdx Outdated
Comment thread docs/sdks/platform-client.mdx Outdated
Comment thread docs/sdks/quickstart/javascript.mdx Outdated
Comment thread docs/sdks/quickstart/javascript.mdx Outdated
Comment thread docs/sdks/tdf.mdx Outdated
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

📄 Preview deployed to https://opentdf-docs-pr-270.surge.sh

Comment thread code_samples/policy_code/create_attribute.mdx Outdated
eugenioenko
eugenioenko previously approved these changes Apr 1, 2026
Copy link
Copy Markdown
Contributor

@eugenioenko eugenioenko left a comment

Choose a reason for hiding this comment

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

Changes look great!

Left a small inline comment, which gemini has something among the same line we can look into later

- Use URLSearchParams instead of raw string body in all getAccessToken
- Add caching note to token provider functions
- Use ...auth spread pattern in platform-client.mdx
- Add getAccessToken definition to platform-client.mdx
- Add setup tip to discovery.mdx and comment to authorization.mdx
  explaining getAccessToken comes from /sdks/authentication

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
marythought and others added 4 commits April 1, 2026 10:21
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace `...auth` spread (undefined in snippet context) with explicit
`interceptors: [authTokenInterceptor(() => myAuth.getAccessToken())]`
in all policy code samples and policy.mdx JS blocks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace manual getAccessToken() implementations with the new
clientCredentialsTokenProvider, refreshTokenProvider, and
externalJwtTokenProvider factory functions from web-sdk#906.

These handle caching, auto-refresh, and concurrent request
deduplication out of the box — no more hand-rolled OAuth fetch code
in every example.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Mary Dickson <mary.dickson@virtru.com>
Copy link
Copy Markdown
Contributor

@eugenioenko eugenioenko left a comment

Choose a reason for hiding this comment

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

interceptors: [authTokenInterceptor(clientCredentialsTokenProvider({
    clientId: 'opentdf', clientSecret: 'secret',
    oidcOrigin: 'http://localhost:8080/auth/realms/opentdf',
  }))],

The nice thing about this example is that it's self-contained. Thats powerful.
Copy/past and it works. 10 of out 10 honestly.

The one thing that raises a small concern for me is that it's a private client credentials flow. We're adding multiple examples of it, but this goes against the nature of Web SDK being for the Browser.

I'm torn a little, one on side, this is self-contained, on the other side it gives an example of how to use WebSDK in the wrong environment or the wrong way. We probably would need to add comments to all examples // don't use this in production/browser and that would defeat the purpose of self-contained example

A compromise. Can we define that only once (instead of on each example) and have something like this on the funciton

The examples below use clientCredentialsTokenProvider for brevity. This requires a client secret and is intended for server-side use only. In browser applications, replace with your OIDC library's token

marythought and others added 5 commits April 6, 2026 10:33
… examples

The JS SDK is designed for browser apps, but all examples use
clientCredentialsTokenProvider (which requires a client secret).
Add a shared admonition across SDK doc pages clarifying this is
for learning only and production browser apps should use
refreshTokenProvider() with an OIDC login flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reframe the Node.js project setup as a convenience for the quickstart,
not the intended runtime. The SDK targets browser apps (React, Angular,
Vue, etc.).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Quickstart: frame Node.js as convenience, SDK is browser-first
- Quickstart: use attributeExists/attributeValueExists discovery helpers
- Quickstart: collapse nested subject condition set arrays
- Authentication: define getMyToken(), add Go/Java DPoP tabs, fix mTLS
- Platform client: show Go service usage, use authorization v2
- TDF: per-SDK parameter tables instead of ambiguous shared table
- Troubleshooting: link to all 3 SDK repos for filing issues

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same treatment as CreateTDF — each SDK gets its own parameter table
matching its actual signature instead of a vague shared table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread docs/guides/authentication-guide.mdx Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
docs/sdks/authentication.mdx (1)

70-70: Use authTokenInterceptor() for custom token providers instead of a raw interceptor.

The documentation at line 70 correctly states that custom () => Promise<string> functions work, but the example at lines 256-279 unnecessarily drops to a raw @connectrpc/connect interceptor with manual header mutation. Since authTokenInterceptor(getMyToken) is already the pattern used elsewhere in this file (and throughout the SDK documentation), use it here to keep the auth surface consistent and avoid requiring consumers to import the transport layer directly.

♻️ Proposed doc update
-import { type Interceptor } from '@connectrpc/connect';
-import { OpenTDF } from '@opentdf/sdk';
+import { authTokenInterceptor, OpenTDF } from '@opentdf/sdk';
@@
-const myAuthInterceptor: Interceptor = (next) => async (req) => {
-    req.header.set('Authorization', `Bearer ${await getMyToken()}`);
-    return next(req);
-};
-
 const client = new OpenTDF({
-    interceptors: [myAuthInterceptor],
+    interceptors: [authTokenInterceptor(getMyToken)],
     platformUrl: 'http://localhost:8080',
 });

Also applies to: 256-279

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/sdks/authentication.mdx` at line 70, Replace the raw `@connectrpc/connect`
header-mutating interceptor example with the standardized authTokenInterceptor
usage: show a TokenProvider function signature () => Promise<string> (e.g.,
getMyToken) and pass it to authTokenInterceptor(getMyToken) instead of manually
creating an interceptor; update imports to remove the transport-level
interceptor import and import authTokenInterceptor from the SDK, and ensure the
example demonstrates attaching authTokenInterceptor to the client/transport the
same way other docs do.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/sdks/authentication.mdx`:
- Around line 63-65: Update the DPoP JavaScript example to stop using
clientCredentialsTokenProvider() (which exposes client secrets in browser
contexts) and instead pass refreshTokenProvider({ clientId, refreshToken,
oidcOrigin }) as the tokenProvider to authTokenDPoPInterceptor(); locate the
example that currently constructs authTokenDPoPInterceptor(..., tokenProvider:
clientCredentialsTokenProvider(...)) and replace the tokenProvider invocation
with refreshTokenProvider(...) ensuring the same
clientId/refreshToken/oidcOrigin values are used and add a short comment noting
that if the IdP requires DPoP-bound access tokens a DPoP-capable token-exchange
provider is required instead of the standard refreshTokenProvider.

In `@docs/sdks/quickstart/javascript.mdx`:
- Around line 245-255: The snippet has scope and undefined identifier bugs: move
the attribute lookup out of the inner block so its declaration is available when
calling platform.v1.attributes.createAttributeValue (e.g., call
platform.v1.attributes.listAttributes() and assign attribute before the if that
uses marketingFqn/attributeValueExists), and replace the undefined targetValue
with the literal string 'marketing' in the createAttributeValue call; also guard
that attribute and attribute.id are present before calling createAttributeValue
to avoid null/undefined usage.

In `@docs/sdks/troubleshooting.mdx`:
- Around line 45-56: Add a server-side warning and browser-safe example next to
the existing clientCredentialsTokenProvider snippet: after the
authTokenInterceptor/clientCredentialsTokenProvider/OpenTDF example, insert a
warning block stating that clientCredentialsTokenProvider is server-side only
and must not expose client secrets, mirroring the Authentication doc wording;
then add a second example using refreshTokenProvider with
authTokenInterceptor/OpenTDF for browser apps (noting the refresh token comes
from the OIDC login flow). Also remove the broken <JsAuthNote /> reference (or
restore its file) so the safety note renders correctly.

---

Nitpick comments:
In `@docs/sdks/authentication.mdx`:
- Line 70: Replace the raw `@connectrpc/connect` header-mutating interceptor
example with the standardized authTokenInterceptor usage: show a TokenProvider
function signature () => Promise<string> (e.g., getMyToken) and pass it to
authTokenInterceptor(getMyToken) instead of manually creating an interceptor;
update imports to remove the transport-level interceptor import and import
authTokenInterceptor from the SDK, and ensure the example demonstrates attaching
authTokenInterceptor to the client/transport the same way other docs do.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2b0f4008-f6b4-4da2-921d-ba92f34cd255

📥 Commits

Reviewing files that changed from the base of the PR and between 45920a4 and 5b19bde.

📒 Files selected for processing (17)
  • code_samples/js_auth_note.mdx
  • code_samples/policy_code/create_attribute.mdx
  • code_samples/policy_code/create_namespace.mdx
  • code_samples/policy_code/create_subject_condition_set.mdx
  • code_samples/policy_code/create_subject_mapping.mdx
  • code_samples/policy_code/list_attributes.mdx
  • code_samples/policy_code/list_namespaces.mdx
  • code_samples/policy_code/list_subject_mapping.mdx
  • docs/guides/authentication-guide.mdx
  • docs/sdks/authentication.mdx
  • docs/sdks/authorization.mdx
  • docs/sdks/discovery.mdx
  • docs/sdks/platform-client.mdx
  • docs/sdks/policy.mdx
  • docs/sdks/quickstart/javascript.mdx
  • docs/sdks/tdf.mdx
  • docs/sdks/troubleshooting.mdx

Comment thread docs/sdks/authentication.mdx
Comment thread docs/sdks/quickstart/javascript.mdx
Comment thread docs/sdks/troubleshooting.mdx
Comment thread docs/sdks/authentication.mdx Outdated
Comment thread docs/sdks/authentication.mdx
Copy link
Copy Markdown
Contributor

@eugenioenko eugenioenko left a comment

Choose a reason for hiding this comment

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

The browser docs lean towards refresh token authentication, but there are cases where auth token might not be available because of security reasons and only access token would be available to the consumer which is enough to make requests to the platform.

Updating the docs to include both as options would help clarify that situation.

- Add Access Token section to authentication.mdx for apps that only have
  an access token (no refresh token available)
- Update intro tip and auth decision guide to present access token as a
  valid browser option alongside refresh token
- Fix DPoP JS example to use generic token provider instead of
  clientCredentialsTokenProvider
- Fix quickstart scoping bug: move attribute lookup outside if block so
  it's available for subject mapping section
- Fix undefined targetValue reference in quickstart

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@marythought
Copy link
Copy Markdown
Contributor Author

marythought commented Apr 6, 2026

The browser docs lean towards refresh token authentication, but there are cases where auth token might not be available because of security reasons and only access token would be available to the consumer which is enough to make requests to the platform.

Updating the docs to include both as options would help clarify that situation.

Addressed in d2afc59 — added a dedicated Access Token section for apps that only have an access token. Updated the intro tip, auth guide scenario matrix, and OIDC Login Flow section to present both access token and refresh token as valid browser options.

@marythought marythought requested a review from eugenioenko April 6, 2026 21:29
Copy link
Copy Markdown
Contributor

@eugenioenko eugenioenko left a comment

Choose a reason for hiding this comment

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

🔥

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants