Overview
Every provider exposes the low-level API documented below: a constructor, createAuthorizationURL(), validateAuthorizationCode(), and where the provider supports them refreshAccessToken() and revokeToken().
All of them except Synology also expose the high level API, getAuthorizationURL() and getUser(). Synology publishes no user profile endpoint, so it stays low-level only.
This table lists the environment prefix each provider reads its options from and the scopes it requests when you set none.
| Provider | Class | Environment | Default scopes |
|---|---|---|---|
| 42 School | FortyTwo | FORTY_TWO_* | public |
| Amazon Cognito | AmazonCognito | AMAZON_COGNITO_* | openid, profile, email |
| AniList | AniList | ANI_LIST_* | Set in the app settings |
| Apple | Apple | APPLE_* | email |
| Atlassian | Atlassian | ATLASSIAN_* | read:me |
| Auth0 | Auth0 | AUTH0_* | openid, profile, email |
| Authentik | Authentik | AUTHENTIK_* | openid, profile, email |
| Autodesk Platform Services | Autodesk | AUTODESK_* | openid, user-profile:read |
| Battle.net | BattleNet | BATTLE_NET_* | openid |
| Bitbucket | Bitbucket | BITBUCKET_* | Set in the app settings |
| Box | Box | BOX_* | Set in the app settings |
| Bungie | Bungie | BUNGIE_* | Set in the app settings |
| Coinbase | Coinbase | COINBASE_* | wallet:user:read, wallet:user:email |
| Discord | Discord | DISCORD_* | identify, email |
| DonationAlerts | DonationAlerts | DONATION_ALERTS_* | oauth-user-show |
| Dribbble | Dribbble | DRIBBBLE_* | Set in the app settings |
| Dropbox | Dropbox | DROPBOX_* | account_info.read |
| Epic Games | EpicGames | EPIC_GAMES_* | basic_profile |
| Etsy | Etsy | ETSY_* | email_r |
Facebook | FACEBOOK_* | public_profile, email | |
| Figma | Figma | FIGMA_* | current_user:read |
| Gitea | Gitea | GITEA_* | read:user |
| GitHub | GitHub | GITHUB_* | read:user, user:email |
| GitLab | GitLab | GITLAB_* | openid, profile, email |
Google | GOOGLE_* | openid, profile, email | |
| Intuit | Intuit | INTUIT_* | openid, profile, email |
| Kakao | Kakao | KAKAO_* | profile_nickname, profile_image, account_email |
| KeyCloak | KeyCloak | KEYCLOAK_* | openid, profile, email |
| Kick | Kick | KICK_* | user:read |
| Lichess | Lichess | LICHESS_* | email:read |
| Line | Line | LINE_* | openid, profile, email |
| Linear | Linear | LINEAR_* | read |
LinkedIn | LINKEDIN_* | openid, profile, email | |
| Mastodon | Mastodon | MASTODON_* | read:accounts |
| Mercado Libre | MercadoLibre | MERCADO_LIBRE_* | Set in the app settings |
| Mercado Pago | MercadoPago | MERCADO_PAGO_* | Set in the app settings |
| Microsoft Entra ID | MicrosoftEntraId | MICROSOFT_ENTRA_ID_* | openid, profile, email |
| MyAnimeList | MyAnimeList | MY_ANIME_LIST_* | Set in the app settings |
| Naver | Naver | NAVER_* | Set in the app settings |
| Notion | Notion | NOTION_* | Set in the app settings |
| Okta | Okta | OKTA_* | openid, profile, email |
| osu! | Osu | OSU_* | identify |
| Patreon | Patreon | PATREON_* | identity |
| Polar | Polar | POLAR_* | openid, profile, email |
Reddit | REDDIT_* | identity | |
| Roblox | Roblox | ROBLOX_* | openid, profile |
| Salesforce | Salesforce | SALESFORCE_* | openid, profile, email |
| Shikimori | Shikimori | SHIKIMORI_* | Set in the app settings |
| Slack (OpenID) | Slack | SLACK_* | openid, profile, email |
| Spotify | Spotify | SPOTIFY_* | user-read-email, user-read-private |
| Start.gg | StartGG | START_GG_* | user.identity, user.email |
| Strava | Strava | STRAVA_* | read |
| Synology | Synology | none | Low-level only |
| TikTok | TikTok | TIKTOK_* | user.info.basic |
| Tiltify | Tiltify | TILTIFY_* | public |
| Tumblr | Tumblr | TUMBLR_* | basic |
| Twitch | Twitch | TWITCH_* | user:read:email |
Twitter | TWITTER_* | users.read, tweet.read | |
| VK | VK | VK_* | email |
| Withings | Withings | WITHINGS_* | user.info |
| WorkOS | WorkOS | WORKOS_* | Set in the app settings |
| Yahoo | Yahoo | YAHOO_* | openid, profile, email |
| Yandex | Yandex | YANDEX_* | login:info, login:email, login:avatar |
| Zoom | Zoom | ZOOM_* | user:read:user |
Providers listed as "set in the app settings" build an authorization URL without a scope parameter, so they ignore both the scopes option and the environment variable.
42 School
OAuth 2.0 provider for 42 School.
Also see the OAuth 2.0 guide.
Initialization
FortyTwo takes a client ID, client secret, and redirect URI.
import * as arctic from "antarctic";
const fortyTwo = new arctic.FortyTwo(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["public", "projects"];
const url = fortyTwo.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. 42 School will return an access token with an expiration.
import * as arctic from "antarctic";
try {
const tokens = await fortyTwo.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessToken = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
You can retrieve user information via the /v2/me endpoint.
const response = await fetch("https://api.intra.42.fr/v2/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Amazon Cognito
OAuth 2.0 authorization code provider for Amazon Cognito.
Also see OAuth 2.0 with PKCE.
Initialization
The domain should not include the protocol or path. Pass a client secret for confidential clients.
import * as arctic from "antarctic";
const domain = "<POOL-DOMAIN>.auth.<REGION>.amazoncognito.com";
const cognito = new arctic.AmazonCognito(domain, clientId, clientSecret, redirectURI);
const cognito = new arctic.AmazonCognito(domain, clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await cognito.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Cognito returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await cognito.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode(). Cognito will only return a new access token.
import * as arctic from "antarctic";
try {
// Pass an empty `scopes` array to keep using the same scopes.
const tokens = await cognito.refreshAccessToken(refreshToken, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await cognito.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await cognito.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch(userPool + "/oauth/userInfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = await cognito.createAuthorizationURL(state, codeVerifier, scopes);Revoke refresh tokens
Pass a refresh token to revokeToken() to revoke all tokens associated with the authorization. This can throw the same errors as validateAuthorizationCode().
try {
await cognito.revokeToken(refreshToken);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Token revocation must be enabled in the settings.
AniList
OAuth 2.0 provider for AniList.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const aniList = new arctic.AniList(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const url = aniList.createAuthorizationURL(state);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. AniList will only return an access token (no expiration).
import * as arctic from "antarctic";
try {
const tokens = await aniList.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use the Viewer query to get the user object.
const query = `query {
Viewer {
id
name
}
}`;
const response = await fetch("https://graphql.anilist.co", {
method: "POST",
headers: {
Authorization: `Bearer ${tokens.accessToken}`,
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify({
query
})
});
const user = await response.json();Apple
OAuth 2.0 provider for Apple.
Also see the OAuth 2.0 guide.
Initialization
The PKCS#8 private key is an instance of Uint8Array.
import * as arctic from "antarctic";
const apple = new arctic.Apple(clientId, teamId, keyId, pkcs8PrivateKey, redirectURI);Here is an example to extract the PKCS#8 key from the PEM certificate.
const certificate = `-----BEGIN PRIVATE KEY-----
TmV2ZXIgZ29ubmEgZ2l2ZSB5b3UgdXANCk5ldmVyIGdvbm5hIGxldCB5b3UgZG93bg0KTmV2ZXIgZ29ubmEgcnVuIGFyb3VuZCBhbmQgZGVzZXJ0IHlvdQ0KTmV2ZXIgZ29ubmEgbWFrZSB5b3UgY3J5DQpOZXZlciBnb25uYSBzYXkgZ29vZGJ5ZQ0KTmV2ZXIgZ29ubmEgdGVsbCBhIGxpZSBhbmQgaHVydCB5b3U
-----END PRIVATE KEY-----`;
const base64 = certificate
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\r", "")
.replaceAll("\n", "")
.trim();
const binary = atob(base64);
const privateKey = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
privateKey[i] = binary.charCodeAt(i);
}Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["name", "email"];
const url = apple.createAuthorizationURL(state, scopes);Requesting scopes
When requesting scopes, the response_mode query parameter must be set to form_post.
const url = apple.createAuthorizationURL(state, scopes);
url.searchParams.set("response_mode", "form_post");Unlike the default "query" response mode, Apple will send an application/x-www-form-urlencoded POST request as the callback, and the user JSON object will be sent in the request body. This is only available the first time the user signs in.
Since this is a cross-origin form request, make sure to relax your CSRF protections, including setting SameSite attribute of the state cookie to None.
/callback?user=%7B%22name%22%3A%7B%22firstName%22%3A%22John%22%2C%22lastName%22%3A%22Doe%22%7D%2C%22email%22%3A%22john%40example.com%22%7D&state=STATE{ "name": { "firstName": "John", "lastName": "Doe" }, "email": "[email protected]" }Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. The ID token will always be returned regardless of the scope. T access token and refresh token currently does not have any uses.
Antarctic provides decodeIdToken() for decoding the ID token's payload.
import * as arctic from "antarctic";
try {
const tokens = await apple.validateAuthorizationCode(code);
const idToken = tokens.idToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Atlassian
OAuth 2.0 provider for Atlassian.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const atlassian = new arctic.Atlassian(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["write:jira-work", "read:jira-user"];
const url = atlassian.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Atlassian returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await atlassian.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await atlassian.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the read:me scope and use the /me endpoint.
const scopes = ["read:me"];
const url = atlassian.createAuthorizationURL(state, scopes);const response = await fetch("https://api.atlassian.com/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Auth0
OAuth 2.0 provider for Auth0.
Also see the OAuth 2.0 guide for confidential clients and the OAuth 2.0 with PKCE guide for public clients.
Initialization
The domain should not include the protocol or path. Pass the client secret for confidential clien.ts
import * as arctic from "antarctic";
const domain = "xxx.auth0.com";
const auth0 = new arctic.Auth0(domain, clientId, clientSecret, redirectURI);
const auth0 = new arctic.Auth0(domain, clientId, null, redirectURI);Create authorization URL
For confidential clients, pass the state and scopes. PKCE is not supported for confidential clients.
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["openid", "profile"];
const url = await auth0.createAuthorizationURL(state, null, scopes);For public clients, pass the state, PKCE code verifier, and scopes.
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await auth0.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
For confidential clients, pass the authorization code.
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Auth0 returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await auth0.validateAuthorizationCode(code, null);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}For public clients, pass the authorization code and code verifier.
const tokens = await auth0.validateAuthorizationCode(code, codeVerifier);Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Auth0 returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await auth0.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await auth0.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await auth0.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://xxx.auth.com/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = await auth0.createAuthorizationURL(state, codeVerifier, scopes);Revoke tokens
Revoke tokens with revokeToken(). Currently, only refresh tokens can be revoked. It throws the same errors as validateAuthorizationCode().
try {
await auth0.revokeToken(refreshToken);
} catch (e) {
// Handle errors
}Authentik
OAuth 2.0 provider for Authentik.
Also see the OAuth 2.0 with PKCE guide.
Initialization
The baseURL parameter is the full URL where the Authentik instance is hosted. Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const baseURL = "https://my-app.com/authentik";
const authentik = new arctic.Authentik(baseURL, clientId, clientSecret, redirectURI);
const authentik = new arctic.Authentik(baseURL, clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await authentik.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Actual values returned by Authentik depends on your configuration and version.
import * as arctic from "antarctic";
try {
const tokens = await authentik.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await authentik.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await authentik.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await authentik.refreshAccessToken(refreshToken);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Use revokeToken() to revoke a token. This can throw the same errors as validateAuthorizationCode().
try {
await authentik.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Autodesk Platform Services
OAuth 2.0 provider for Autodesk Platform Services.
Also see the OAuth 2.0 with PKCE guide.
Initialization
Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const autodesk = new arctic.Autodesk(clientId, clientSecret, redirectURI);
const autodesk = new arctic.Autodesk(clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "user:read", "data:read"];
const url = await autodesk.createAuthorizationURL(state, codeVerifier, scopes);The list of scopes Autodesk Platform Services supports can be found at the Developer's Guide/Scopes page.
Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Autodesk Platform Services returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await autodesk.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Autodesk Platform Services returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
// Pass an empty `scopes` array to keep using the same scopes.
const tokens = await autodesk.refreshAccessToken(refreshToken, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Use revokeToken() to revoke a token. You need to specify wether the token is an access_token or a refresh_token. This can throw the same errors as validateAuthorizationCode().
try {
await autodesk.revokeToken(token, token_type);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
See the endpoint documentation for the token claims.
const scopes = ["openid"];
const url = await autodesk.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await autodesk.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://api.userprofile.autodesk.com/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Battle.net
OAuth 2.0 provider for Battle.net.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const battlenet = new arctic.BattleNet(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["openid", "wow.profile"];
const url = battlenet.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Battle.net returns an access token and the access token expiration.
import * as arctic from "antarctic";
try {
const tokens = await battlenet.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use the User Info endpoint.
const response = await fetch("https://oauth.battle.net/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Bitbucket
OAuth 2.0 provider for Bitbucket.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const bitBucket = new arctic.Bitbucket(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const url = bitBucket.createAuthorizationURL(state);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. BitBucket returns an access token and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await bitBucket.validateAuthorizationCode(code);
// Accessing other fields will throw an error
const accessToken = tokens.accessToken();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await bitBucket.refreshAccessToken(refreshToken);
// Accessing other fields will throw an error
const accessToken = tokens.accessToken();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Enable the account scope on your account page and use the /user endpoint.
const response = await fetch("https://api.bitbucket.org/2.0/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Box
OAuth 2.0 provider for Box.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const box = new arctic.Box(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["root_readonly", "manage_managed_users"];
const url = box.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Box will only return an access token (no expiration).
import * as arctic from "antarctic";
try {
const tokens = await box.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use the /users/me endpoint.
const response = await fetch("https://api.box.com/2.0/users/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. The behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await box.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Revoke tokens with revokeToken(). Revoking a refresh token will also invalidate access tokens issued with it. It throws the same errors as validateAuthorizationCode().
try {
await box.revokeToken(token);
} catch (e) {
// Handle errors
}Bungie
OAuth 2.0 provider for Bungie. Only supports confidential clients.
Also see the OAuth 2.0 guide.
Initialization
Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const bungie = new arctic.Bungie(clientId, clientSecret, redirectURI);
const bungie = new arctic.Bungie(clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["ReadBasicUserProfile", "ReadGroups"];
const url = bungie.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError..
import * as arctic from "antarctic";
try {
const tokens = await bungie.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh tokens are only provided for confidential clients.
const tokens = await bungie.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();The refresh token expiration is returned as refresh_expires_in.
const tokens = await bungie.validateAuthorizationCode(code);
if ("refresh_expires_in" in tokens.data && typeof tokens.data.refresh_expires_in === "number") {
const refreshTokenExpiresIn = tokens.data.refresh_expires_in;
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. The behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await bungie.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the GetCurrentBungieNetUser endpoint.
const response = await fetch("https://www.bungie.net/Platform/User/GetCurrentBungieNetUser", {
headers: {
Authorization: `Bearer ${accessToken}`,
"X-API-Key": apiKey
}
});
const emails = await response.json();Coinbase
OAuth 2.0 provider for Coinbase.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const coinbase = new arctic.Coinbase(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["wallet:user:email", "wallet:accounts:read"];
const url = coinbase.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Coinbase returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await coinbase.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await coinbase.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /user endpoint.
const response = await fetch("https://api.coinbase.com/v2/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Revoke tokens
Revoke tokens with revokeToken(). This can throw the same errors as validateAuthorizationCode().
try {
await coinbase.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Discord
OAuth 2.0 provider for Discord.
Also see the OAuth 2.0 guide for confidential clients and the OAuth 2.0 with PKCE guide for public clients.
Initialization
Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const discord = new arctic.Discord(clientId, clientSecret, redirectURI);
const discord = new arctic.Discord(clientId, null, redirectURI);Create authorization URL
For confidential clients, pass the state and scopes. PKCE is not supported for confidential clients.
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["email", "activities.read"];
const url = await discord.createAuthorizationURL(state, null, scopes);For public clients, pass the state, PKCE code verifier, and scopes.
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["email", "activities.read"];
const url = await discord.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Discord returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await discord.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Discord returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await discord.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the identify scope and use the /users/@me endpoint.
const scopes = ["identify"];
const url = await discord.createAuthorizationURL(state, scopes);const response = await fetch("https://discord.com/api/users/@me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Revoke tokens
Pass a token to revokeToken() to revoke all tokens associated with the authorization. This can throw the same errors as validateAuthorizationCode().
try {
await discord.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}DonationAlerts
OAuth 2.0 provider for DonationAlerts.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const donationAlerts = new arctic.DonationAlerts(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["oauth-user-show"];
const url = donationAlerts.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. DonationAlerts returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await donationAlerts.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. DonationAlerts returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const scopes = ["oauth-user-show"];
const tokens = await donationAlerts.refreshAccessToken(refreshToken, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the oauth-user-show scope and use the /user/oauth endpoint.
const scopes = ["oauth-user-show"];
const url = donationAlerts.createAuthorizationURL(state, scopes);const response = await fetch("https://www.donationalerts.com/api/v1/user/oauth", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Dribbble
OAuth 2.0 provider for Dribbble.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const dribble = new arctic.Dribble(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["public", "upload"];
const url = dribble.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Dribble will only return an access token (no expiration).
import * as arctic from "antarctic";
try {
const tokens = await dribble.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use the /user endpoint.
const response = await fetch("https://api.dribbble.com/v2/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Dropbox
OAuth 2.0 provider for Dropbox.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const dropbox = new arctic.Dropbox(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["account_info.read", "files.content.read"];
const url = dropbox.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Dropbox returns an access token and its expiration.
import * as arctic from "antarctic";
try {
const tokens = await dropbox.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
Also see supported claims.
const scopes = ["openid"];
const url = dropbox.createAuthorizationURL(state, scopes);import * as arctic from "antarctic";
const tokens = await dropbox.validateAuthorizationCode(code);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://api.dropboxapi.com/2/openid/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = dropbox.createAuthorizationURL(state, scopes);The /users/get_current_account endpoint can also be used.
Refresh access tokens
Set the token_access_type parameter to offline to get refresh tokens.
const url = dropbox.createAuthorizationURL(state, scopes);
url.searchParams.set("token_access_type", "offline");const tokens = await dropbox.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();Use refreshAccessToken() to get a new access token using a refresh token. Dropbox will only return the access token and its expiration. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await dropbox.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Pass a token to revokeToken() to revoke all tokens associated with the authorization (in other words, both tokens will be revoked regardless of which one you passed). This can throw the same errors as validateAuthorizationCode().
try {
await dropbox.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Epic Games
OAuth 2.0 provider for Epic Games.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const epicgames = new arctic.EpicGames(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["basic_profile", "friends_list"];
const url = epicgames.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Epic returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await epicgames.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}The refresh token expiration is returned as refresh_expires and refresh_expires_at.
const tokens = await epicgames.validateAuthorizationCode(code);
if ("refresh_expires" in tokens.data && typeof tokens.data.refresh_expires === "number") {
const refreshTokenExpiresInSeconds = tokens.data.refresh_expires;
}const tokens = await epicgames.validateAuthorizationCode(code);
if ("refresh_expires_at" in tokens.data && typeof tokens.data.refresh_expires_at === "string") {
const refreshTokenExpiresAt = new Date(tokens.data.refresh_expires_at);
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Epic returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await epicgames.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the basic_profile scope and use the /v2/userInfo endpoint.
const scopes = ["basic_profile"];
const url = epic.createAuthorizationURL(state, scopes);const response = await fetch("https://api.epicgames.dev/epic/oauth/v2/userInfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Revoke tokens
Pass a token to revokeToken() to revoke all tokens associated with the authorization. This can throw the same errors as validateAuthorizationCode().
try {
await epic.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Etsy
Implements OAuth 2.0 with PKCE.
For usage, see OAuth 2.0 provider with PKCE.
Initialization
import * as arctic from "antarctic";
const etsy = new arctic.Etsy(clientId, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["listings_r", "listings_w"];
const url: URL = await etsy.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Etsy returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens: OAuth2Tokens = await etsy.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Add the shops_r and email_r scope. First use the getMe endpoint to get the user's ID.
const tokens = await etsy.validateAuthorizationCode(code, codeVerifier);
const response = await fetch("https://openapi.etsy.com/v3/application/users/me", {
headers: {
"X-Api-Key": clientId,
Authorization: `Bearer ${tokens.accessToken}`
}
});
const result = await response.json();
const userId = result.user_id;Then use the getUser endpoint with the user ID to get the user's profile.
const response = await fetch(`https://openapi.etsy.com/v3/application/users/${userId}`, {
headers: {
"X-Api-Key": clientId,
Authorization: `Bearer ${tokens.accessToken}`
}
});
const user = await response.json();OAuth 2.0 provider for Facebook.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const facebook = new arctic.Facebook(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["email", "public_profile"];
const url = facebook.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Facebook will return an access token with an expiration.
Unlike other providers, this will not throw OAuth2RequestError. Facebook's error response is not compliant with the RFC and you must manually parse the response body to get the specific error message.
import * as arctic from "antarctic";
try {
const tokens = await facebook.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.UnexpectedErrorResponseBodyError) {
// Invalid authorization code, credentials, or redirect URI
const responseBody = e.data;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use the /me endpoint. See user fields.
const searchParams = new URLSearchParams();
searchParams.set("access_token", accessToken);
searchParams.set("fields", ["id", "name", "picture", "email"].join(","));
const response = await fetch("https://graph.facebook.com/me" + "?" + searchParams.toString());
const user = await response.json();Figma
OAuth 2.0 provider for Figma.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const figma = new arctic.Figma(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["files:read", "file_variables:read"];
const url = figma.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Figma returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await figma.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Figma only returns an access token and its expiration. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await figma.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /me endpoint.
const response = await fetch("https://api.figma.com/v1/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Gitea
OAuth 2.0 provider for Gitea.
Also see OAuth 2.0 with PKCE.
Initialization
The baseURL parameter is the full URL where the Gitea instance is hosted. Use https://gitea.com for managed servers. Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const baseURL = "https://gitea.com";
const baseURL = "https://my-app.com/gitea";
const gitea = new arctic.gitea(baseURL, clientId, clientSecret, redirectURI);
const gitea = new arctic.gitea(baseURL, clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["read:user", "write:notification"];
const url = await gitea.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Gitea returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await gitea.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await gitea.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the read:user scope and use the /user endpoint.
const scopes = ["read:user"];
const url = await gitea.createAuthorizationURL(state, codeVerifier, scopes);const response = await fetch("https://gitea.com/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();GitHub
OAuth 2.0 provider for GitHub Apps and OAuth Apps.
Also see the OAuth 2.0 guide.
Initialization
The redirect URI is optional but required by GitHub if there are multiple URIs defined.
import * as arctic from "antarctic";
const github = new arctic.GitHub(clientId, clientSecret, null);
const github = new arctic.GitHub(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["user:email", "repo"];
const url = github.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. OAuth Apps will only return an access token (no expiration).
import * as arctic from "antarctic";
try {
const tokens = await github.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}If you're using GitHub Apps, GitHub will provide an expiration for the access token alongside a refresh token.
const tokens = await github.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();The refresh token expiration is returned as refresh_token_expires_in.
const tokens = await github.validateAuthorizationCode(code);
if (
"refresh_token_expires_in" in tokens.data &&
typeof tokens.data.refresh_token_expires_in === "number"
) {
const refreshTokenExpiresIn = tokens.data.refresh_token_expires_in;
}Refresh access tokens
For GitHub Apps, use refreshAccessToken() to get a new access token using a refresh token. The behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await github.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /user endpoint.
const response = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user email
Add the email scope and use the /user/emails endpoint.
const scopes = ["user:email"];
const url = github.createAuthorizationURL(state, scopes);const response = await fetch("https://api.github.com/user/emails", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const emails = await response.json();GitLab
OAuth 2.0 provider for GitLab.
Also see the OAuth 2.0 guide.
Initialization
The baseURL parameter is the full URL where the GitLab instance is hosted. Use https://gitlab.com for managed servers. Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const baseURL = "https://gitlab.com";
const baseURL = "https://my-app.com/gitlab";
const gitlab = new arctic.GitLab(baseURL, clientId, clientSecret, redirectURI);
const gitlab = new arctic.GitLab(baseURL, clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["read_user", "profile"];
const url = gitlab.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. GitLab returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await gitlab.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await gitlab.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the read_user scope and use the /user endpoint.
const scopes = ["read_user"];
const url = gitlab.createAuthorizationURL(state, scopes);const response = await fetch("https://gitlab.com/api/v4/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Revoke tokens
Use revokeToken() to revoke a token. This can throw the same errors as validateAuthorizationCode().
try {
await gitlab.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OAuth 2.0 authorization code provider for Google. Only supports confidential clients.
Also see OAuth 2.0 with PKCE.
Initialization
import * as arctic from "antarctic";
const google = new arctic.Google(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await google.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Google will return an access token with an expiration.
import * as arctic from "antarctic";
try {
const tokens = await google.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}The refresh token expiration is returned as refresh_token_expires_in.
const tokens = await google.validateAuthorizationCode(code);
if (
"refresh_token_expires_in" in tokens.data &&
typeof tokens.data.refresh_token_expires_in === "number"
) {
const refreshTokenExpiresIn = tokens.data.refresh_token_expires_in;
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
Also see ID token claims.
const scopes = ["openid"];
const url = await google.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await google.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://openidconnect.googleapis.com/v1/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = await google.createAuthorizationURL(state, codeVerifier, scopes);Refresh tokens
Set the access_type parameter to offline to get refresh tokens. You will only get the refresh token on the user's first authentication.
const url = await google.createAuthorizationURL(state, codeVerifier, scopes);
url.searchParams.set("access_type", "offline");const tokens = await google.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
if (tokens.hasRefreshToken()) {
const refreshToken = tokens.refreshToken();
}Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode(). Google will not provide a new refresh token after a token refresh.
import * as arctic from "antarctic";
try {
const tokens = await google.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Revoke tokens with revokeToken(). This can throw the same errors as validateAuthorizationCode().
try {
await google.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Intuit
OAuth 2.0 provider for Intuit.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const intuit = new arctic.Intuit(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["email", "activities.read"];
const url = intuit.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Intuit returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await intuit.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}The refresh token expiration is returned as x_refresh_token_expires_in.
const tokens = await intuit.validateAuthorizationCode(code);
if (
"x_refresh_token_expires_in" in tokens.data &&
typeof tokens.data.x_refresh_token_expires_in === "number"
) {
const refreshTokenExpiresIn = tokens.data.x_refresh_token_expires_in;
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
Also see ID token claims.
const scopes = ["openid"];
const url = intuit.createAuthorizationURL(state, scopes);import * as arctic from "antarctic";
const tokens = await intuit.validateAuthorizationCode(code);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://accounts.platform.intuit.com/v1/openid_connect/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = intuit.createAuthorizationURL(state, scopes);Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. The returned values are the same as authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await intuit.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Use revokeToken() to revoke a token. This can throw the same errors as validateAuthorizationCode().
try {
await intuit.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Kakao
OAuth 2.0 provider for Kakao.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const kakao = new arctic.Kakao(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["account_email", "profile"];
const url = kakao.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Kakao returns an access token, its expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await kakao.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}The refresh token expiration is returned as refresh_token_expires_in.
const tokens = await kakao.validateAuthorizationCode(code);
if (
"refresh_token_expires_in" in tokens.data &&
typeof tokens.data.refresh_token_expires_in === "number"
) {
const refreshTokenExpiresIn = tokens.data.refresh_token_expires_in;
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Kakao returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await kakao.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /user/me endpoint.
const response = await fetch("https://kapi.kakao.com/v2/user/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();KeyCloak
OAuth 2.0 provider for KeyCloak.
Also see the OAuth 2.0 with PKCE guide.
Initialization
Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const realmURL = "https://auth.example.com/realms/myrealm";
const keycloak = new arctic.KeyCloak(realmURL, clientId, clientSecret, redirectURI);
const keycloak = new arctic.KeyCloak(realmURL, clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await keycloak.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Actual values returned by KeyCloak depends on your configuration and version.
import * as arctic from "antarctic";
try {
const tokens = await keycloak.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}The refresh token expiration is returned as refresh_expires_in.
const tokens = await keycloak.validateAuthorizationCode(code);
if ("refresh_expires_in" in tokens.data && typeof tokens.data.refresh_expires_in === "number") {
const refreshTokenExpiresIn = tokens.data.refresh_expires_in;
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await keycloak.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await keycloak.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await keycloak.refreshAccessToken(refreshToken);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Use revokeToken() to revoke a token. This can throw the same errors as validateAuthorizationCode().
try {
await keycloak.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Kick
OAuth 2.0 provider for Kick.
Also see the OAuth 2.0 with PKCE guide.
Initialization
import * as arctic from "antarctic";
const kick = new arctic.Kick(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["user:read"];
const url = await kick.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Kick returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await kick.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Kick returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await kick.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the user:read scope when creating the authorization URL.
const scopes = ["user:read"];
const url = await kick.createAuthorizationURL(state, codeVerifier, scopes);Then make a request to the Kick REST API with the access token.
const tokens = await kick.validateAuthorizationCode(code, codeVerifier);
const response = await fetch("https://api.kick.com/public/v1/users", {
headers: {
Authorization: `Bearer ${tokens.accessToken()}`
}
});
const user = await response.json();Revoke tokens
Pass a token to revokeToken() to revoke all tokens associated with the authorization. This can throw the same errors as validateAuthorizationCode().
try {
await kick.revokeToken(refreshToken);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Lichess
OAuth 2.0 provider for Lichess.
Also see the OAuth 2.0 with PKCE guide.
Initialization
import * as arctic from "antarctic";
const lichess = new arctic.Lichess(clientId, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["challenge:read", "challenge:write"];
const url = await lichess.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Lichess returns an access token and its expiration.
import * as arctic from "antarctic";
try {
const tokens = await lichess.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use the /api/account endpoint
const lichessUserResponse = await fetch("https://lichess.org/api/account", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await lichessUserResponse.json();Get user email
Add the email:read scope and use the /api/account/email endpoint
const scopes = ["email:read"];
const url = await lichess.createAuthorizationURL(state, codeVerifier, scopes);const response = await fetch("https://lichess.org/api/account/email", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const email = await response.json();Line
OAuth 2.0 provider for Line.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const line = new arctic.Line(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await line.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Line returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await line.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Line only returns a new access token and its expiration. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await line.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await line.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await line.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://api.line.me/oauth2/v2.1/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = await line.createAuthorizationURL(state, codeVerifier, scopes);Or, alternatively use the /profile endpoint.
Linear
OAuth 2.0 provider for Linear.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const linear = new arctic.Linear(clientId, clientSecret, redirectURI);Create authorization URL
The read scope must always be included.
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["read", "write"];
const url = linear.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Linear will return an access token with an expiration.
import * as arctic from "antarctic";
try {
const tokens = await linear.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use Linear's GraphQL API.
const response = await fetch("https://api.linear.app/graphql", {
method: "POST",
body: `{ "query": "{ viewer { id name } }" }`,
headers: {
"Content-Type": "application/json"
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();OAuth 2.0 provider for LinkedIn.
Also see the OAuth 2.0 guide.
Initialization
The domain should not include the protocol or path.
import * as arctic from "antarctic";
const linkedin = new arctic.LinkedIn(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["openid", "profile"];
const url = linkedin.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. LinkedIn returns an access token, its expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await linkedin.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. LinkedIn returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await linkedin.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}The refresh token expiration is returned as refresh_token_expires_in.
const tokens = await linkedin.validateAuthorizationCode(code);
if (
"refresh_token_expires_in" in tokens.data &&
typeof tokens.data.refresh_token_expires_in === "number"
) {
const refreshTokenExpiresIn = tokens.data.refresh_token_expires_in;
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = linkedin.createAuthorizationURL(state, scopes);import * as arctic from "antarctic";
const tokens = await linkedin.validateAuthorizationCode(code);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://api.linkedin.com/v2/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = linkedin.createAuthorizationURL(state, scopes);Mastodon
OAuth 2.0 provider for Mastodon.
Also see the OAuth 2.0 with PKCE guide.
Initialization
The baseURL parameter is the full URL where the Mastodon instance is hosted.
import * as arctic from "antarctic";
const baseURL = "https://mastodon.social";
const mastodon = new arctic.Mastodon(baseURL, clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["read", "write"];
const url = await mastodon.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Mastodon will only return an access token (no expiration).
import * as arctic from "antarctic";
try {
const tokens = await mastodon.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Revoke tokens
Use revokeToken() to revoke a token. This can throw the same errors as validateAuthorizationCode().
try {
await mastodon.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Mercado Libre
OAuth 2.0 provider for Mercado Libre. This client requires PKCE to be enabled in your application settings.
Also see the OAuth 2.0 with PKCE guide.
Initialization
import * as arctic from "antarctic";
const mercadolibre = new arctic.MercadoLibre(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const url = await mercadolibre.createAuthorizationURL(state);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Mercado Libre returns an access token, its expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await mercadolibre.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Add the offline_access scope to get a refresh token.
const tokens = await mercadolibre.validateAuthorizationCode(code, codeVerifier);
const refreshToken = tokens.refreshToken();Use refreshAccessToken() to get a new access token using a refresh token. Mercado Libre returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await mercadolibre.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /users/me endpoint.
const response = await fetch("https://api.mercadolibre.com/users/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Mercado Pago
OAuth 2.0 provider for Mercado Pago. This client requires PKCE to be enabled in your application settings.
Also see the OAuth 2.0 with PKCE guide.
Initialization
import * as arctic from "antarctic";
const mercadopago = new arctic.MercadoPago(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const url = await mercadopago.createAuthorizationURL(state);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Mercado Pago returns an access token and its expiration by default.
import * as arctic from "antarctic";
try {
const tokens = await mercadopago.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh tokens
Add the offline_access scope to get a refresh token.
const tokens = await mercadopago.validateAuthorizationCode(code, codeVerifier);
const refreshToken = tokens.refreshToken();Use refreshAccessToken() to get a new access token using a refresh token. Mercado Pago returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await mercadopago.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Microsoft Entra ID
OAuth 2.0 provider for Microsoft Entra ID.
Also see the OAuth 2.0 guide.
Initialization
See Endpoints for more on the tenant parameter. Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const entraId = new arctic.MicrosoftEntraId(tenant, clientId, clientSecret, redirectURI);
const entraId = new arctic.MicrosoftEntraId(tenant, clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await entraId.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Entra ID returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await entraId.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Entra ID returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
// Pass an empty `scopes` array to keep using the same scopes.
const tokens = await entraId.refreshAccessToken(refreshToken, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. The nonce parameter is required by Entra ID to use OpenID. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await entraId.createAuthorizationURL(state, codeVerifier, scopes);
// The nonce should be unique to each request similar to state.
// However, nonce can just be "_" here since it isn't useful for server-based OAuth.
url.searchParams.set("nonce", nonce);import * as arctic from "antarctic";
const tokens = await entraId.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://graph.microsoft.com/oidc/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = await entraId.createAuthorizationURL(state, codeVerifier, scopes);MyAnimeList
OAuth 2.0 provider for MyAnimeList.
Also see the OAuth 2.0 guide.
Initialization
The redirect URI is optional.
import * as arctic from "antarctic";
const mal = new arctic.MyAnimeList(clientId, clientSecret, null);
const mal = new arctic.MyAnimeList(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const url = await mal.createAuthorizationURL(state, codeVerifier);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. MyAnimeList returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await mal.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. MyAnimeList returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await mal.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /users endpoint.
const response = await fetch("https://api.myanimelist.net/v2/users/@me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Naver
OAuth 2.0 provider for Naver.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const naver = new arctic.Naver(clientId, clientSecret, redirectURI);Create authorization URL
const url = naver.createAuthorizationURL();Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Naver returns an access token and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await naver.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}It also returns the access token expiration, but does so in a non-RFC compliant manner. This is a known issue with Naver.
const tokens = await bungie.validateAuthorizationCode(code);
// Should be returned as a number per RFC 6749, but returns it as a string.
if ("expires_in" in tokens.data && typeof tokens.data.expires_in === "string") {
const accessTokenExpiresIn = Number(tokens.data.expires_in);
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Naver returns the same values as during the authorization code validation, including the access token expiration which needs to be manually parsed out. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await naver.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /v1/nid/me endpoint.
const response = await fetch("https://openapi.naver.com/v1/nid/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Notion
OAuth 2.0 provider for Notion.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const notion = new arctic.Notion(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const url = notion.createAuthorizationURL(state);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Notion will only return an access token (no expiration).
import * as arctic from "antarctic";
try {
const tokens = await notion.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use the /users/me endpoint.
const response = await fetch("https://api.notion.com/v1/users/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Okta
OAuth 2.0 provider for Okta.
Also see the OAuth 2.0 guide.
Initialization
The domain parameter should not include the protocol or path. The authorizationServerId parameter is optional.
import * as arctic from "antarctic";
const domain = "auth.example.com";
const okta = new arctic.Okta(domain, null, clientId, clientSecret, redirectURI);
const okta = new arctic.Okta(domain, authorizationServerId, clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await okta.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Actual values returned by Okta depends on your configuration.
import * as arctic from "antarctic";
try {
const tokens = await okta.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Okta requires you to pass scopes when refreshing tokens. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
// Pass an empty `scopes` array to keep using the same scopes.
const tokens = await okta.refreshAccessToken(refreshToken, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Use revokeToken() to revoke a token. This can throw the same errors as validateAuthorizationCode().
try {
await okta.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}osu!
OAuth 2.0 provider for osu!
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const osu = new arctic.Osu(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["public", "friends.read"];
const url = osu.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. osu! returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await osu.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. osu! returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await osu.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /me endpoint.
const response = await fetch("https://osu.ppy.sh/api/v2/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Patreon
OAuth 2.0 provider for Patreon.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const patreon = new arctic.Patreon(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["identity", "identity[email]"];
const url = patreon.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Patreon returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await patreon.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Patreon returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await patreon.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the identity scope and use the /api/oauth2/v2/identity endpoint. Optionally add the identity[email] scope to get user email.
const scopes = ["identity", "identity[email]"];
const url = patreon.createAuthorizationURL(state, scopes);const response = await fetch("https://www.patreon.com/api/oauth2/v2/identity", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Polar
OAuth 2.0 authorization code provider for Polar. Only supports confidential clients.
Also see OAuth 2.0 with PKCE.
Initialization
import * as arctic from "antarctic";
const polar = new arctic.Polar(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await polar.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Polar returns an access token, its expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await polar.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await polar.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await polar.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://docs.polar.sh/api/v1/oauth2/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = await polar.createAuthorizationURL(state, codeVerifier, scopes);Refresh tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await polar.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Revoke tokens with revokeToken(). This can throw the same errors as validateAuthorizationCode().
try {
await polar.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OAuth 2.0 provider for Reddit.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const patreon = new arctic.Reddit(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["edit", "read"];
const url = reddit.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Reddit returns an access token and its expiration.
import * as arctic from "antarctic";
try {
const tokens = await reddit.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Set the duration parameter to permanent to get refresh tokens.
const url = reddit.createAuthorizationURL(state, scopes);
url.searchParams.set("duration", "permanent");const tokens = await reddit.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();Use refreshAccessToken() to get a new access token using a refresh token. Reddit returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await reddit.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /me endpoint.
const response = await fetch("https://oauth.reddit.com/api/v1/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Roblox
OAuth 2.0 provider for Roblox.
Also see the OAuth 2.0 with PKCE guide.
Initialization
Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const roblox = new arctic.Roblox(clientId, clientSecret, redirectURI);
const roblox = new arctic.Roblox(clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await roblox.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Roblox returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await roblox.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Roblox returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await roblox.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await roblox.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await roblox.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://apis.roblox.com/oauth/v1/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile. The Roblox API does not provide an email address.
const scopes = ["openid", "profile"];
const url = await roblox.createAuthorizationURL(state, codeVerifier, scopes);Revoke tokens
Pass a token to revokeToken() to revoke all tokens associated with the authorization. This can throw the same errors as validateAuthorizationCode().
try {
await roblox.revokeToken(refreshToken);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Salesforce
OAuth 2.0 provider for Salesforce.
Also see the OAuth 2.0 with PKCE guide.
Initialization
The domain parameter should not include paths or protocol. Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const domain = "login.salesforce.com";
const salesforce = new arctic.Salesforce(domain, clientId, clientSecret, redirectURI);
const salesforce = new arctic.Salesforce(domain, clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["openid", "profile"];
const url = await salesforce.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Salesforce only returns an access token.
import * as arctic from "antarctic";
try {
const tokens = await salesforce.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Add the refresh_token scope to get refresh tokens.
const scopes = ["refresh_token"];
const url = await salesforce.createAuthorizationURL(state, codeVerifier, scopes);const tokens = await salesforce.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const refreshToken = tokens.refreshToken();Use refreshAccessToken() to get a new access token using a refresh token. Salesforce only returns an access token. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await salesforce.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = await salesforce.createAuthorizationURL(state, codeVerifier, scopes);import * as arctic from "antarctic";
const tokens = await salesforce.validateAuthorizationCode(code, codeVerifier);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://login.salesforce.com/services/oauth2/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = await salesforce.createAuthorizationURL(state, codeVerifier, scopes);Revoke tokens
Revoke tokens with revokeToken(). This can throw the same errors as validateAuthorizationCode().
try {
await salesforce.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Shikimori
OAuth 2.0 provider for Shikimori.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const shikimori = new arctic.Shikimori(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const url = shikimori.createAuthorizationURL(state);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Shikimori returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await shikimori.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Shikimori returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await shikimori.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
const response = await fetch("https://shikimori.one/api/users/whoami", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Slack (OpenID)
OAuth 2.0 provider for Slack (OpenID Connect).
Also see the OAuth 2.0 guide.
Initialization
The redirect URI is optional.
import * as arctic from "antarctic";
const slack = new arctic.Slack(clientId, clientSecret, null);
const slack = new arctic.Slack(clientId, clientSecret, redirectURI);Create authorization URL
The openid scope is required.
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["openid", "profile"];
const url = slack.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Slack will return an access token (no expiration) and an ID token.
import * as arctic from "antarctic";
try {
const tokens = await slack.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const idToken = tokens.idToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Decode the ID token or the userinfo endpoint to get the user profile. Antarctic provides decodeIdToken() for decoding the token's payload.
import * as arctic from "antarctic";
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://openidconnect.googleapis.com/v1/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = slack.createAuthorizationURL(state, codeVerifier, scopes);Spotify
OAuth 2.0 provider for Spotify.
Also see the OAuth 2.0 guide.
Initialization
Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const spotify = new arctic.Spotify(clientId, clientSecret, redirectURI);
const spotify = new arctic.Spotify(clientId, null, redirectURI);Create authorization URL
For confidential clients, pass the state and scopes. PKCE is not supported for confidential clients.
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["user-read-email", "user-read-private"];
const url = await spotify.createAuthorizationURL(state, null, scopes);For public clients, pass the state, PKCE code verifier, and scopes.
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["user-read-email", "user-read-private"];
const url = await spotify.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
For confidential clients, pass the authorization code.
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Spotify returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await spotify.validateAuthorizationCode(code, null);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}For public clients, pass the authorization code and code verifier.
const tokens = await spotify.validateAuthorizationCode(code, codeVerifier);Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Spotify returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await spotify.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /users/me endpoint. The user-read-email scope is required to get the user's email.
const response = await fetch("https://api.spotify.com/v1/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Start.gg
OAuth 2.0 provider for Start.gg.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const startgg = new arctic.StartGG(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["user.identity", "user.email"];
const url = startgg.createAuthorizationURL(state, scopes);Validate authorization code
Start.gg requires a list of scopes in addition to the authorization code. validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Start.gg returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await startgg.validateAuthorizationCode(code, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Start.gg returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
// Pass an empty `scopes` array to keep using the same scopes.
const tokens = await startgg.refreshAccessToken(refreshToken, scopes);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the user.identity scope and optionally the user.email to get the user email. See the Start.gg Schema.
const response = await fetch("https://api.start.gg/gql/alpha", {
method: "POST",
body: `{"query": "{ currentUser {id slug email player { gamerTag } } }" }`,
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${accessToken}`
}
});
const result = await response.json();Strava
OAuth 2.0 provider for Strava.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const strava = new arctic.Strava(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["activity:write", "read"];
const url = strava.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Strava returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await strava.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Strava returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await strava.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the read scope and use the /athlete endpoint. Alternatively, use the read_all scope to get all private data.
const scopes = ["read"];
const url = strava.createAuthorizationURL(state, scopes);const response = await fetch("https://www.strava.com/api/v3/athlete", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Synology
OAuth 2.0 provider for Synology SSO and OAuth Apps.
Also see the OAuth 2.0 with PKCE guide.
Prerequisites
To use this provider, you have to install SSO Server package on your Synology NAS.
There you have to:
- Configure the base URL under which the SSO Server will be reachable
- Enable the OIDC service
- Create a new OAuth App
Note: Both the base URL and the redirect URI have to use
https.
Initialization
The baseURL parameter is the full URL of your Synology NAS that you have configured in the SSO Server.
import * as arctic from "antarctic";
const baseURL = "https://my_synology_nas.local:5001";
const baseURL = "https://sso.nas.example.com";
const synology = new arctic.Synology(baseUrl, applicationId, applicationSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["email", "groups", "openid"];
const url = await synology.createAuthorizationURL(state, codeVerifier, scopes);Note: You can find all available scopes in
/webman/sso/.well-known/openid-configuration
Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError.
Synology returns an access token and the access token expiration.
import * as arctic from "antarctic";
try {
const tokens = await synology.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user info
Use the /webman/sso/SSOUserInfo.cgi endpoint.
const user_info = await fetch("https://example.com/webman/sso/SSOUserInfo.cgi", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();TikTok
OAuth 2.0 authorization code provider for TikTok.
Also see OAuth 2.0 with PKCE.
Initialization
import * as arctic from "antarctic";
const tiktok = new arctic.TikTok(clientKey, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["user.info.basic", "video.list"];
const url = await tiktok.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. TikTok returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await tiktok.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}The refresh token expiration is returned as refresh_expires_in.
const tokens = await tiktok.validateAuthorizationCode(code);
if ("refresh_expires_in" in tokens.data && typeof tokens.data.refresh_expires_in === "number") {
const refreshTokenExpiresIn = tokens.data.refresh_expires_in;
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. This method's behavior is identical to validateAuthorizationCode().
import * as arctic from "antarctic";
try {
const tokens = await tiktok.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Pass a token to revokeToken() to revoke a token. This can throw the same errors as validateAuthorizationCode().
try {
await tiktok.revokeToken(refreshToken);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Token revocation must be enabled in the settings.
Tiltify
OAuth 2.0 provider for Tiltify.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const tiltify = new arctic.Tiltify(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["activity:write", "read"];
const url = tiltify.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Tiltify returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await tiltify.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Tiltify returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await tiltify.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /api/public/current-use endpoint without passing any arguments.
const response = await fetch("https://v5api.tiltify.com/api/public/current-user", {
headers: {
Authorization: `Bearer ${accessToken}`,
"Client-Id": clientId
}
});
const user = await response.json();Tumblr
OAuth 2.0 provider for Tumblr.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const patreon = new arctic.Tumblr(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["basic", "write"];
const url = tumblr.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Tumblr returns an access token and its expiration.
import * as arctic from "antarctic";
try {
const tokens = await tumblr.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Add the offline_access scope to get refresh tokens.
const scopes = ["offline_access"];
const url = tumblr.createAuthorizationURL(state, scopes);const tokens = await tumblr.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();Use refreshAccessToken() to get a new access token using a refresh token. Tumblr returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await tumblr.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /user/info endpoint.
const response = await fetch("https://api.tumblr.com/v2/user/info", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Twitch
OAuth 2.0 provider for Twitch.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const twitch = new arctic.Twitch(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["activity:write", "read"];
const url = twitch.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Twitch returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await twitch.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
Also see ID token claims.
const scopes = ["openid"];
const url = twitch.createAuthorizationURL(state, scopes);import * as arctic from "antarctic";
const tokens = await twitch.validateAuthorizationCode(code);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://id.twitch.tv/oauth2/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Twitch returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await twitch.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /users endpoint without passing any arguments. The user:read:email scope is required to get the user's email from the endpoint.
const response = await fetch("https://api.twitch.tv/helix/users", {
headers: {
Authorization: `Bearer ${accessToken}`,
"Client-Id": clientId
}
});
const user = await response.json();OAuth 2.0 provider for Twitter API v2.
Also see the OAuth 2.0 with PKCE guide.
Initialization
Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const twitter = new arctic.Twitter(clientId, clientSecret, redirectURI);
const twitter = new arctic.Twitter(clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["account_info.read", "files.content.read"];
const url = await twitter.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Twitter returns an access token and its expiration.
import * as arctic from "antarctic";
try {
const tokens = await twitter.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Add the users.read and tweet.read scopes and use the /users/me endpoint. You cannot get user emails with the v2 API.
const scopes = ["users.read", "tweet.read"];
const url = await twitter.createAuthorizationURL(state, codeVerifier, scopes);const response = await fetch("https://api.twitter.com/2/users/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Refresh access tokens
Add the offline.access scope to get refresh tokens.
const scopes = ["offline.access"];
const url = await twitter.createAuthorizationURL(state, codeVerifier, scopes);const tokens = await twitter.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();Use refreshAccessToken() to get a new access token using a refresh token. Twitter returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await twitter.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Revoke tokens
Use revokeToken() to revoke a token. This can throw the same errors as validateAuthorizationCode().
try {
await twitter.revokeToken(refreshToken);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}VK
OAuth 2.0 provider for VK.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const vk = new arctic.VK(clientId, clientSecret, redirectURI);Create authorization URL
Optionally use the offline scope to get access tokens with no expiration.
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["email", "messages", "offline"];
const url = vk.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. VK will return an access token.
import * as arctic from "antarctic";
try {
const tokens = await vk.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
// Only if `offline` scope is not used.
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get user profile
Use the users.get endpoint.
const response = await fetch("https://api.vk.com/method/users.get", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Withings
OAuth 2.0 provider for Withings.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const withings = new arctic.Withings(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["user.info", "user.metrics", "user.activity"];
const url = withings.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Withings will return an access token with an expiration.
Withings deviates from the RFC and the value of OAuth2RequestError.code will not be a registered OAuth 2.0 error code.
import * as arctic from "antarctic";
try {
const tokens = await withings.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const responseBody = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Get measures
Use the /measure endpoint. See the API docs.
const response = await fetch("https://wbsapi.withings.net/measure", {
method: "POST",
headers: {
Authorization: `Bearer ${tokens.accessToken()}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
action: "getmeas",
meastypes: "1,5,6,8,76",
category: 1,
lastupdate: 1746082800
})
});
const measures = await response.json();WorkOS
OAuth 2.0 provider for WorkOS.
Also see the OAuth 2.0 guide.
Initialization
Pass the client secret for confidential clients.
import * as arctic from "antarctic";
const workos = new arctic.WorkOS(clientId, clientSecret, redirectURI);
const workos = new arctic.WorkOS(clientId, null, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const url = await workos.createAuthorizationURL(state);Validate authorization code
For confidential clients, pass the authorization code.
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. WorkOS will only return an access token (no expiration).
import * as arctic from "antarctic";
try {
const tokens = await workos.validateAuthorizationCode(code, null);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}For public clients, pass the authorization code and code verifier.
const tokens = await workos.validateAuthorizationCode(code, codeVerifier);Get user profile
The profile is included in the token response.
const tokens = await workos.validateAuthorizationCode(code);
if (
"profile" in tokens.data &&
typeof tokens.data.profile === "object" &&
tokens.data.profile !== null
) {
const profile = tokens.data.profile;
}Yahoo
OAuth 2.0 provider for Yahoo.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const yahoo = new arctic.Yahoo(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["openid", "profile"];
const url = yahoo.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Yahoo returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await yahoo.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Yahoo returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await yahoo.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}OpenID Connect
Use OpenID Connect with the openid scope to get the user's profile with an ID token or the userinfo endpoint. Antarctic provides decodeIdToken() for decoding the token's payload.
const scopes = ["openid"];
const url = yahoo.createAuthorizationURL(state, scopes);import * as arctic from "antarctic";
const tokens = await yahoo.validateAuthorizationCode(code);
const idToken = tokens.idToken();
const claims = arctic.decodeIdToken(idToken);const response = await fetch("https://api.login.yahoo.com/openid/v1/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Get user profile
Make sure to add the profile scope to get the user profile and the email scope to get the user email.
const scopes = ["openid", "profile", "email"];
const url = yahoo.createAuthorizationURL(state, scopes);Yandex
OAuth 2.0 provider for Yandex.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const yandex = new arctic.Yandex(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const scopes = ["activity:write", "read"];
const url = yandex.createAuthorizationURL(state, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Yandex returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await yandex.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Yandex returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await yandex.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Use the /myself endpoint.
const response = await fetch("https://api.tracker.yandex.net/v2/myself", {
headers: {
Authorization: `OAuth ${accessToken}`,
"X-Org-ID": ORGANIZATION_ID
}
});
const user = await response.json();Zoom
OAuth 2.0 provider for Zoom.
Also see the OAuth 2.0 guide.
Initialization
import * as arctic from "antarctic";
const zoom = new arctic.Zoom(clientId, clientSecret, redirectURI);Create authorization URL
import * as arctic from "antarctic";
const state = arctic.generateState();
const codeVerifier = arctic.generateCodeVerifier();
const scopes = ["user:read:email"];
const url = await zoom.createAuthorizationURL(state, codeVerifier, scopes);Validate authorization code
validateAuthorizationCode() will either return an OAuth2Tokens, or throw one of OAuth2RequestError, ArcticFetchError, UnexpectedResponseError, or UnexpectedErrorResponseBodyError. Zoom returns an access token, the access token expiration, and a refresh token.
import * as arctic from "antarctic";
try {
const tokens = await zoom.validateAuthorizationCode(code, codeVerifier);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}Refresh access tokens
Use refreshAccessToken() to get a new access token using a refresh token. Zoom returns the same values as during the authorization code validation. This method also returns OAuth2Tokens and throws the same errors as validateAuthorizationCode()
import * as arctic from "antarctic";
try {
const tokens = await zoom.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}Get user profile
Add the user:read scope in the app settings and use the /users/me endpoint.
const response = await fetch("https://api.zoom.us/v2/users/me", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();Revoke tokens
Revoke tokens with revokeToken(). This can throw the same errors as validateAuthorizationCode().
try {
await zoom.revokeToken(token);
} catch (e) {
if (e instanceof arctic.OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof arctic.ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}