Skip to content
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

SDK quickstart structure (done on NodeJS) #373

Merged
merged 18 commits into from
Jul 15, 2024
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
77 changes: 45 additions & 32 deletions docs/authentication/auth0/auth0-demo-app.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ title: Permit and Auth0 Demo
---

## 1. Introduction

### 1.1. The application

The demo application is a simple task management application.
To demonstrate the relationship between authentication and authorization, we created a simple to-do application, with authentication already implemented into it based on the [Auth0 Next.JS getting started guide](https://auth0.com/docs/quickstart/webapp/nextjs/interactive). Let’s clone it and run it on your local environment.
To demonstrate the relationship between authentication and authorization, we created a simple to-do application, with authentication already implemented into it based on the [Auth0 Next.JS getting started guide](https://auth0.com/docs/quickstart/webapp/nextjs/interactive). Let’s clone it and run it on your local environment.

**Note:** While this article does not require you to have [Next.JS knowledge](https://nextjs.org/), it requires an Auth0 account with a basic configuration, and Node.JS installed in your [local](https://nodejs.org/en/download) or [remote](https://codesandbox.io/signin?continue=/dashboard?import_repo=true) environment.

Expand All @@ -16,18 +18,19 @@ The full code of the demo application is available [here](https://github.com/per

For our example App, we will create the following roles (it is recommended to use lowercase keys, as keys are case-sensitive):

* admin
* manager
* viewer
- admin
- manager
- viewer

### 1.2. Create the right resources in Permit

In our example, we will set up a todo application, so we will create a `task` resource with the following actions:

- get
- post
- delete

Setting up roles and resources can be done through the [Permit dashboard](https://app.permit.io/policy-editor/roles), by using the [Permit API](https://api.permit.io/v2/redoc#tag/Roles/operation/create_role), or with one of our SDKs: [Python](/sdk/python/usage-example/#create-a-role), [NodeJS](/sdk/nodejs/usage-example#create-a-role) and more. Additional SDKs are available in the SDK Reference section [inside the docs](/).
Setting up roles and resources can be done through the [Permit dashboard](https://app.permit.io/policy-editor/roles), by using the [Permit API](https://api.permit.io/v2/redoc#tag/Roles/operation/create_role), or with one of our SDKs: [Python](/sdk/python/usage-example/#create-a-role), [NodeJS](/sdk/nodejs/quickstart-nodejs#creating-a-new-role-with-permissions) and more. Additional SDKs are available in the SDK Reference section [inside the docs](/).

### 1.3. Set up the right permissions in Permit.io:

Expand All @@ -38,6 +41,7 @@ Setting up roles and resources can be done through the [Permit dashboard](https:
As noted earlier, these permissions can be set up through either the [Permit dashboard](https://app.permit.io/policy-editor) or by using the [Permit API](https://api.permit.io/v2/redoc#tag/Roles/operation/assign_permissions_to_role).

## 2. Run the demo application

### 2.1. Clone the demo application:

```bash
Expand All @@ -46,6 +50,7 @@ git checkout auth0-integration
```

### 2.2. Put your Auth0 credentials in the .env file

To get your own keys in the desired format, [use this link](https://auth0.com/docs/quickstart/webapp/nextjs/interactive#configure-the-sdk) while logged in to your Auth0 account

```bash
Expand All @@ -57,6 +62,7 @@ AUTH0_CLIENT_SECRET='<auth0_client_secret>'
```

### 2.3. Put your Permit credentials in the .env file

You can get your Permit API Key from the [projects page](https://app.permit.io/projects) by clicking on the three dots on the top right of your environment and selecting `Copy API Key`.

_![Get Permit API key](/img/onboarding/secret-key-1.png)_
Expand All @@ -65,24 +71,25 @@ _![Get Permit API key](/img/onboarding/secret-key-1.png)_
PERMIT_API_KEY=<permit_api_key>
```



## 3. How it works

### 3.1. Auth0

As we want to use Auth0 for authentication, we will use the Auth0 SDK to get each user's information and access token.
On the frontend side, we have the Auth0 `useUser` at `index.tsx` that will give us the user's information, and the `userProvider` in `_app.tsx` that redirects the user to the login page if they have not logged in.

```tsx
// index.tsx
//...
const { user, isLoading } = useUser();
const { user, isLoading } = useUser();
//...
```

```tsx
// _app.tsx
//...
<UserProvider>
<Component {...pageProps} />
<Component {...pageProps} />
</UserProvider>
//...
```
Expand All @@ -96,6 +103,7 @@ import { handleAuth } from "@auth0/nextjs-auth0";

export default handleAuth();
```

```ts
// pages/api/tasks.ts
import { getSession } from "@auth0/nextjs-auth0";
Expand All @@ -110,46 +118,49 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
```

### 3.2. Permit

As we want to use Permit for authorization, we will use the Permit SDK to get users' permissions and check if they have the right ones.
Authorization is only done on the backend side, so we will use the `permit` middleware at `pages/api/tasks.ts` to manage all permit-related requests.

```ts
// pages/api/tasks.ts
import { Permit } from 'permitio';
import { Permit } from "permitio";

export const permit = new Permit({
pdp: 'https://cloudpdp.api.permit.io',
pdp: "https://cloudpdp.api.permit.io",
token: process.env.PERMIT_SDK_TOKEN,
});
export default withApiAuthRequired(async function handler(
req: NextApiRequest,
res: NextApiResponse<Task | Task[] | Response>
) {
// Auth0 is checking if the user is logged in (who the user is)
// Auth0 is checking if the user is logged in (who the user is)
const session = await getSession(req, res);
if (!session?.user) {
res.status(401).json({ message: 'unauthorized' });
res.status(401).json({ message: "unauthorized" });
return;
}
// Permit is checking if the user has the right permissions (what the user can do)
// Permit is checking if the user has the right permissions (what the user can do)
const isAllowedForOperation = await permit.check(
session?.user?.sub as string || '', // the user identifier (Permit user id / or Permit user key, in this example we set the Auth0 user id as the key)
(session?.user?.sub as string) || "", // the user identifier (Permit user id / or Permit user key, in this example we set the Auth0 user id as the key)
req.method?.toLowerCase() as string, // the action (can be: get, post, delete)
'task' // our resource key
"task" // our resource key
);
if (!isAllowedForOperation) {
res.status(403).json({ message: 'forbidden' });
res.status(403).json({ message: "forbidden" });
return;
}
//... handle the request
});
```

## 4. The integration

Now that we have the user's information and permissions, we can integrate them.
We need to make sure that Permit is synced with Auth0 so that each user who logs in will have the right roles and permissions.

### 4.1. Sync Auth0 with Permit

First, we need to make sure each user that logs into our app is synced with Permit.
This will be done in the `pages/api/auth/[...auth0].ts` file:

Expand All @@ -165,20 +176,21 @@ export default handleAuth({
},
});
```

This will ensure that each user who logs into our app will be navigated to the `postLogin` page.
Now we need to sync the user with Permit - add the following code to the `postLogin`:

```tsx
// pages/postLogin/index.tsx
export async function getServerSideProps({ req, res }: any) {
const session = await getSession(req, res);
const permitUserObj = {
email: session?.user?.email,
key: session?.user?.sub,
first_name: session?.user?.name,
}
const permitUser = await permit.api.syncUser(permitUserObj);
//... the sync role logic
const session = await getSession(req, res);
const permitUserObj = {
email: session?.user?.email,
key: session?.user?.sub,
first_name: session?.user?.name,
};
const permitUser = await permit.api.syncUser(permitUserObj);
//... the sync role logic
}
```

Expand All @@ -187,10 +199,10 @@ This can be done using this [Auth0 guide](https://auth0.com/docs/manage-users/ac

Here's a quick recap on how this can be done (Please use the Auth0 guide for a more detailed description):

- Go to your Auth0 dashboard > Applications > API.
- Create an API if you don't have one.
- Click on the three dots on the right of your API and click on settings.
- Scroll down to `RBAC Settings` and enable `Add Permissions in the Access Token`.
- Go to your Auth0 dashboard > Applications > API.
- Create an API if you don't have one.
- Click on the three dots on the right of your API and click on settings.
- Scroll down to `RBAC Settings` and enable `Add Permissions in the Access Token`.
- Click on `Save Changes`.

In short, you need to navigate to the Auth0 dashboard and create a new rule https://manage.auth0.com/dashboard/[your-region]/[your-tenant-name]/rules.
Expand All @@ -214,7 +226,7 @@ function (user, context, callback) {
}
```

Now you can see that the session.user object from Auth0 has `my_app_name/roles` section with our roles (of course, you can set <my_app_name> to whatever you want):
Now you can see that the session.user object from Auth0 has `my_app_name/roles` section with our roles (of course, you can set <my_app_name> to whatever you want):

```js
auth0User {
Expand All @@ -229,6 +241,7 @@ auth0User {
sid: 'I9xntALjR3M37Iw62Lgc3xxxxxxxxxx'
}
```

Then when a user logs into our app, we can also sync their roles with Permit by adding the following code just below the `permit.api.syncUser` function:

```tsx
Expand All @@ -248,7 +261,7 @@ Then when a user logs into our app, we can also sync their roles with Permit by
}
```

Now if you assign a role to a user (Either in Auth0 or in Permit), the user will have the correct roles and permissions.
Now if you assign a role to a user (Either in Auth0 or in Permit), the user will have the correct roles and permissions.
(Make sure you use the exact same role names in both Auth0 and Permit - they are case-sensitive!)

[Check out the postLogin page in this example to see the full code.](https://github.com/permitio/permit-next-todo-starter/blob/auth0-integration/pages/postLogin/index.tsx)
Loading