Skip to content
Merged
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
55 changes: 55 additions & 0 deletions docs/guides/authentication/custom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
description: Integrating with a custom authentication system.
sidebar_position: 100
sidebar_label: Custom Authentication
---
Comment on lines +1 to +5
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Sidebar position should be adjusted to maintain documentation order

The high sidebar_position: 100 appears to be inconsistent with the sequence of other authentication guides which use values 1-6. Since this is a custom authentication guide, it should be positioned appropriately within the sequence, likely after the specific auth provider guides.

  • Consider adjusting sidebar_position to 7 to maintain a logical sequence after auth0 (6) and other specific providers
  • Current sequence: next-auth (1), clerk (2), supabase (3), lucia (5), auth0 (6), custom (100)
🔗 Analysis chain

Verify the sidebar position value

The sidebar_position: 100 seems unusually high. Please confirm if this is intentional or if it should be adjusted to match the sequence of other authentication guides.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check other authentication guide positions
fd -e md . docs/guides/authentication -x grep -l "sidebar_position" {} \; | xargs grep "sidebar_position"

Length of output: 452


# Integrating With a Custom Authentication System

You may be using an authentication provider that's not mentioned in the guides. Or you may have a custom-implemented one. Integrating ZenStack with any authentication system is pretty straightforward. This guide will provide the general steps to follow.

## Determining what's needed for access control

The bridge that connects authentication and authorization is the `auth()` function that represents the authenticated current user. Based on your requirements, you should determine what fields are needed from it. The `auth()` object must at least contain an id field that uniquely identifies the current user. If you do RBAC, you'll very likely need an `auth().role` field available. Or even an `auth().permissions` field for fine-grained control.

The `auth()` call needs to be resolved to a "type" in ZModel. If you store user data in your database, you may already have a "User" model that carries all the fields you need to access.

```zmodel
model User {
id String @id
role String
permissions String[]
...
}
```

ZenStack picks up the model named "User" automatically to resolve `auth()` unless another model or type is specifically appointed (by using the `@@auth` attribute). For example, if you're not storing user data locally, you can define a "type" to resolve `auth()`. This way, you can provide typing without being backed by a database table.

```zmodel
type Auth {
id String @id
role String
permissions String[]
@@auth
}
```

Just remember that any thing that you access from `auth().` must be resolved.

## Fetching the current user along with the additional information

At runtime in your backend code, you need to provide a value for the `auth()` call to ZenStack, so it can use it to evaluate access policies. How this is done is solely dependent on your authentication mechanism. Here are some examples:

1. If you use JWT tokens, you can issue tokens with user id and other fields embedded, then validate and extract them from the request.
2. If you use a dedicated authentication service, you can call it to get the current user's information.

You must ensure that whatever approach you use, the user information you get can be trusted and free of tampering.

## Creating an enhanced PrismaClient

Finally, you can call the `enhance` API to create an enhanced PrismaClient with the user information and enjoy automatically enforced access policies.

```ts
const user = await getCurrentUser(); // your implementation
const db = enhance(prisma, { user });
```