Skip to content
184 changes: 83 additions & 101 deletions docs/sdks/authorization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ const platformClient = new PlatformClient({

Every authorization call requires an `EntityIdentifier` — the entity (user, service, etc.) you're asking about. The entity can be identified by email, username, client ID, JWT token, claims, or registered resource FQN.

**Go** — use the v2 helper functions:
<Tabs>
<TabItem value="go" label="Go">

| Helper | Description |
|--------|-------------|
Expand All @@ -88,7 +89,27 @@ req := &authorizationv2.GetDecisionRequest{
}
```

**Java** — build the nested proto structure:
</TabItem>
<TabItem value="java" label="Java">

| Helper | Description |
|--------|-------------|
| `EntityIdentifiers.forEmail(email)` | Identify by email address |
| `EntityIdentifiers.forClientId(clientId)` | Identify by client ID (service account / NPE) |
| `EntityIdentifiers.forUserName(username)` | Identify by username |
| `EntityIdentifiers.forToken(jwt)` | Resolve entity from a JWT token |

```java
import io.opentdf.platform.sdk.EntityIdentifiers;

GetDecisionRequest request = GetDecisionRequest.newBuilder()
.setEntityIdentifier(EntityIdentifiers.forEmail("alice@example.com"))
// ...
.build();
```

<details>
<summary>Without helpers (manual proto construction)</summary>

```java
EntityIdentifier.newBuilder()
Expand All @@ -103,7 +124,30 @@ EntityIdentifier.newBuilder()
.build()
```

**JavaScript** — use the `identifier` oneof:
</details>

</TabItem>
<TabItem value="js" label="JavaScript">

| Helper | Description |
|--------|-------------|
| `EntityIdentifiers.forEmail(email)` | Identify by email address |
| `EntityIdentifiers.forClientId(clientId)` | Identify by client ID (service account / NPE) |
| `EntityIdentifiers.forUserName(username)` | Identify by username |
| `EntityIdentifiers.forToken(jwt)` | Resolve entity from a JWT token |
| `EntityIdentifiers.withRequestToken()` | Derive entity from the request's Authorization header |

```typescript
import { EntityIdentifiers } from '@opentdf/sdk';

const response = await platformClient.v2.authorization.getDecision({
entityIdentifier: EntityIdentifiers.forEmail('alice@example.com'),
// ...
});
```

<details>
<summary>Without helpers (manual object construction)</summary>

```typescript
{
Expand All @@ -126,16 +170,22 @@ EntityIdentifier.newBuilder()
}
```

</details>

</TabItem>
</Tabs>

**Supported entity types:**

| Type | Go helper | Java setter | JS `case` |
|------|-----------|-------------|-----------|
| Email | `ForEmail(email)` | `.setEmailAddress(email)` | `'emailAddress'` |
| Client ID | `ForClientID(id)` | `.setClientId(id)` | `'clientId'` |
| Username | `ForUserName(name)` | `.setUserName(name)` | `'userName'` |
| JWT Token | `ForToken(jwt)` | `.setToken(Token.newBuilder().setJwt(jwt))` | `'token'` |
| Claims | — | `.setClaims(claims)` | `'claims'` |
| Registered Resource | — | `.setRegisteredResourceValueFqn(fqn)` | `'registeredResourceValueFqn'` |
| Type | Go | Java | JavaScript |
Comment thread
marythought marked this conversation as resolved.
|------|-----|------|------------|
| Email | `ForEmail(email)` | `EntityIdentifiers.forEmail(email)` | `EntityIdentifiers.forEmail(email)` |
| Client ID | `ForClientID(id)` | `EntityIdentifiers.forClientId(id)` | `EntityIdentifiers.forClientId(id)` |
| Username | `ForUserName(name)` | `EntityIdentifiers.forUserName(name)` | `EntityIdentifiers.forUserName(name)` |
| JWT Token | `ForToken(jwt)` | `EntityIdentifiers.forToken(jwt)` | `EntityIdentifiers.forToken(jwt)` |
| Request Token | `WithRequestToken()` | — | `EntityIdentifiers.withRequestToken()` |
| Claims | — | manual proto construction | manual object construction |
| Registered Resource | — | manual proto construction | manual object construction |

- **Claims** are used by the Entity Resolution Service (ERS) for custom claim-based entity resolution.
- **Registered Resource** identifies an entity by a [registered resource](/components/policy/registered_resources) value FQN stored in platform policy, where the resource acts as a single entity for authorization decisions.
Expand Down Expand Up @@ -176,7 +226,7 @@ await platformClient.v2.authorization.getEntitlements({ ... })

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `entityIdentifier` | `EntityIdentifier` | Yes | The entity to query. In Go, use helpers like `authorizationv2.ForEmail("user@example.com")`. |
| `entityIdentifier` | `EntityIdentifier` | Yes | The entity to query. Use [helpers](#entityidentifier) like `ForEmail(...)` (Go) or `EntityIdentifiers.forEmail(...)` (Java/JS). |
| `withComprehensiveHierarchy` | `bool` | No | When true, returns all entitled values for attributes with hierarchy rules, propagating down from the entitled value. |

**Example**
Expand Down Expand Up @@ -279,18 +329,10 @@ for _, dr := range decisionResponse.GetDecisionResponses() {
<TabItem value="java" label="Java">

```java
import io.opentdf.platform.sdk.EntityIdentifiers;

GetEntitlementsRequest request = GetEntitlementsRequest.newBuilder()
.setEntityIdentifier(
EntityIdentifier.newBuilder()
.setEntityChain(
EntityChain.newBuilder()
.addEntities(
Entity.newBuilder()
.setId("user-bob")
.setEmailAddress("bob@OrgA.com")
)
)
)
.setEntityIdentifier(EntityIdentifiers.forEmail("bob@OrgA.com"))
.build();

GetEntitlementsResponse resp = sdk.getServices()
Expand All @@ -308,23 +350,10 @@ for (EntityEntitlements entitlement : resp.getEntitlementsList()) {
<TabItem value="js" label="JavaScript">

```typescript
import { EntityIdentifiers } from '@opentdf/sdk';

const response = await platformClient.v2.authorization.getEntitlements({
entityIdentifier: {
identifier: {
case: 'entityChain',
value: {
entities: [
{
ephemeralId: 'user-bob',
entityType: {
case: 'emailAddress',
value: 'bob@OrgA.com',
},
},
],
},
},
},
entityIdentifier: EntityIdentifiers.forEmail('bob@OrgA.com'),
});

for (const entitlement of response.entitlements) {
Expand All @@ -335,20 +364,10 @@ for (const entitlement of response.entitlements) {
To expand hierarchy rules:

```typescript
import { EntityIdentifiers } from '@opentdf/sdk';

const response = await platformClient.v2.authorization.getEntitlements({
entityIdentifier: {
identifier: {
case: 'entityChain',
value: {
entities: [
{
ephemeralId: 'user-123',
entityType: { case: 'emailAddress', value: 'user@company.com' },
},
],
},
},
},
entityIdentifier: EntityIdentifiers.forEmail('user@company.com'),
withComprehensiveHierarchy: true,
});

Expand Down Expand Up @@ -398,7 +417,7 @@ await platformClient.v2.authorization.getDecision({ ... })

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `entityIdentifier` | `EntityIdentifier` | Yes | The entity requesting access. In Go, use helpers like `authorizationv2.ForEmail(...)` or `authorizationv2.ForToken(jwt)`. |
| `entityIdentifier` | `EntityIdentifier` | Yes | The entity requesting access. Use [helpers](#entityidentifier) like `ForEmail(...)` (Go) or `EntityIdentifiers.forEmail(...)` (Java/JS). |
| `action` | `Action` | Yes | The action being performed (e.g., `decrypt`, `read`). |
| `resource` | `Resource` | Yes | The resource being accessed, identified by attribute value FQNs. |

Expand Down Expand Up @@ -534,18 +553,10 @@ for _, dr := range decisionResponse.GetDecisionResponses() {
<TabItem value="java" label="Java">

```java
import io.opentdf.platform.sdk.EntityIdentifiers;

GetDecisionRequest request = GetDecisionRequest.newBuilder()
.setEntityIdentifier(
EntityIdentifier.newBuilder()
.setEntityChain(
EntityChain.newBuilder()
.addEntities(
Entity.newBuilder()
.setId("user-123")
.setEmailAddress("user@company.com")
)
)
)
.setEntityIdentifier(EntityIdentifiers.forEmail("user@company.com"))
.setAction(
Action.newBuilder()
.setName("decrypt")
Expand Down Expand Up @@ -580,22 +591,11 @@ if (decision.getDecision() == Decision.DECISION_PERMIT) {
<TabItem value="js" label="JavaScript">

```typescript
import { EntityIdentifiers } from '@opentdf/sdk';
import { Decision } from '@opentdf/sdk/platform/authorization/v2/authorization_pb.js';

const response = await platformClient.v2.authorization.getDecision({
entityIdentifier: {
identifier: {
case: 'entityChain',
value: {
entities: [
{
ephemeralId: 'user-123',
entityType: { case: 'emailAddress', value: 'user@company.com' },
},
],
},
},
},
entityIdentifier: EntityIdentifiers.forEmail('user@company.com'),
action: { name: 'decrypt' },
resource: {
resource: {
Expand Down Expand Up @@ -778,20 +778,12 @@ for _, dr := range decisionResponse.GetDecisionResponses() {
<TabItem value="java" label="Java">

```java
import io.opentdf.platform.sdk.EntityIdentifiers;

GetDecisionBulkRequest request = GetDecisionBulkRequest.newBuilder()
.addDecisionRequests(
GetDecisionMultiResourceRequest.newBuilder()
.setEntityIdentifier(
EntityIdentifier.newBuilder()
.setEntityChain(
EntityChain.newBuilder()
.addEntities(
Entity.newBuilder()
.setId("user-123")
.setEmailAddress("user@company.com")
)
)
)
.setEntityIdentifier(EntityIdentifiers.forEmail("user@company.com"))
.setAction(Action.newBuilder().setName("decrypt"))
.addResources(
Resource.newBuilder()
Expand Down Expand Up @@ -841,22 +833,12 @@ import GetDecisionsExample from '@site/code_samples/java/get-decisions.mdx';
<TabItem value="js" label="JavaScript">

```typescript
import { EntityIdentifiers } from '@opentdf/sdk';

const response = await platformClient.v2.authorization.getDecisionBulk({
decisionRequests: [
{
entityIdentifier: {
identifier: {
case: 'entityChain',
value: {
entities: [
{
ephemeralId: 'user-123',
entityType: { case: 'emailAddress', value: 'user@company.com' },
},
],
},
},
},
entityIdentifier: EntityIdentifiers.forEmail('user@company.com'),
action: { name: 'decrypt' },
resources: [
{
Expand Down
29 changes: 10 additions & 19 deletions docs/sdks/discovery.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -582,42 +582,33 @@ Entity.newBuilder().setId("e1").setUuid("550e8400-e29b-41d4-a716-446655440000").
<TabItem value="js" label="JavaScript">

```typescript
import { EntityIdentifiers } from '@opentdf/sdk';
import { PlatformClient } from '@opentdf/sdk/platform';

const platform = new PlatformClient({ ...auth, platformUrl });

const resp = await platform.v2.authorization.getEntitlements({
entityIdentifier: {
identifier: {
case: 'entityChain',
value: {
ephemeralId: 'e1',
entities: [
{
ephemeralId: 'e1',
entityType: { case: 'emailAddress', value: 'alice@example.com' },
},
],
},
},
},
entityIdentifier: EntityIdentifiers.forEmail('alice@example.com'),
});

if (resp.entitlements.length > 0) {
console.log("alice's entitlements:", resp.entitlements[0].actionsPerAttributeValueFqn);
}
```

Other supported entity types (placed inside the `entities` array):
Other supported [entity identifier helpers](/sdks/authorization#entityidentifier):

```typescript
// By username
{ ephemeralId: 'e1', entityType: { case: 'userName', value: 'alice' } }
import { EntityIdentifiers } from '@opentdf/sdk';

// By client ID (NPE / service account)
{ ephemeralId: 'e1', entityType: { case: 'clientId', value: 'my-service' } }
EntityIdentifiers.forUserName('alice') // By username
EntityIdentifiers.forClientId('my-service') // By client ID (NPE / service account)
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

:::note
The JavaScript SDK does not currently provide a `forUuid` helper. To use UUID-based entity identifiers, construct the `EntityIdentifier` manually using the protobuf message types from `@opentdf/sdk/platform`.
:::

</TabItem>
</Tabs>

Expand Down
Loading