Skip to content

Commit

Permalink
docs: improve authorization guide (#3064)
Browse files Browse the repository at this point in the history
- Fix docs redirects
- Improve authorization guide

---------

Co-authored-by: Samuel Bodin <1637651+bodinsamuel@users.noreply.github.com>
  • Loading branch information
bastienbeurier and bodinsamuel authored Nov 27, 2024
1 parent d0f3acb commit 9f80094
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 105 deletions.
29 changes: 13 additions & 16 deletions docs-v2/guides/authorize-an-api-from-your-app-with-custom-ui.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ sidebarTitle: 'Authorize an API from you app (custom UI)'
description: 'Step-by-step guide on getting user authorization with your own UI.'
---

# Authorize users from your app using your own UI
<Info>
Pre-requisites:
- complete the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration)
- generate a [Connect session token](/guides/getting-started/authorize-an-api-from-your-app#generate-a-session-token-backend)
</Info>

## Integrate the frontend SDK

Once you have tested that the authorization flow works for your own external account, you can trigger authorization flows for your customers from your app with the Nango SDK.

Get your `Public Key` from the _Environment Settings_ tab.

In your frontend, initiate Nango ([reference](/reference/sdks/frontend#instantiate-the-frontend-sdk)):

```ts
import Nango from '@nangohq/frontend';

const nango = new Nango({ connectSessionToken: '<CONNECTION-SESSION-TOKNE>' });
const nango = new Nango({ connectSessionToken: '<CONNECT-SESSION-TOKEN>' });
```

Initiate the authorization flow ([reference](/reference/sdks/frontend#collect-and-store-end-user-credentials)):
Expand Down Expand Up @@ -85,19 +85,17 @@ nango

</Tabs>

<Tip>
Nango will automatically collect, store, and refresh the API credentials as needed.
</Tip>

## APIs requiring connection-specific configuration for authorization
## Handle APIs requiring connection-specific configuration for authorization

Some APIs require connection-specific configuration (e.g. Zendesk, Shopify).

For example, Zendesk has the following authorization URL, where the subdomain is specific to a user's Zendesk account:

`https://<USER-SUBDOMAIN>.zendesk.com/oauth/authorizations/new`

For these cases, you must provide this configuration when calling `nango.auth()` ([reference](/reference/sdks/frontend#collect-and-store-end-user-credentials)):
When using the [Connect UI](/guides/getting-started/authorize-an-api-from-your-app#option-1-use-the-nango-connect-ui), this information is collected from the end user with an automatically-generated form.

But when using a custom UI, you must provide this configuration when calling `nango.auth()` ([reference](/reference/sdks/frontend#collect-and-store-end-user-credentials)):

```js
nango.auth('zendesk', {
Expand All @@ -113,11 +111,10 @@ nango.auth('zendesk', {
});
```

This _connection configuration_ is stored in the connection. You can retrieve it with the SDK ([reference](/reference/sdks/node#get-a-connection-with-credentials)), API ([reference](/reference/api/connection/get)), and the Nango UI.

# Troubleshoot authorization errors
This _connection configuration_ is stored in the connection. You can retrieve it with the SDK ([reference](/reference/sdks/node#get-a-connection-with-credentials)) and API ([reference](/reference/api/connection/get)), or see it in connection details in the Nango UI.

If an authorization request fails, you can analyze the relevant log in the _Logs_ tab of the Nango UI.
# Next
Once the authorization succeeds, follow the [_Save the connection ID_ section](/guides/getting-started/authorize-an-api-from-your-app#save-the-connection-id-backend) to finish implementation of the authorization flow.

<Tip>
**Questions, problems, feedback?** Please reach out in the [Slack community](https://nango.dev/slack).
Expand Down
2 changes: 1 addition & 1 deletion docs-v2/guides/customize/create-a-custom-integration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: 'Step-by-step guide on how to create a custom integration with Nang
In Nango, integration use-cases are mapped to [syncs](/understand/concepts/syncs) and [actions](/understand/concepts/actions). Before starting, determine if a sync, an action, or a combination of both fits your use case.

<Info>
Pre-requisite: completion of the [_Set up the CLI and folder_ guide](/guides/customize/setup).
Pre-requisite: complete the [_Set up the CLI and folder_ guide](/guides/customize/setup).
</Info>

# Edit the `nango.yaml` configuration
Expand Down
178 changes: 93 additions & 85 deletions docs-v2/guides/getting-started/authorize-an-api-from-your-app.mdx
Original file line number Diff line number Diff line change
@@ -1,40 +1,67 @@
---
title: 'Authorize users from your app'
sidebarTitle: 'Authorize users from your app'
description: 'Step-by-step guide on getting user authorization to access an external API, from your application.'
description: 'Step-by-step guide to getting user authorization to access an external API from your application.'
---

<Info>
Pre-requisite: completion of the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration).
Pre-requisite: complete the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration).
</Info>

Nango Connect requires a unique temporary token to securely authenticate your users.
# Generate a session token (backend)

<img src="/images/connect-ui/steps.png" alt="Nango Connect UI required steps" />
In **your backend**, set up an API endpoint that your frontend will call. This endpoint should request a session token from Nango and return it to the frontend.

<Tip>You can check a live implementation in our <a href="https://github.com/NangoHQ/sample-app?rel=connect-ui-guide"> Sample App</a></Tip>
Here's an example of how to generate a session token using Nango's API ([API ref](/reference/api/connect/sessions/create) / [Node SDK ref](/reference/sdks/node#create-a-connect-session)):

## Step 1: Generate a Session token
<Tabs>

To securely authenticate your users, we need a dedicated token generated on your backend and passed to the frontend. This security measure allows us to strictly identify authenticated users and pre-filter allowed integrations.
<Tab title="cURL">

On **your backend**, you need an API endpoint that your frontend contacts, which will then communicate with the Nango API. Once you get back the token, forward it to Nango Connect.
This token has a lifespan of 30 minutes after which it expires.
```bash
curl --request POST \
--url https://api.nango.dev/connect/sessions \
--header 'Authorization: Bearer <NANGO-SECRET-KEY>' \
--header 'Content-Type: application/json' \
--data '{
"end_user": {
"id": "<END-USER-ID>",
"email": "<END-USER-EMAIL>",
"display_name": "<OPTIONAL-END-USER-DISPLAY-NAME>"
},
"organization": {
"id": "<OPTIONAL-ORG-ID>",
"display_name": "<OPTIONAL-ORG-DISPLAY-NAME>"
},
"allowed_integrations": [
"<INTEGRATION-ID>"
]
}'

```

```javascript
</Tab>

<Tab title="Node">

```ts
import { Nango } from '@nangohq/node';

const nango = new Nango({ secretKey: process.env['NANGO_SECRET_KEY'] });
const nango = new Nango({ secretKey: process.env['<NANGO-SECRET-KEY>'] });

api.post('/sessionToken', (req, res) => {
// Ask Nango for a secure token
const res = await nango.createConnectSession({
end_user: {
id: user.id,
email: user.email,
display_name: user.displayName,
id: '<END-USER-ID>',
email: '<END-USER-EMAIL>',
display_name: '<OPTIONAL-END-USER-DISPLAY-NAME>',
},
allowed_integrations: ['bamboohr'],
organization: {
id: '<OPTIONAL-ORG-ID>',
display_name: '<OPTIONAL-ORG-DISPLAY-NAME>'
},
allowed_integrations: ['<INTEGRATION-ID>'],
});

// Send this token back to your frontend
Expand All @@ -43,110 +70,91 @@ api.post('/sessionToken', (req, res) => {
});
});
```
</Tab>

<Card title="POST /connect/sessions" icon="code" href="/reference/api/connect/sessions/create" horizontal>
Not using the SDK? Check our HTTP API reference
</Card>

## Step 2: Trigger Auth Flow
</Tabs>

In **your frontend**, you need to load our SDK, get the Session Token from Step 1 and open Nango Connect
<Accordion title="Details on end user and organization information">
The `end_user` and `organization` information fields helps identify which connection belongs to which end user and organization. This information is also used for display purposes in the Nango UI and, in some cases, for custom billing plans.

```js
import Nango from '@nangohq/frontend';

const nango = new Nango();
const connect = nango.openConnectUI();
Required fields:
- `end_user.id`: Your internal ID of the user who initiated the authorization flow. This ID, and potentially the `organization.id`, are crucial for reconciling the connection details that your backend receives from Nango once the connection is successfully created (as described in the [_Save the connection ID_ section](#save-the-connection-id-backend)).
- `end_user.email`: The email of the user who initiated the authorization flow. This email is displayed in the Nango UI and used to retrieve & display the user's company logo, enhancing visual clarity.

// Call the endpoint created in Step 1
const res = await fetch('/sessionToken', { method: 'POST' });
connect.setSessionToken(res.sessionToken);
```
<Info>
**Organization-level connections**

<Tip>It's recommended to set the `sessionToken` asynchronously to be able to display the UI loading to your users before it's ready for better UX</Tip>
In some cases, a connection belongs to an organization rather than a user. In such cases, fill in the relevant organization information, in additional to the required end user information (based on the user who initiated the authorization flow). Sometimes, the user email in your app will not match the email they use to connect their external account, which is fine. If you really cannot provide a user ID and email, you can use placeholders without affecting how Nango operates.
</Info>

</Accordion>

## Step 3: Link Connection ID to your user
## Trigger the auth flow (frontend)

In **your frontend**, the Connect UI will send back an event when a user connects or closes the modal. You can register an event listener and respond appropriately.
In **your frontend**, load the Nango frontend SDK, retrieve the session token from the backend, and trigger the authorization flow.

When a user completes a flow, you will receive a `connect` event. This event contains the `providerConfigKey`, which is the id of your integration and a `connectionId`, which is the auto-generated id that represents the couple user + integration.
### Option 1: Use the Nango Connect UI

```js
[...]

function saveConnectionId(authResults) {
await fetch('/connection', { method: 'POST', body: authResults });
}

nango.openConnectUI({
sessionToken: await getSessionToken(),
import Nango from '@nangohq/frontend';

// Listen to events
const nango = new Nango();
const connect = nango.openConnectUI({
onEvent: (event) => {
if (event.type === 'connect') {
void saveConnectionId(event.payload);
if (event.type === 'close') {
// Handle modal closed.
} else if (event.type === 'connect') {
// Handle auth flow successful.
}
},
});

const res = await fetch('/sessionToken', { method: 'POST' }); // Retrieve the session roken from your backend.
connect.setSessionToken(res.sessionToken); // A loading indicator is shown until this is set.
```

In your backend, associate this connectionId to your end user.
### Option 2: Use your custom UI

```javascript
api.post('/connection', (req, res) => {
await User.update({
connectionId: req.body.connectionId,
integrationId: req.body.providerConfigKey,
});
Refer to the [_Authorize an API from your app with custom UI_ guide](/guides/authorize-an-api-from-your-app-with-custom-ui) for details on implementing a custom user interface.

res.status(200).send({
success: true
});
});
```
## Save the Connection ID (backend)

<Tip>If you have multiple integrations you will have to store multiple `connectionId`s</Tip>
The connection ID, a UUID generated by Nango, is required to manage the connection and access its credentials & data. So you need to persist this ID.

## Listen for webhooks
Upon successful authorization, Nango will send a webhook to your backend with the connection ID.

Your backend is notified by Nango when an authorization attempt is completed, successful or not.
To set up this webhook:
1. go to the _Environment Settings_ tab in the Nango UI
2. specify a _Webhook URL_ where Nango should send notifications
3. enable the _Send New Connection Creation Webhooks_ option
4. create the specified route in your backend to handle Nango webhooks

To set this up:
1. go to the _Environment Settings_ tab
2. specify a _Webhook URL_ to which Nango will send notifications
3. listen for webhooks in your backend at the specified route
4. enable the "Send New Connection Creation Webhooks" checkbox

Nango webhooks are post requests with the following JSON body:
Successful authorization webhooks sent by Nango are `POST` requests with the following JSON body:
```json
{
"type": "auth",
"operation": "creation",
"success": true,
"connectionId": "<CONNECTION-ID>",
"authMode": "OAUTH1|OAUTH2|OAUTH2_CC|BASIC|API_KEY|APP_STORE|CUSTOM|APP|NONE|TBA",
"providerConfigKey": "<INTEGRATION-ID>",
"provider": "<API-CONFIGURATION-ID>",
"environment": "dev" | "prod",
"success": true | false,
"operation": "creation" | "override" | "unknown",
"error": "<ERROR>"
"endUser": { "endUserId": "<END-USER-ID>", "organizationId": "<ORGANIZATION-ID>" },
...
}
```

For each successful authorization attempt, persist the connection ID & integration ID in your database. You will need them to retrieve the connection credentials later.
For each successful authorization, persist the `connectionId` value alongside its corresponding user or organization, designated by `endUser.endUserId` and `endUser.organizationId`.

<Info>
Before using Nango in production, we advise [verifying webhook signatures](/guides/verify-webhooks-from-nango).
</Info>
# Troubleshoot authorization errors

# You are ready
If an authorization request fails, you can analyze the relevant log in the _Logs_ tab of the Nango UI.

Your users can now launch Nango Connect and connect to any of your integrations, Nango is taking care of the rest.


<Card title="Want to build your own UI?" icon="code" href="/guides/authorize-an-api-from-your-app-with-custom-ui" horizontal>
Use the Headless API to create your custom experience
</Card>
# You are ready

You have successfully set up the authorization flow for your users. Next steps:
- View new connections & associated credentials in the _Connections_ tab of the Nango UI
- Retrieve connection credentials with the [API](/reference/api/connection/get) or [Node SDK](/reference/sdks/node#get-a-connection-with-credentials)
- [Read data](/guides/getting-started/read-from-an-api) from the API
- [Write data](/guides/getting-started/write-to-an-api) to the API
- [Proxy request](/guides/getting-started/proxy-requests-to-an-api) to the API

<Tip>
**Questions, problems, feedback?** Please reach out in the [Slack community](https://nango.dev/slack).
Expand Down
2 changes: 1 addition & 1 deletion docs-v2/guides/getting-started/read-from-an-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: 'Step-by-step guide on how to continuously sync data from an API (u
---

<Info>
Pre-requisite: completion of the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration).
Pre-requisite: complete the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration).
</Info>

# Activate a sync template
Expand Down
2 changes: 1 addition & 1 deletion docs-v2/guides/getting-started/write-to-an-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: 'Step-by-step guide on how to write to an API (using an action temp
---

<Info>
Pre-requisite: completion of the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration).
Pre-requisite: complete the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration).
</Info>

# Activate an action template
Expand Down
2 changes: 1 addition & 1 deletion docs-v2/guides/proxy-requests-to-an-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: 'Step-by-step guide on how to proxy requests to an API (using the _
---

<Info>
Pre-requisite: completion of the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration).
Pre-requisite: complete the [_Configure an integration_ guide](/guides/getting-started/configure-an-integration).
</Info>

The [Proxy](/understand/concepts/proxy) lets you query external APIs easily with credentials injection, request logging, and pre-configurations for base URLs, rate-limits, retries, etc.
Expand Down
Binary file removed docs-v2/images/connect-ui/steps.png
Binary file not shown.

0 comments on commit 9f80094

Please sign in to comment.