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
Binary file added docs/assets/integrate/oauth2/oauth2-creds.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/integrate/oauth2/settings-links.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/integrate/oauth2/settings-new.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/integrate/oauth2/settings-scopes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
173 changes: 96 additions & 77 deletions docs/integrate/oauth2/connect.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,76 +3,106 @@ title: "OAuth 2.0 Connect"
sidebarTitle: "Connect users"
---

## Authorize

To start the authorization flow you need to redirect the user to the authorization URL. It looks like this:

```
https://polar.sh/oauth2/authorize?
response_type=code
&client_id=CLIENT_ID
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&scope=openid%20email
```

The parameters are the one described in the [OpenID Connect specification](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). The most important ones are:

<ParamField path="response_type=code" type="string" required>
Indicates that you want to use the authorization code flow. Most common and
the only one supported by Polar.
</ParamField>

<ParamField path="client_id" type="string" required>
The Client ID you got when creating the OAuth 2.0 client.
</ParamField>

<ParamField path="redirect_uri" type="string" required>
The URL where the user will be redirected after granting access to their data. Make sure you declared it when creating the OAuth2 client.
</ParamField>

<ParamField path="scope" type="string" required>
A space-separated list of scopes you want to ask for. Make sure they are part of the scopes you declared when creating the OAuth2 client.
</ParamField>

If you redirect the user to this URL, they'll see a page asking them to grant access to their data, corresponding to the scopes you asked for.

<img src="/assets/integrate/oauth2/connect.png" />

If they allow it, they'll be redirected to your `redirect_uri` with a `code` parameter in the query string. This code is a one-time code that you can exchange for an access token.

#### Exchange code token

Once you have the authorization code, you can exchange it for an access token. To do so, you'll need to make a `POST` request to the token endpoint. This call needs to be authenticated with the Client ID and Client Secret you got when creating the OAuth2 client.

Here is an example with cURL:

```bash
curl -X POST https://api.polar.sh/v1/oauth2/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&code=AUTHORIZATION_CODE&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&redirect_uri=https://example.com/callback'
```

You should get the following response:

```json
{
"token_type": "Bearer",
"access_token": "polar_at_XXX",
"expires_in": 864000,
"refresh_token": "polar_rt_XXX",
"scope": "openid email",
"id_token": "ID_TOKEN"
}
```

The `access_token` will allow you to make authenticated API requests on behalf of the user. The `refresh_token` is a long-lived token that you can use to get new access tokens when the current one expires. The `id_token` is a signed JWT token containing information about the user, as per the [OpenID Connect specification](https://openid.net/specs/openid-connect-core-1_0.html#IDToken).
<Steps>
<Step title="Redirect the user to Authorization URL">
To start the authorization flow you need to redirect the user to the authorization URL. It looks like this:

```
https://polar.sh/oauth2/authorize?
response_type=code
&client_id=CLIENT_ID
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&scope=openid%20email
```

<Note>
The domain to which the authorize request needs to be made is **polar.sh** (and not api.polar.sh).
</Note>

The parameters are the one described in the [OpenID Connect specification](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest). The most important ones are:

<ParamField path="response_type=code" type="string" required>
Indicates that you want to use the authorization code flow. Most common and
the only one supported by Polar.
</ParamField>

<ParamField default="user" path="sub_type" type="string" required>
Supports: `organization`, `user`

Indicates the level of access you want to include for your OAuth 2.0 token.

With `user` - the access of the OAuth 2.0 token is to all the organizations of the user.

With `organization` - the access of the OAuth 2.0 token is limited to the organization selected by the user.
</ParamField>

<ParamField path="client_id" type="string" required>
The Client ID you got when creating the OAuth 2.0 client.
</ParamField>

<ParamField path="redirect_uri" type="string" required>
The URL where the user will be redirected after granting access to their data. Make sure you declared it when creating the OAuth2 client.
</ParamField>

<ParamField path="scope" type="string" required>
A space-separated list of scopes you want to ask for. Make sure they are part of the scopes you declared when creating the OAuth2 client.
<Note>
If you require `id_token` to be part of the response, make sure to include `openid` as part of the scope.
</Note>
</ParamField>

Once redirected, the user will see a page requesting them to grant access to their data according to the scopes you specified.

<img src="/assets/integrate/oauth2/connect.png" />

If they allow it, they'll be redirected to your set `redirect_uri` with the `code` parameter in the query string. This `code` is a one-time use code that you can exchange for an access token.
</Step>
<Step title="Exchange authorization code for an access token">
Once you have the authorization code, you can exchange it for an access token. To do so, you'll need to make [a `POST` request to the token endpoint](/docs/api-reference/oauth2/connect/request-token). This call needs to be authenticated with the Client ID and Client Secret you got when [creating the OAuth2 client](/integrate/oauth2/setup).

Here is an example with cURL:

```bash
curl -X POST https://api.polar.sh/v1/oauth2/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&code=AUTHORIZATION_CODE&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&redirect_uri=https://example.com/callback'
```

You should get the following response:

```json
{
"token_type": "Bearer",
"access_token": "polar_at_XXX",
"expires_in": 864000,
"refresh_token": "polar_rt_XXX",
"scope": "openid email",
"id_token": "ID_TOKEN"
}
```

The `access_token` will allow you to make authenticated API requests on behalf of the user. The `refresh_token` is a long-lived token that you can use to get new access tokens when the current one expires. The `id_token` is a signed JWT token containing information about the user, as per the [OpenID Connect specification](https://openid.net/specs/openid-connect-core-1_0.html#IDToken).
</Step>
<Step title="Make authenticated requests">
Once you have an access token, you can make authenticated requests to the API. Here is a simple example with cURL:

```bash
curl -X GET https://api.polar.sh/v1/oauth2/userinfo \
-H 'Authorization: Bearer polar_at_XXX'
```
</Step>
</Steps>

#### User vs Organization Access Tokens

We support the concept of access tokens at **organization level**. Contrary to the standard access tokens, those tokens are not tied to a user but to an organization. They can be used to make requests operating only on a specific organization data, improving privacy and security.

To ask for an organization access token, you need to add the parameter `sub_type=organization` to the authorization URL:

<Note>
The default value of `sub_type` is user.
</Note>

```
https://polar.sh/oauth2/authorize?response_type=code&client_id=polar_ci_j3X95_MgfdSCeCd2qkFnUw&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&scope=openid%20email&sub_type=organization
```
Expand All @@ -81,23 +111,12 @@ At this point, the user will be prompted to select one of their organization bef

The rest of the flow remains unchanged. The access token you'll get will be tied to the selected organization.


Bear in mind that some endpoints might not support organization access tokens.
Typically, user-specific endpoints like `/v1/users/benefit` will not work with
organization access tokens.

<Note>
Some endpoints might not support organization access tokens. Typically, user-specific endpoints like `/v1/users/benefit` will not work with organization access tokens.
</Note>

#### Public Clients

Public clients are clients where the Client Secret can't be kept safe, as it would be accessible by the final user. This is the case for SPA, mobile applications, or any client running on the user's device.

In this case, **and only if the client is configured as a Public Client**, the request to the token endpoint won't require the `client_secret` parameter. However, the [PKCE](https://oauth.net/2/pkce/) method will be required to maximize security.

### Make authenticated requests

Once you have an access token, either from a Personal Access Token or from the OpenID Connect flow, you can make authenticated requests to the API. Here is a simple example with cURL:

```bash
curl -X GET https://api.polar.sh/v1/oauth2/userinfo \
-H 'Authorization: Bearer polar_at_XXX'
```
9 changes: 3 additions & 6 deletions docs/integrate/oauth2/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ sidebarTitle: "Introduction"
description: "For partners building services and extensions for Polar customers"
---

### OpenID Connect (OAuth2)
### OpenID Connect (OAuth 2.0)

Only use our **OpenID Connect** in case you want to act on the behalf of other users via our API, e.g building an app/service for Polar customers. Otherwise, always use an **Organization Access Token (OAT)** to integrate Polar for your own service.

Polar implements the [OpenID Connect specification](https://openid.net/developers/how-connect-works/) to enable third-party authentication. It's a layer on top of the OAuth2 framework aiming at making integration more standard and predictable.

In particular, it comes with a **discovery endpoint** allowing compatible clients to automatically work with the OpenID Connect server. Here is Polar's one:

[OpenID Configuration](https://api.polar.sh/.well-known/openid-configuration)
Polar implements the [OpenID Connect specification](https://openid.net/developers/how-connect-works/) to enable third-party authentication. It's a layer on top of the OAuth 2.0 framework aiming at making integration more standard and predictable.

In particular, it comes with a **discovery endpoint** allowing compatible clients to automatically work with the OpenID Connect server. Polar's OpenID Configuration is available at https://api.polar.sh/.well-known/openid-configuration.
65 changes: 46 additions & 19 deletions docs/integrate/oauth2/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,50 @@ title: "Create an OAuth 2.0 Client"
sidebarTitle: "Create a client"
---

Before being able to make authentication requests, you'll need an **OAuth2 Client**. It's the entity that'll identify you, as a third-party developer, between Polar and the final user.
To make authentication requests to Polar on behalf of your users, you will need an **OAuth 2.0 Client**. It's the entity that'll identify you, as a third-party developer, between Polar and the final user.

You can manage them from your [User Settings](https://polar.sh/settings#oauth)

Here are the required fields:

* *Application Name*: the name of the application that'll be shown to the final users.
* *Client Type*: the type of client you are creating. [Read more](#public-clients)
* *Redirect URIs*: for security reasons, you need to declare your application URL where the users will be redirected after granting access to their data.
<Note>
When configuring your OAuth client, you must use an `https://` URL for security reasons. We block `http://` URLs, except when the hostname is `localhost`. This exception allows you to use `http://localhost` for convenient testing in development mode.
</Note>
* *Scopes*: the list of scopes your app will be able to ask for. To improve privacy and security, select only the scopes you really need for your application.
* *Homepage URL*: the URL of your application. It'll be shown to the final users on the authorization page.

Optionally, you can also add a **logo**, **terms of service** and **privacy policy** URL. They'll all be shown to the final users on the authorization page.

Once your client is created, you'll get a **Client ID** and a **Client Secret**. You'll need those values to make authentication requests.

Those values are super sensitive and should be kept secret. They allow making authentication requests on Polar!
<Steps>
<Step title="Go to OAuth Applications in Account Settings">
Go to [Account Settings > Developer > OAuth Applications](https://polar.sh/dashboard/account/developer) and click the `New OAuth App` button to start obtaining the OAuth 2.0 `client_id` and `client_secret` values.
<img src="/assets/integrate/oauth2/settings-new.png" />
</Step>
<Step title="Fill the details for your OAuth 2.0 application">
<img src="/assets/integrate/oauth2/settings-till-redirect.png" />
<ParamField path="Application Name" type="string" required>
Name of the application that will be shown to the final users.
</ParamField>
<ParamField path="Logotype" type="string">
Upload a logo to be shown on the authorization screen.
</ParamField>
<ParamField path="Client Type" type="string" required>
`Confidential Client` or `Public Client`
</ParamField>
<ParamField path="Redirect URIs" type="string" required>
URL(s) where the users will be redirected after granting access to their data.
<Note>
When configuring your OAuth client, you must use an `https://` URL for security reasons. We block `http://` URLs, except when the hostname is `localhost`. This exception allows you to use `http://localhost` for convenient testing in development mode.
</Note>
</ParamField>
<img src="/assets/integrate/oauth2/settings-scopes.png" />
<img src="/assets/integrate/oauth2/settings-links.png" />
<ParamField path="Scopes" type="string" required>
The list of scopes your app will be able to ask for.
</ParamField>
<ParamField path="Homepage URL" type="string" required>
URL of your application. It will be shown to the final users on the authorization page.
</ParamField>
<ParamField path="Terms of Service" type="string" required>
URL to your application's terms of service.
</ParamField>
<ParamField path="Privacy Policy" type="string" required>
URL to your application's privacy policy.
</ParamField>
</Step>
<Step title="Save the OAuth 2.0 configuration">
Click the `Create` button to save the OAuth 2.0 configuration
</Step>
<Step title="Obtain the client_id and client_secret values">
Once the OAuth 2.0 configuration is saved, you will be presented with the `Client ID` and `Client Secret`. Store them as `client_id` and `client_secret` in your application as environment variables so that they can be securely accessed.
<img src="/assets/integrate/oauth2/oauth2-creds.png" />
</Step>
</Steps>
Loading