Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions code_samples/js_auth_note.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
:::info JavaScript examples use client credentials for simplicity
The JavaScript SDK is designed for **browser applications**. The examples on this page use `clientCredentialsTokenProvider` because it's self-contained and easy to follow, but it requires a client secret and **must not be used in browser code**.

In production browser apps, complete an OIDC login flow to obtain a refresh token, then use [`refreshTokenProvider()`](/sdks/authentication#refresh-token). See the [Authentication Decision Guide](/guides/authentication-guide) for help choosing the right method.
:::
6 changes: 5 additions & 1 deletion code_samples/policy_code/create_attribute.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,15 @@ import CreateAttributeExample from '@site/code_samples/java/create-attribute.mdx
<TabItem value="js" label="TypeScript">

```typescript
import { authTokenInterceptor, clientCredentialsTokenProvider } from '@opentdf/sdk';
import { PlatformClient } from '@opentdf/sdk/platform';
import { AttributeRuleTypeEnum } from '@opentdf/sdk/platform/policy/objects_pb.js';

const platform = new PlatformClient({
authProvider,
interceptors: [authTokenInterceptor(clientCredentialsTokenProvider({
clientId: 'opentdf', clientSecret: 'secret',
oidcOrigin: 'http://localhost:8080/auth/realms/opentdf',
}))],
platformUrl: 'http://localhost:8080',
});

Expand Down
6 changes: 5 additions & 1 deletion code_samples/policy_code/create_namespace.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,14 @@ import CreateNamespaceExample from '@site/code_samples/java/create-namespace.mdx
<TabItem value="js" label="TypeScript">

```typescript
import { authTokenInterceptor, clientCredentialsTokenProvider } from '@opentdf/sdk';
import { PlatformClient } from '@opentdf/sdk/platform';

const platform = new PlatformClient({
authProvider,
interceptors: [authTokenInterceptor(clientCredentialsTokenProvider({
clientId: 'opentdf', clientSecret: 'secret',
oidcOrigin: 'http://localhost:8080/auth/realms/opentdf',
}))],
platformUrl: 'http://localhost:8080',
});

Expand Down
6 changes: 5 additions & 1 deletion code_samples/policy_code/create_subject_condition_set.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import CreateSubjectConditionSetExample from '@site/code_samples/java/create-sub

```typescript
import { create } from '@bufbuild/protobuf';
import { authTokenInterceptor, clientCredentialsTokenProvider } from '@opentdf/sdk';
import { PlatformClient } from '@opentdf/sdk/platform';
import {
ConditionBooleanTypeEnum,
Expand All @@ -86,7 +87,10 @@ import {
} from '@opentdf/sdk/platform/policy/subjectmapping/subject_mapping_pb.js';

const platform = new PlatformClient({
authProvider,
interceptors: [authTokenInterceptor(clientCredentialsTokenProvider({
clientId: 'opentdf', clientSecret: 'secret',
oidcOrigin: 'http://localhost:8080/auth/realms/opentdf',
}))],
platformUrl: 'http://localhost:8080',
});

Expand Down
6 changes: 5 additions & 1 deletion code_samples/policy_code/create_subject_mapping.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,14 @@ import CreateSubjectMappingExample from '@site/code_samples/java/create-subject-
<TabItem value="js" label="TypeScript">

```typescript
import { authTokenInterceptor, clientCredentialsTokenProvider } from '@opentdf/sdk';
import { PlatformClient } from '@opentdf/sdk/platform';

const platform = new PlatformClient({
authProvider,
interceptors: [authTokenInterceptor(clientCredentialsTokenProvider({
clientId: 'opentdf', clientSecret: 'secret',
oidcOrigin: 'http://localhost:8080/auth/realms/opentdf',
}))],
platformUrl: 'http://localhost:8080',
});

Expand Down
6 changes: 5 additions & 1 deletion code_samples/policy_code/list_attributes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,14 @@ import ListAttributesExample from '@site/code_samples/java/list-attributes.mdx';
<TabItem value="js" label="TypeScript">

```typescript
import { authTokenInterceptor, clientCredentialsTokenProvider } from '@opentdf/sdk';
import { PlatformClient } from '@opentdf/sdk/platform';

const platform = new PlatformClient({
authProvider,
interceptors: [authTokenInterceptor(clientCredentialsTokenProvider({
clientId: 'opentdf', clientSecret: 'secret',
oidcOrigin: 'http://localhost:8080/auth/realms/opentdf',
}))],
platformUrl: 'http://localhost:8080',
});

Expand Down
6 changes: 5 additions & 1 deletion code_samples/policy_code/list_namespaces.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ import ListNamespacesExample from '@site/code_samples/java/list-namespaces.mdx';
<TabItem value="js" label="TypeScript">

```typescript
import { authTokenInterceptor, clientCredentialsTokenProvider } from '@opentdf/sdk';
import { PlatformClient } from '@opentdf/sdk/platform';

const platform = new PlatformClient({
authProvider,
interceptors: [authTokenInterceptor(clientCredentialsTokenProvider({
clientId: 'opentdf', clientSecret: 'secret',
oidcOrigin: 'http://localhost:8080/auth/realms/opentdf',
}))],
platformUrl: 'http://localhost:8080',
});

Expand Down
6 changes: 5 additions & 1 deletion code_samples/policy_code/list_subject_mapping.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,14 @@ import ListSubjectMappingsExample from '@site/code_samples/java/list-subject-map
<TabItem value="js" label="TypeScript">

```typescript
import { authTokenInterceptor, clientCredentialsTokenProvider } from '@opentdf/sdk';
import { PlatformClient } from '@opentdf/sdk/platform';

const platform = new PlatformClient({
authProvider,
interceptors: [authTokenInterceptor(clientCredentialsTokenProvider({
clientId: 'opentdf', clientSecret: 'secret',
oidcOrigin: 'http://localhost:8080/auth/realms/opentdf',
}))],
platformUrl: 'http://localhost:8080',
});

Expand Down
18 changes: 10 additions & 8 deletions docs/guides/authentication-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ flowchart TD

| Scenario | Recommended Method | Notes |
|----------|-------------------|-------|
| Backend service / microservice | [Client Credentials](/sdks/authentication#client-credentials) | Most straightforward. SDK auto-refreshes tokens on expiry. |
| Web application (browser) | [OIDC Login Flow](/sdks/authentication#refresh-token) | JS SDK only. Your app completes an OIDC login to get an access token and optional refresh token. Never expose client secrets in browser code. |
| Backend service / microservice | [Client Credentials](/sdks/authentication#client-credentials) | Most straightforward. Use `clientCredentialsTokenProvider()` — it caches tokens and auto-refreshes on expiry. |
| Web application (browser) with refresh token | [Refresh Token](/sdks/authentication#refresh-token) | JS SDK only. Use `refreshTokenProvider()` with a refresh token from your OIDC login flow. Handles automatic renewal. |
| Web application (browser) with access token only | [Access Token](/sdks/authentication#access-token) | JS SDK only. Use `authTokenInterceptor()` with a function that returns your access token. Use when your IdP doesn't issue refresh tokens. |
| CLI tool (interactive user) | `otdfctl auth login` | Opens a browser for OIDC login. See [CLI auth docs](/components/cli/auth/login). |
| CI/CD pipeline / automated job | [Client Credentials](/sdks/authentication#client-credentials) | Use a dedicated service account. Rotate secrets regularly. |
| Federated identity / SAML | [Token Exchange](/sdks/authentication#token-exchange) | Exchange an existing token for one the platform accepts. |
Expand All @@ -73,19 +74,20 @@ flowchart TD

### Client Credentials (Backend Services)

The simplest path. Register a client in your IdP, then pass the client ID and secret to the SDK. The SDK handles token acquisition and refresh automatically.
The simplest path. Register a client in your IdP, then use `clientCredentialsTokenProvider()` (JS) or pass the client ID and secret directly (Go/Java). The SDK handles token acquisition, caching, and refresh automatically.

**What you need:** A client ID and client secret from your IdP.

See [SDK code examples](/sdks/authentication#client-credentials) for Go, Java, and JavaScript.

### OIDC Login Flow (Browser Apps)

For browser-based applications, your app completes an [OIDC Authorization Code flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth) to obtain an access token and (optionally) a refresh token from the IdP. The IdP returns both tokens after a successful `/token` call with a valid authorization code — though the refresh token is only issued if the IdP is configured to provide one. You then pass the refresh token to the JS SDK, which uses it to maintain a valid access token.
For browser-based applications, your app completes an [OIDC Authorization Code flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth) to obtain an access token and (optionally) a refresh token from the IdP.

**What you need:** An access token and optional refresh token from a completed OIDC login flow.
- **If you have a refresh token**, use [`refreshTokenProvider()`](/sdks/authentication#refresh-token) — it handles token exchange and automatic renewal.
- **If you only have an access token** (because your IdP doesn't issue refresh tokens or the grant is disabled for security reasons), use [`authTokenInterceptor()`](/sdks/authentication#access-token) with a function that returns your token.

See [SDK code examples](/sdks/authentication#refresh-token) (JavaScript only).
See SDK code examples: [Refresh Token](/sdks/authentication#refresh-token) | [Access Token](/sdks/authentication#access-token) (JavaScript only).

### Token Exchange (Federated Identity)

Expand Down Expand Up @@ -165,9 +167,9 @@ OpenTDF does not prescribe a specific deployment strategy. This checklist covers

### "My token expired and I'm getting errors"

- **Client credentials:** The SDK refreshes automatically — if you're seeing expiry errors, check that your IdP is reachable.
- **Client credentials:** The built-in `clientCredentialsTokenProvider()` (JS) and Go/Java SDKs refresh automatically — if you're seeing expiry errors, check that your IdP is reachable.
- **OAuth token source (Go):** `WithOAuthAccessTokenSource` does not auto-refresh. Your `TokenSource` implementation must handle refresh.
- **Refresh token (JS):** Ensure the refresh token itself hasn't expired. Long-lived refresh tokens can be configured in your IdP.
- **Refresh token (JS):** `refreshTokenProvider()` handles rotation automatically, but ensure the initial refresh token itself hasn't expired. Long-lived refresh tokens can be configured in your IdP.

### "DPoP-related errors"

Expand Down
Loading
Loading