-
-
Notifications
You must be signed in to change notification settings - Fork 42
doc: migrate more auth guide to v3 #511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
versioned_docs/version-3.x/recipe/auth-integration/clerk.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| --- | ||
| description: Integrating with Clerk. | ||
| sidebar_position: 2 | ||
| sidebar_label: Clerk | ||
| --- | ||
|
|
||
| # Clerk Integration | ||
|
|
||
| [Clerk](https://clerk.com/) is a comprehensive authentication and user management platform, providing both APIs and pre-made UI components. This guide will show you how to integrate Clerk with ZenStack's [access control system](../../orm/access-control/). | ||
|
|
||
| ### Set up Clerk | ||
|
|
||
| First, follow Clerk's [quick start guides](https://clerk.com/docs/quickstarts/overview) to set up your project if you haven't already. | ||
|
|
||
| ### Adjust your ZModel | ||
|
|
||
| Since Clerk manages both user authentication and storage, you don't need to store users in your database anymore. However, you still need to provide a type that the `auth()` function can resolve to. Instead of using a regular model, we can declare a `type` instead: | ||
|
|
||
| You can include any field you want in the `User` type, as long as you provide the same set of fields in the context object when calling `ZenStackClient`'s `$setAuth()` method. | ||
|
|
||
| The following code shows an example blog post schema: | ||
|
|
||
| ```zmodel | ||
| type User { | ||
| id String @id | ||
|
|
||
| @@auth | ||
| } | ||
|
|
||
| model Post { | ||
| id String @id @default(cuid()) | ||
| createdAt DateTime @default(now()) | ||
| updatedAt DateTime @updatedAt | ||
| title String | ||
| published Boolean @default(false) | ||
| authorId String // stores Clerk's user ID | ||
|
|
||
| // author has full access | ||
| @@allow('all', auth() != null && auth().id == authorId) | ||
|
|
||
| // logged-in users can view published posts | ||
| @@allow('read', auth() != null && published) | ||
| } | ||
| ``` | ||
|
|
||
| If you choose to [synchronize user data to your database](https://clerk.com/docs/users/sync-data-to-your-backend), you can define `User` as a regular `model` since it's then backed by a database table. | ||
|
|
||
| ### Create a user-bound ORM client | ||
|
|
||
| When using ZenStack's built-in access control, you often use the `auth()` function in policy rules to reference the current user's identity. The evaluation of `auth()` at runtime requires you to call the `$setAuth()` method and pass in the validated user identity from Clerk. | ||
|
|
||
| Please refer to clerk's documentation on how to fetch the current user on the server side for your specific framework. The following code shows an example for Next.js (app router): | ||
|
|
||
| ```ts | ||
| import { auth } from "@clerk/nextjs/server"; | ||
|
|
||
| // ZenStack ORM client with access policy plugin installed | ||
| import { authDb } from './db'; | ||
|
|
||
| async function getUserDb() { | ||
| // get the validated user identity from Clerk | ||
| const authObject = await auth(); | ||
|
|
||
| // create a user-bound ORM client | ||
| return authDb.$setAuth( | ||
| authObject.userId ? { id: authObject.userId } : undefined); | ||
| } | ||
| ``` | ||
59 changes: 59 additions & 0 deletions
59
versioned_docs/version-3.x/recipe/auth-integration/custom.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| --- | ||
| description: Integrating with a custom authentication system. | ||
| sidebar_position: 100 | ||
| sidebar_label: Custom Authentication | ||
| --- | ||
|
|
||
| # Custom Authentication Integration | ||
|
|
||
| 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. | ||
|
|
||
| ## Determine 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 "model" or "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. | ||
|
|
||
| ## Fetch 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. | ||
|
|
||
| ## Create a user-bound ORM client | ||
|
|
||
| Finally, you can call the `$setAuth()` method on `ZenStackClient` to create an ORM instance that's bound to the current user. | ||
|
|
||
| ```ts | ||
| // ZenStack ORM client with access policy plugin installed | ||
| import { authDb } from './db'; | ||
|
|
||
| const user = await getCurrentUser(); // your implementation | ||
| const db = authDb.$setAuth(user); | ||
| ``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.