Skip to content
Open
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
4 changes: 4 additions & 0 deletions docs/core/authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ Omit `required_permissions` to preserve pre-FGA behavior — the call returns/va

All admin mutations require the super-admin secret (cookie or `X-Authorizer-Admin-Secret`). They are prefixed with `_authz_` to namespace the authorization API distinctly from other admin operations.

:::tip
Every mutation in this section can also be performed from the admin UI at **`/dashboard`** (Authorization section) — no GraphQL required. The dashboard calls these same `_authz_` mutations under the hood, so the two are interchangeable.
:::

### Step 1 — Define resources and scopes

```graphql
Expand Down
41 changes: 38 additions & 3 deletions docs/sdks/authorizer-go/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,40 @@ if res.IsValid {
}
```

### Step 4: Fine-grained authorization (FGA)

Authorizer supports `resource:scope` based fine-grained permissions. The SDK exposes them in two ways.

**Assert required permissions while validating** -- pass `RequiredPermissions` to `ValidateJWTToken`, `ValidateSession` or `GetSession`. They are evaluated with AND semantics: every entry must be granted, otherwise the result is unauthorized.

```go
res, err := authorizerClient.ValidateJWTToken(&authorizer.ValidateJWTTokenInput{
TokenType: authorizer.TokenTypeAccessToken,
Token: "your-jwt-token",
RequiredPermissions: []*authorizer.PermissionInput{
{Resource: "documents", Scope: "read"},
{Resource: "documents", Scope: "write"},
},
})
if err != nil || !res.IsValid {
// unauthorized
}
```

**Fetch the principal's granted permissions** -- `GetPermissions` returns the `resource:scope` permissions for the authenticated principal. Pass the auth header (or session cookie) so the principal can be identified.

```go
permissions, err := authorizerClient.GetPermissions(map[string]string{
"Authorization": "Bearer your-access-token",
})
if err != nil {
panic(err)
}
for _, p := range permissions {
fmt.Println(p.Resource, p.Scope)
}
```

## Available Methods

The SDK provides the following methods:
Expand All @@ -90,8 +124,9 @@ The SDK provides the following methods:
- `GetProfile` -- Get user profile
- `UpdateProfile` -- Update user profile
- `MagicLinkLogin` -- Login with magic link
- `ValidateJWTToken` -- Validate a JWT token
- `GetSession` -- Get current session
- `ValidateJWTToken` -- Validate a JWT token (optionally with `RequiredPermissions` for FGA)
- `GetSession` -- Get current session (optionally with `RequiredPermissions` for FGA)
- `GetPermissions` -- Get the fine-grained `resource:scope` permissions granted to the authenticated user
- `RevokeToken` -- Revoke a token
- `Logout` -- Logout user
- `ValidateSession` -- Validate a session
- `ValidateSession` -- Validate a session (optionally with `RequiredPermissions` for FGA)
78 changes: 70 additions & 8 deletions docs/sdks/authorizer-js/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ title: Functions
- [signup](#--signup)
- [verifyEmail](#--verifyemail)
- [getProfile](#--getprofile)
- [getPermissions](#--getpermissions)
- [updateProfile](#--updateprofile)
- [forgotPassword](#--forgotpassword)
- [resetPassword](#--resetpassword)
Expand Down Expand Up @@ -291,6 +292,39 @@ const { data, errors } = await authRef.getProfile({
})
```

## - `getPermissions`

Function to fetch the fine-grained authorization (FGA) permissions granted to the authenticated user. This function makes an authorized request, hence if it is used from the browser the HTTP cookie is sent if user has logged in else you need to pass headers object.

It accepts the optional JSON object as parameter, you can pass the HTTP Headers there.

| Key | Description | Required |
| --------------- | -------------------------------------------------------------------------------------- | -------- |
| `Authorization` | Authorization header passed to the server. It needs `Bearer access_token` as its value | true |

It returns an array of permission objects in the response `data`. Each object has the following keys

**Response**

| Key | Description |
| ---------- | ------------------------------------------------------------------- |
| `resource` | The resource the permission applies to, e.g. `documents` |
| `scope` | The action allowed on the resource, e.g. `read`, `write`, `delete` |

**Sample Usage**

```js
// from browser if HTTP cookie is present
const { data, errors } = await authRef.getPermissions()

// from NodeJS / if HTTP cookie is not used
const { data, errors } = await authRef.getPermissions({
Authorization: `Bearer ${token}`,
})

// data => [{ resource: 'documents', scope: 'read' }, ...]
```

## - `updateProfile`

Function to update profile of user. This function makes an authorized request, hence if it is used from the browser the HTTP cookie is sent if user has logged in else you need to pass headers object.
Expand Down Expand Up @@ -473,7 +507,7 @@ const { data, errors } await authRef.getMetadata()

Function to get session information. This function makes an authorized request, hence if it is used from the browser the HTTP cookie is sent if user has logged in else you need to pass headers object.

It accepts the optional JSON object as parameter, you can pass the HTTP Headers there. Optionally you can also validate the roles against the given token by passing the `roles` as second argument to function.
It accepts the optional JSON object as parameter, you can pass the HTTP Headers there. Optionally you can also pass a `SessionQueryRequest` object as the second argument to validate `roles` and `required_permissions` (FGA) against the session — if any required permission is denied, the request returns unauthorized.

| Key | Description | Required |
| --------------- | ------------------------------------------------------------------------------------ | -------- |
Expand Down Expand Up @@ -512,6 +546,16 @@ const { data, errors } = await authRef.getSession(
},
'admin',
)

// with fine-grained authorization (FGA) checks
const { data, errors } = await authRef.getSession(
{
Authorization: `Bearer some_token`,
},
{
required_permissions: [{ resource: 'documents', scope: 'read' }],
},
)
```

## - `revokeToken`
Expand Down Expand Up @@ -578,9 +622,10 @@ It expects the JSON object as parameter with following parameters

| Key | Description | Required |
| ------------ | -------------------------------------------------------------------------------------------------------- | -------- |
| `token_type` | Type of token that needs to be validated. It can be one of `access_token`, `refresh_token` or `id_token` | `true` |
| `token` | Jwt token string | `true` |
| `roles` | Array of roles to validate jwt token for | `false` |
| `token_type` | Type of token that needs to be validated. It can be one of `access_token`, `refresh_token` or `id_token` | `true` |
| `token` | Jwt token string | `true` |
| `roles` | Array of roles to validate jwt token for | `false` |
| `required_permissions` | Array of `{ resource, scope }` permissions (FGA) that must **all** be granted to the principal (AND semantics). If any is denied, `is_valid` is `false` | `false` |

It returns the following keys in response `data` object

Expand All @@ -594,8 +639,18 @@ It returns the following keys in response `data` object

```js
const { data, errors } = await authRef.validateJWTToken({
token_type: `access_token`
token: `some jwt token string`
token_type: `access_token`,
token: `some jwt token string`,
})

// with fine-grained authorization (FGA) checks
const { data, errors } = await authRef.validateJWTToken({
token_type: `access_token`,
token: `some jwt token string`,
required_permissions: [
{ resource: 'documents', scope: 'read' },
{ resource: 'documents', scope: 'write' },
],
})
```

Expand All @@ -607,8 +662,9 @@ It expects the JSON object as parameter with following parameters

| Key | Description | Required |
| -------- | --------------------------------------------------------------------------------------------------- | -------- |
| `cookie` | browser session cookie value. If not present it will need coookie present in header as https cookie | `false` |
| `roles` | Array of roles to validate jwt token for | `false` |
| `cookie` | browser session cookie value. If not present it will need coookie present in header as https cookie | `false` |
| `roles` | Array of roles to validate jwt token for | `false` |
| `required_permissions` | Array of `{ resource, scope }` permissions (FGA) that must **all** be granted to the principal (AND semantics). If any is denied, `is_valid` is `false` | `false` |

It returns the following keys in response `data` object

Expand All @@ -624,6 +680,12 @@ It returns the following keys in response `data` object
const { data, errors } = await authRef.validateSession({
cookie: ``,
})

// with fine-grained authorization (FGA) checks
const { data, errors } = await authRef.validateSession({
cookie: ``,
required_permissions: [{ resource: 'documents', scope: 'read' }],
})
```

## - `verifyOtp`
Expand Down