diff --git a/.github/ISSUE_TEMPLATE/2_bug_provider.yml b/.github/ISSUE_TEMPLATE/2_bug_provider.yml index 1ee4409a23..5490fd3e77 100644 --- a/.github/ISSUE_TEMPLATE/2_bug_provider.yml +++ b/.github/ISSUE_TEMPLATE/2_bug_provider.yml @@ -101,6 +101,7 @@ body: - "Webex" - "Wordpress" - "WorkOS" + - "Wca" - "Yandex" - "Zoho" - "Zoom" diff --git a/packages/core/src/providers/wca.ts b/packages/core/src/providers/wca.ts new file mode 100644 index 0000000000..69710c0f7a --- /dev/null +++ b/packages/core/src/providers/wca.ts @@ -0,0 +1,144 @@ +/** + *
+ * Built-in World Cube Association integration. + * + * + * + *
+ * + * @module providers/wca + */ + +import type { OAuthConfig, OAuthUserConfig } from "./index.js" + +/** @see [Get the authenticated user](https://www.worldcubeassociation.org/help/api) */ +export interface WCAProfile { + me: { + id: number + created_at: string + updated_at: string + name: string + wca_id: string | null + gender: string + country_iso2: string + url: string + country: { + id: string + name: string + continent_id: string + iso2: string + } + delegate_status: string | null + class: string + teams: any[] + avatar: { + id: number | null + status: string + thumbnail_crop_x: number + thumbnail_crop_y: number + thumbnail_crop_w: number + thumbnail_crop_h: number + url: string + thumb_url: string + is_default: boolean + can_edit_thumbnail: boolean + } + email: string + } +} + +/** + * Add WCA login to your page and make requests to [WCA APIs](https://www.worldcubeassociation.org/api). + * + * ### Setup + * + * #### Callback URL + * ``` + * https://example.com/api/auth/callback/wca + * ``` + * + * #### Configuration + * ```ts + * import { Auth } from "@auth/core" + * import Wca from "@auth/core/providers/wca" + * + * const request = new Request(origin) + * const response = await Auth(request, { + * providers: [ + * Wca({ clientId: WCA_CLIENT_ID, clientSecret: WCA_CLIENT_SECRET }), + * ], + * }) + * ``` + * + * ### Resources + * + * - [WCA API docs](https://www.worldcubeassociation.org/help/api) + * - [WCA OAuth overview](https://www.worldcubeassociation.org/api#oauth) + * - [Create/Manage WCA OAuth Apps](https://www.worldcubeassociation.org/oauth/applications) + * - [Learn more about OAuth](https://authjs.dev/concepts/oauth) + * - [Source code](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/wca.ts) + * + * ### Notes + * + * By default, Auth.js assumes that the WCA provider is + * based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification. + * + * :::tip + * + * The WCA provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/wca.ts). + * To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/configuring-oauth-providers). + * + * ::: + * + * :::info **Disclaimer** + * + * If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue). + * + * Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from + * the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec, + * we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions). + * + * ::: + */ +export default function Wca( + config: OAuthUserConfig +): OAuthConfig { + const apiBaseUrl = "https://www.worldcubeassociation.org" + return { + id: "wca", + name: "World Cube Association", + type: "oauth", + authorization: { + url: `${apiBaseUrl}/oauth/authorize`, + params: { scope: "public" }, + }, + token: `${apiBaseUrl}/oauth/token`, + userinfo: { + url: `${apiBaseUrl}/api/v0/me`, + async request({ tokens }) { + const profile = await fetch(`${apiBaseUrl}/api/v0/me`, { + headers: { + Authorization: `Bearer ${tokens.access_token}`, + "User-Agent": "authjs", + }, + }) + + return await profile.json() + }, + }, + profile(profile) { + const { id, name, avatar, email, wca_id, country, gender } = profile.me + return { + id: id.toString(), + name, + email, + image: avatar.url, + wcaId: wca_id, + country, + gender, + } + }, + style: { bg: "#24292f", text: "#fff" }, + options: config, + } +}