Skip to content

Commit

Permalink
Add oauth docs
Browse files Browse the repository at this point in the history
  • Loading branch information
bcbogdan committed Sep 17, 2024
1 parent 3a668ff commit 9308ff6
Show file tree
Hide file tree
Showing 9 changed files with 692 additions and 0 deletions.
14 changes: 14 additions & 0 deletions v2/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,20 @@ module.exports = {
beforeDefaultRemarkPlugins,
},
],
[
"@docusaurus/plugin-content-docs",
{
id: "oauth",
path: "oauth",
routeBasePath: "docs/oauth",
sidebarPath: require.resolve("./oauth/sidebars.js"),
showLastUpdateTime: true,
editUrl: "https://github.com/supertokens/docs/tree/master/v2/",
remarkPlugins: remarkPlugins,
rehypePlugins: rehypePlugins,
beforeDefaultRemarkPlugins,
},
],
[
"@docusaurus/plugin-content-docs",
{
Expand Down
106 changes: 106 additions & 0 deletions v2/oauth/clients-without-dedicated-backend.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
title: Clients without dedicated backends
hide_title: true
---

# Clients Without Dedicated Backends

You can use the following guide if you have `frontend applications` that use an `authentication service` that is on a different domain but do not have dedicated `backends` for other functionalities.

## 1. Set Up Your Authentication Service

:::note
TODO: Add actual code snippets here
:::

First, initialize and setup **SuperTokens** in your `authentication service`.

## 2. Initialize the OAuth2Provider

In addition to the authentication recipes you’ve set up, initialize the `OAuth2Provider` recipe in your `backend service`.

```typescript
import supertokens from "supertokens-node";
import OAuth2Provider from"supertokens-node/recipe/oauth2provider";

supertokens.init({
framework: "express",
supertokens: {
connectionURI: "<YOUR_CONNECTION_URI>",
apiKey: "<YOUR_API_KEY>",
},
appInfo: {
appName: "",
apiDomain: "<YOUR_API_DOMAIN>",
websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
apiBasePath: "/auth",
websiteBasePath: "/auth"
},
recipeList: [
// This is where you initialize the OAuth2 recipe
OAuth2Provider.init(),
]
});
```

## 3. Add a Way to Create OAuth2 Clients

We have to create OAuth2 clients in order to allow them to authenticate through our flow.

First we need to add a method to do this.
Our recommendation is to use the `createOAuth2Client` function that is exposed by our SDK.
Alternatively, you can also directly call the **SuperTokens** core API.

### Using the `createOAuth2Client` function

:::note
TODO: Add details about what each parameter means
:::

```typescript
import { createOAuth2Client } from "supertokens-node/recipe/oauth2provider";

createClient({
// This value will be shown in the auth page when the app requests the user to authenticate
clientName: 'My Application',
// TODO: Add info about this
responseTypes: ['code', 'id_token'],
// TODO: Add info about this
grantTypes: ['authorization_code', 'refresh_token'],
// TODO: Add info about this
redirectUri: 'https://example.com/oauth/callback',
});

```

### Using the Core API

```bash
curl -X POST https://<CORE_SERVICE_DOMAIN>/recipe/oauth2/admin/clients \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Application",
"response_types": ["code", "id_token"],
"grant_types": ["authorization_code", "refresh_token"],
"redirect_uri": ["https://different.com/oauth/callback"]
}'
```

## 4. Create Separate Clients for Each Frontend Application

Using the method that we defined in the previous step create separate clients for each of your `frontend applications`.

Repeat the process for each domain, adjusting the `clientName` and `redirectUri` as necessary.


## 5. Set Up Your Frontend and Integrate with an OIDC Library

Integrate your frontend applications with a generic OAuth2 or OIDC library. Here are a few popular options: [oidc-client-js](https://github.com/IdentityModel/oidc-client-js), [openid-client](https://github.com/panva/node-openid-client)

### Example Using `openid-client`

```typescript

// TODO: Add example here
```

Empty file.
108 changes: 108 additions & 0 deletions v2/oauth/introduction.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: Introduction
hide_title: true
---

# OAuth2 Support

**OAuth2**, Open Authorization, is an industry-standard authorization framework that enables third-party applications to obtain limited access to a user's resources without exposing their credentials.
It is commonly used for single sign-on (SSO) and authorization.

## When to use OAuth2

In most cases, when using **SuperTokens**, you should not have to use OAuth2 directly.
We already expose the **[ThirdParty Recipe](/docs/thirdparty/introduction)** that enables users to login using external providers.
This covers most of the authentication scenarios that involve OAuth2.

However, there are some custom use cases where you will have to implement a different authentication flow.

- **[If you have multiple frontend clients that connect to different backends](/docs)**
- **[If you have multiple frontend clients connecting to the same backend](/docs)**
- **[If you want to have an unified login experience across multiple domains](/docs)**
- **[If you want to reuse your website login for desktop and mobile apps](/docs)**
- **[For authenticating microservices](/docs)**

For these specific instances we expose recipes that allow you to complete your setup.

## OAuth2 Reference

Before we explore the guides let's first recap some common terms and concepts that are used in the framework.
We will use them throughout the next pages.

### Providers

An **OAuth 2.0 Provider** is a server that implements the OAuth 2.0 protocol, responsible for issuing access tokens to third-party applications after authenticating users.
The provider enables those applications to access and interact with the user's resources securely and without exposing the user's credentials.

### Clients

An **OAuth 2.0 Client** is an application that interacts with an **OAuth 2.0 Provider** to request access to a user's resources.
It then utilizes the access tokens granted by the provider to perform authorized operations on behalf of the user.

The term **client** does not imply any particular implementation characteristics (e.g. whether the application executes on a server, a desktop, or other devices).


### Tokens

An **OAuth Token** is a credential used to access protected resources on behalf of a user.
There are several types of tokens defined by the protocol.

#### Access Token

**Access tokens** are what the **OAuth Client** uses to make requests to an API. The access token is meant to be read and validated by the API.

To validate the token on the backend side you can use the `validateOAuth2AccessToken` exposed by the `OAuth2Provider` recipe.

#### ID Token

An ID token contains information about what happened when a user authenticated, and is intended to be read by the **OAuth Client**.
The ID token may also contain information about the user such as their name or email address, although that is not a requirement of an ID token.

#### Refresh Token

An OAuth Refresh Token is a string that the OAuth client can use to get a new access token without the user's interaction.

### Flows

**Flows** are the set of steps an **OAuth Client** has to perform in order to obtain an access token.
Our implementation supports the following flow types:
- [Authorization Code](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1)
- [Implicit](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.2)
- [Client credentials](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.4)


### Redirect URIs

In the *Authorization Code* and *Implicit* flows, the user is redirected to the authorization provider at the start of authentication.
The results are then communicated to the client through a redirection to one of the redirect URIs registered by the client.

These are configured on the client, during creation, or they can also be added later.
At the end of the authentication flow the user is redirected to one of these after they have completed the authorization request.

### Scopes

**Scopes** in OAuth 2.0 specify the level of access an application is requesting from the user's resources.
This way you can define the boundaries and permissions for what the access token can do.

:::note
- Where do we add these scopes in the actual code
- What's user-info
:::

Our implementation has the following built-in scopes:
- `email`: adds the `email` and `email_verified` claims into the id-token and the user-info.
- `phoneNumber`: adds the `phoneNumber` and `phoneNumber_verified` claims into the id-token and the user-info
- `roles`: adds the roles claim into the id-token and access token.
- This will contain the roles returned by `getRolesForUser`
- This only works if the `UserRoles` recipe is initialized
- `permissions`: adds the `permissions` claim into the id-token and access token.
- This will contain the list of permissions obtained by concatenating the result of `getPermissionsForRole` for all roles returned by `getRolesForUser`
- This only works if the `UserRoles` recipe is initialized


### PKCE

[**PKCE**](https://oauth.net/2/pkce/) is an extension to the **Authorization Code flow** to prevent CSRF and authorization code injection attacks.
We support PKCE and recommend that you use a library that makes use of it.
You can opt-in by setting the `code_challenge` (and optionally `code_challenge_method`) parameters in the authorization URL and then verifying it after the user gets redirected back to the client.

110 changes: 110 additions & 0 deletions v2/oauth/machine-to-machine-authentication.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
title: Machine to Machine Authentication
hide_title: true
---

# Machine to Machine Authentication

You can use the following guide if you want to implement a custom authentication flow between your microservices.

## 1. Set Up Your Authentication Service

:::note
TODO: Add actual code snippets here
:::

First, initialize and setup **SuperTokens** in your `authentication service`.

## 2. Initialize the OAuth2Provider

In addition to the authentication recipes you’ve set up, initialize the `OAuth2Provider` recipe in your `authentication backend`.

```typescript
import supertokens from "supertokens-node";
import OAuth2Provider from"supertokens-node/recipe/oauth2provider";

supertokens.init({
framework: "express",
supertokens: {
connectionURI: "<YOUR_CONNECTION_URI>",
apiKey: "<YOUR_API_KEY>",
},
appInfo: {
appName: "",
apiDomain: "<YOUR_API_DOMAIN>",
websiteDomain: "<YOUR_WEBSITE_DOMAIN>",
apiBasePath: "/auth",
websiteBasePath: "/auth"
},
recipeList: [
// This is where you initialize the OAuth2 recipe
OAuth2Provider.init(),
]
});
```

## 3. Add a Way to Create OAuth2 Clients

We have to create OAuth2 clients in order to allow them to authenticate through our flow.

First we need to add a method to do this.
Our recommendation is to use the `createOAuth2Client` function that is exposed by our SDK.
Alternatively, you can also directly call the **SuperTokens** core API.

### Using the `createOAuth2Client` function

:::note
TODO: Add details about what each parameter means
:::

```typescript
import { createOAuth2Client } from "supertokens-node/recipe/oauth2provider";

createClient({
clientName: 'My Application',
grantTypes: ["client_credentials"],
});

```

### Using the Core API

```bash
curl -X POST https://<CORE_SERVICE_DOMAIN>/recipe/oauth2/admin/clients \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Application",
"grant_types": ["client_credentials"]
}'
```

## 4. Create Separate Clients for Each Application

Using the method that we defined in the previous step create separate clients for each of your `backend services`.

Repeat the process for each domain, adjusting the `clientName` as necessary.

## 5. Create Tokens

To generate tokens for your microservices using the `client_credentials` grant type, use the following code snippet:

:::note
Not sure on how scope should look like
:::

```typescript
fetch('https://api.auth.example.com/auth/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
client_id: "<YOUR_CLIENT_ID>",
client_secret: "<YOUR_CLIENT_SECRET>",
grant_type: 'client_credentials',
scope: ["<YOUR_REQUIRED_SCOPE>"],
}),
});
```


Loading

0 comments on commit 9308ff6

Please sign in to comment.