Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
pilcrowonpaper committed Jan 10, 2024
1 parent ef8a7ce commit 76007a5
Show file tree
Hide file tree
Showing 29 changed files with 161 additions and 58 deletions.
3 changes: 2 additions & 1 deletion docs/malta.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"title": "Guides",
"pages": [
["OAuth 2.0", "/guides/oauth2"],
["OAuth 2.0 with PKCE", "/guides/oauth2-pkce"]
["OAuth 2.0 with PKCE", "/guides/oauth2-pkce"],
["OpenID Connect", "/guides/oidc"]
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/guides/oauth2-pkce.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ return redirect(url);

## Validate authorization code

Compare the state, and use `validateAuthorizationCode()` to validate the authorization code with the code verifier. This returns an object with an access token, and a refresh token if requested. If the code is invalid, it will throw an [`OAuth2RequestError`](https://oslo.js.org/reference/oauth2/OAuth2RequestError).
Compare the state, and use `validateAuthorizationCode()` to validate the authorization code with the code verifier. This returns an object with an access token, an ID token for OIDC, and a refresh token if requested. If the code is invalid, it will throw an [`OAuth2RequestError`](https://oslo.js.org/reference/oauth2/OAuth2RequestError).

```ts
import { OAuth2RequestError } from "arctic";
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/guides/oauth2.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ return redirect(url);

## Validate authorization code

Compare the state, and use `validateAuthorizationCode()` to validate the authorization code. This returns an object with an access token, and a refresh token if requested. If the code or your credentials are invalid, it will throw an [`OAuth2RequestError`](https://oslo.js.org/reference/oauth2/OAuth2RequestError).
Compare the state, and use `validateAuthorizationCode()` to validate the authorization code. This returns an object with an access token, ID token for OIDC, and a refresh token if requested. If the code or your credentials are invalid, it will throw an [`OAuth2RequestError`](https://oslo.js.org/reference/oauth2/OAuth2RequestError).

```ts
import { OAuth2RequestError } from "arctic";
Expand Down
12 changes: 12 additions & 0 deletions docs/pages/guides/oidc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: "OpenID Connect"
---

Arctic will use OpenID Connect if the provider supports it. `validateAuthorizationCode()` will return an ID token for OIDC providers, which can be parsed to get the user info.

```ts
import { parseJWT } from "oslo/jwt";

const tokens = await google.validateAuthorizationCode(code, codeVerifier);
const googleUser = parseJWT(tokens.idToken)!.payload;
```
11 changes: 9 additions & 2 deletions docs/pages/providers/atlassian.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ const tokens: AtlassianTokens = await atlassian.refreshAccessToken(refreshToken)

## Get user profile

Add the `read:me` scopes and use the [`/me` endpoint](https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/#how-do-i-retrieve-the-public-profile-of-the-authenticated-user-).
Add the `read:me` scope and use the [`/me` endpoint](https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/#how-do-i-retrieve-the-public-profile-of-the-authenticated-user-).

```ts
const url = await atlassian.createAuthorizationURL(state, {
scopes: ["read:me"]
});
```

```ts
const tokens = await apple.validateAuthorizationCode(code);
const response = await fetch("https://api.atlassian.com/me", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
11 changes: 9 additions & 2 deletions docs/pages/providers/auth0.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,21 @@ const tokens: Auth0Tokens = await auth0.refreshAccessToken(refreshToken);

## Get user profile

Add the `profile` scopes. Optionally add the `email` scopes to get user email.
Add the `profile` scope. Optionally add the `email` scope to get user email.

```ts
const url = await auth0.createAuthorizationURL(state, {
scopes: ["profile", "email"]
});
```

Parse the ID token or use the `userinfo` endpoint. See [ID token structure](https://auth0.com/docs/secure/tokens/id-tokens/id-token-structure#sample-id-token).

```ts
const tokens = await auth0.validateAuthorizationCode(code);
const response = await fetch("https://xxx.auth.com/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
11 changes: 9 additions & 2 deletions docs/pages/providers/bitbucket.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ const tokens: BitbucketTokens = await bitbucket.refreshAccessToken(refreshToken)

## Get user profile

Add the `account` scopes and use the [`/user` endpoint](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-users/#api-user-get).
Add the `account` scope and use the [`/user` endpoint](https://developer.atlassian.com/cloud/bitbucket/rest/api-group-users/#api-user-get).

```ts
const url = await bitbucket.createAuthorizationURL(state, {
scopes: ["account"]
});
```

```ts
const tokens = await bitbucket.validateAuthorizationCode(code);
const response = await fetch("https://api.bitbucket.org/2.0/user", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
3 changes: 2 additions & 1 deletion docs/pages/providers/box.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ const tokens: BoxTokens = await box.validateAuthorizationCode(code);
Use the [`/users/me` endpoint](https://developer.box.com/reference/get-users-me).

```ts
const tokens = await box.validateAuthorizationCode(code);
const response = await fetch("https://api.box.com/2.0/users/me", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
11 changes: 9 additions & 2 deletions docs/pages/providers/discord.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,19 @@ const tokens: DiscordTokens = await discord.refreshAccessToken(refreshToken);

## Get user profile

Add the `identity` scopes and use the [`/users/@me` endpoint`]().
Add the `identity` scope and use the [`/users/@me` endpoint`]().

```ts
const url = await discord.createAuthorizationURL(state, {
scopes: ["identity"]
});
```

```ts
const tokens = await discord.validateAuthorizationCode(code);
const response = await fetch("https://discord.com/api/users/@me", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
10 changes: 8 additions & 2 deletions docs/pages/providers/dropbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ const tokens: DropboxRefreshedTokens = await dropbox.refreshAccessToken(refreshT

## Get user profile

Add the `profile` scopes. Optionally add the `email` scopes to get user email.
Add the `profile` scope. Optionally add the `email` scope to get user email.

Parse the ID token or use the [`userinfo` endpoint](https://api.dropboxapi.com/2/openid/userinfo). See [supported claims](https://developers.dropbox.com/oidc-guide#oidc-standard).

```ts
const tokens = await dropbox.validateAuthorizationCode(code);
const response = await fetch("https://api.dropboxapi.com/2/openid/userinfo", {
method: "POST".
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand All @@ -49,3 +50,8 @@ Set `access_type` params to `offline`.
const url = await dropbox.createAuthorizationURL();
url.searchParams.set("access_type", "offline");
```

```ts
const tokens = await dropbox.validateAuthorizationCode(code);
const refreshToken: string | null = tokens.refreshToken;
```
6 changes: 4 additions & 2 deletions docs/pages/providers/facebook.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ const tokens: FacebookTokens = await facebook.validateAuthorizationCode(code);

## Get user profile

Use the `/me` endpoint. See [fields](https://developers.facebook.com/docs/graph-api/reference/user#Reading).
Use the `/me` endpoint. See [user fields](https://developers.facebook.com/docs/graph-api/reference/user#Reading).

```ts
const tokens = await facebook.validateAuthorizationCode(code);

const url = new Request("https://graph.facebook.com/me");
url.searchParams.set("access_token", accessToken);
url.searchParams.set("access_token", tokens.accessToken);
url.searchParams.set("fields", ["id", "name", "picture", "email"].join(","));
const response = await fetch(url);
const user = await response.json();
Expand Down
3 changes: 2 additions & 1 deletion docs/pages/providers/figma.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ const tokens: FigmaRefreshedTokens = await figma.refreshAccessToken(refreshToken
Use the [`/me` endpoint](https://www.figma.com/developers/api#get-me-endpoint).

```ts
const figma = await discord.validateAuthorizationCode(code);
const response = await fetch("https://api.figma.com/v1/me", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
13 changes: 10 additions & 3 deletions docs/pages/providers/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,27 @@ Use the [`/user` endpoint](https://docs.github.com/en/rest/users/users?apiVersio
```ts
const response = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
```

## Get email

Add the `email` scopes and use the [`/user/emails` endpoint](https://docs.github.com/en/rest/users/emails?apiVersion=2022-11-28#list-email-addresses-for-the-authenticated-user).
Add the `email` scope and use the [`/user/emails` endpoint](https://docs.github.com/en/rest/users/emails?apiVersion=2022-11-28#list-email-addresses-for-the-authenticated-user).

```ts
const url = await github.createAuthorizationURL(state, {
scopes: ["email"]
});
```

```ts
const tokens = await github.validateAuthorizationCode(code);
const response = await fetch("https://api.github.com/user/emails", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const emails = await response.json();
Expand Down
11 changes: 9 additions & 2 deletions docs/pages/providers/gitlab.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,19 @@ const tokens: GitLabTokens = await gitlab.refreshAccessToken(refreshToken);

## Get user profile

Add the `read_user` scopes and use the [`/user` endpoint](https://docs.gitlab.com/ee/api/users.html#list-current-user).
Add the `read_user` scope and use the [`/user` endpoint](https://docs.gitlab.com/ee/api/users.html#list-current-user).

```ts
const url = await gitlab.createAuthorizationURL(state, {
scopes: ["read_user"]
});
```

```ts
const tokens = await gitlab.validateAuthorizationCode(code);
const response = await fetch("https://gitlab.com/api/v4/user", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
9 changes: 5 additions & 4 deletions docs/pages/providers/google.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,21 @@ const tokens: GoogleRefreshedTokens = await google.refreshAccessToken(refreshTok

## Get user profile

Add the `profile` scopes. Optionally add the `email` scopes to get user email.
Add the `profile` scope. Optionally add the `email` scope to get user email.

```ts
const google = new Google(clientId, clientSecret, redirectURI, {
scopes: ["profile"]
const url = await google.createAuthorizationURL(state, codeVerifier, {
scopes: ["profile", "email"]
});
```

Parse the ID token or use the `userinfo` endpoint. See [ID token claims](https://developers.google.com/identity/openid-connect/openid-connect#an-id-tokens-payload).

```ts
const tokens = await google.validateAuthorizationCode(code, codeVerifier);
const response = await fetch("https://openidconnect.googleapis.com/v1/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
3 changes: 2 additions & 1 deletion docs/pages/providers/kakao.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ const tokens: KakaoTokens = await kakao.refreshAccessToken(refreshToken);
Use the [`/user/me` endpoint](https://developers.kakao.com/docs/latest/en/kakaologin/rest-api#req-user-info).

```ts
const tokens = await kakao.validateAuthorizationCode(code);
const response = await fetch("https://kapi.kakao.com/v2/user/me", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
7 changes: 4 additions & 3 deletions docs/pages/providers/keycloak.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,21 @@ const tokens: KeycloakTokens = await keycloak.refreshAccessToken(refreshToken);

## Get user profile

Add the `profile` scopes. Optionally add the `email` scopes to get user email.
Add the `profile` scope. Optionally add the `email` scope to get user email.

```ts
const keycloak = new Keycloak(realmURL, clientId, clientSecret, redirectURI, {
const url = await keycloak.createAuthorizationURL(state, codeVerifier, {
scopes: ["profile", "email"]
});
```

Parse the ID token or use the `userinfo` endpoint.

```ts
const tokens = await keycloak.validateAuthorizationCode(code, codeVerifier);
const response = await fetch("https://example.com/realms/xxx/protocol/openid-connect/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
7 changes: 4 additions & 3 deletions docs/pages/providers/line.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,21 @@ const tokens: LineRefreshedTokens = await line.refreshAccessToken(refreshToken);

## Get user profile

Add the `profile` scopes. Optionally add the `email` scopes to get user email.
Add the `profile` scope. Optionally add the `email` scope to get user email.

```ts
const line = new Line(clientId, clientSecret, redirectURI, {
const url = await line.createAuthorizationURL(state, codeVerifier, {
scopes: ["profile", "email"]
});
```

Parse the ID token or use the `userinfo` endpoint. See [ID token claims](https://developers.line.biz/en/docs/line-login/verify-id-token/#signature).

```ts
const tokens = await line.validateAuthorizationCode(code, codeVerifier);
const response = await fetch("https://api.line.me/oauth2/v2.1/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
11 changes: 9 additions & 2 deletions docs/pages/providers/linkedin.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,21 @@ const tokens: LinkedInTokens = await linkedIn.refreshAccessToken(refreshToken);

## Get user profile

Add the `profile` scopes, and optionally add the `email` scopes to get user email.
Add the `profile` scopes, and optionally add the `email` scope to get user email.

```ts
const url = await linkedIn.createAuthorizationURL(state, {
scopes: ["profile", "email"]
});
```

Parse the ID token or use the `userinfo` endpoint. See [ID token claims](https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin-v2#response-body-schema).

```ts
const tokens = await linkedIn.validateAuthorizationCode(code);
const response = await fetch("https://api.linkedin.com/v2/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
10 changes: 5 additions & 5 deletions docs/pages/providers/microsoft-entra-id.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@ const tokens: MicrosoftEntraIdTokens = await entraId.refreshAccessToken(refreshT

## Get user profile

Add the `profile` scopes. Optionally add the `email` scopes to get user email.
Add the `profile` scope. Optionally add the `email` scope to get user email.

```ts
const url: URL = await entraId.createAuthorizationURL(state, codeVerifier, {
// optional
scopes: ["profile", "email"] // "openid" always included
const url = await entraId.createAuthorizationURL(state, codeVerifier, {
scopes: ["profile", "email"]
});
```

Parse the ID token or use the `userinfo` endpoint. See [ID token claims](https://learn.microsoft.com/en-us/entra/identity-platform/id-token-claims-reference).

```ts
const tokens = await entraId.validateAuthorizationCode(code, codeVerifier);
const response = await fetch("https://graph.microsoft.com/oidc/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();
Expand Down
Loading

0 comments on commit 76007a5

Please sign in to comment.