diff --git a/dist/bundle.d.ts b/dist/bundle.d.ts index 72f55d0751..61b987eae4 100644 --- a/dist/bundle.d.ts +++ b/dist/bundle.d.ts @@ -3853,9 +3853,10 @@ export interface BaseOAuthAuthentication extends BaseAuthentication { tokenQueryParam?: string; } /** - * Authenticate using OAuth2. You must specify the authorization URL, token exchange URL, and - * scopes here as part of the pack definition. You'll provide the application's client ID and - * client secret in the pack management UI, so that these can be stored securely. + * Authenticate using the OAuth2 Authorization Code flow. You must specify the authorization URL, + * token exchange URL, and scopes here as part of the pack definition. You'll provide the + * application's client ID and client secret in the pack management UI, so that these can be stored + * securely. * * The API must use a (largely) standards-compliant implementation of OAuth2. * @@ -3915,7 +3916,7 @@ export interface OAuth2Authentication extends BaseOAuthAuthentication { pkceChallengeMethod?: "plain" | "S256"; } /** - * Authenticate using OAuth2 client credentials. + * Authenticate using the OAuth2 Client Credentials flow. * You must specify the token exchange URL here as part of the pack definition. * You'll provide the application's client ID and client secret when authenticating. * diff --git a/dist/types.d.ts b/dist/types.d.ts index b0c4220066..fee7a13b22 100644 --- a/dist/types.d.ts +++ b/dist/types.d.ts @@ -501,9 +501,10 @@ export interface BaseOAuthAuthentication extends BaseAuthentication { tokenQueryParam?: string; } /** - * Authenticate using OAuth2. You must specify the authorization URL, token exchange URL, and - * scopes here as part of the pack definition. You'll provide the application's client ID and - * client secret in the pack management UI, so that these can be stored securely. + * Authenticate using the OAuth2 Authorization Code flow. You must specify the authorization URL, + * token exchange URL, and scopes here as part of the pack definition. You'll provide the + * application's client ID and client secret in the pack management UI, so that these can be stored + * securely. * * The API must use a (largely) standards-compliant implementation of OAuth2. * @@ -563,7 +564,7 @@ export interface OAuth2Authentication extends BaseOAuthAuthentication { pkceChallengeMethod?: 'plain' | 'S256'; } /** - * Authenticate using OAuth2 client credentials. + * Authenticate using the OAuth2 Client Credentials flow. * You must specify the token exchange URL here as part of the pack definition. * You'll provide the application's client ID and client secret when authenticating. * diff --git a/docs/embedded-snippets/samples/packs/authentication/battlenet.html b/docs/embedded-snippets/samples/packs/authentication/battlenet.html new file mode 100644 index 0000000000..aa9257657a --- /dev/null +++ b/docs/embedded-snippets/samples/packs/authentication/battlenet.html @@ -0,0 +1,33 @@ + + + + + + + +
+ + diff --git a/docs/embedded-snippets/samples/snippets/authentication/system_oauth2_client_credentials.html b/docs/embedded-snippets/samples/snippets/authentication/system_oauth2_client_credentials.html new file mode 100644 index 0000000000..edd393e20a --- /dev/null +++ b/docs/embedded-snippets/samples/snippets/authentication/system_oauth2_client_credentials.html @@ -0,0 +1,33 @@ + + + + + + + +
+ + diff --git a/docs/embedded-snippets/samples/snippets/authentication/user_oauth2.html b/docs/embedded-snippets/samples/snippets/authentication/user_oauth2.html index 8dc7968cc9..80b4dbea80 100644 --- a/docs/embedded-snippets/samples/snippets/authentication/user_oauth2.html +++ b/docs/embedded-snippets/samples/snippets/authentication/user_oauth2.html @@ -16,7 +16,7 @@ require(['vs/editor/editor.main'], function () { var editor = monaco.editor.create(document.getElementById('container'), { - value: "// When registering your app in the API's developer console set the redirect URL\n// to: https://coda.io/packsAuth/oauth2/{PACK ID}\n// After building your Pack, remember to visit the Settings tab to set your\n// client ID and secret.\npack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2,\n // The following two URLs are will be found in the API's documentation.\n authorizationUrl: \"${1:https://example.com/authorize}\",\n tokenUrl: \"${2:https://example.com/token}\",\n scopes: [\n // TODO: List the API scopes to request, if any.\n ],\n getConnectionName: async function (context) {\n // TODO: Fetch the name of the account.\n let name = \"\";\n return name;\n },\n});", + value: "// When registering your app in the API's developer console set the redirect URL\n// to: https://coda.io/packsAuth/oauth2/{PACK ID}\n// After building your Pack, remember to visit the Settings tab to set your\n// client ID and secret.\npack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2,\n // The following two URLs will be found in the API's documentation.\n authorizationUrl: \"${1:https://example.com/authorize}\",\n tokenUrl: \"${2:https://example.com/token}\",\n scopes: [\n // TODO: List the API scopes to request, if any.\n ],\n getConnectionName: async function (context) {\n // TODO: Fetch the name of the account.\n let name = \"\";\n return name;\n },\n});", language: 'javascript', minimap: {enabled: false}, readOnly: true, diff --git a/docs/embedded-snippets/samples/snippets/authentication/user_oauth2_client_credentials.html b/docs/embedded-snippets/samples/snippets/authentication/user_oauth2_client_credentials.html new file mode 100644 index 0000000000..75d7054a2a --- /dev/null +++ b/docs/embedded-snippets/samples/snippets/authentication/user_oauth2_client_credentials.html @@ -0,0 +1,33 @@ + + + + + + + +
+ + diff --git a/docs/guides/basics/authentication/oauth2.md b/docs/guides/basics/authentication/oauth2.md index ecfee9b9ec..b3729aecd5 100644 --- a/docs/guides/basics/authentication/oauth2.md +++ b/docs/guides/basics/authentication/oauth2.md @@ -16,6 +16,23 @@ Read the [Authentication guide][authentication] for more information about how t Coda doesn't currently support the older 1.0 or 1.0a versions of the OAuth specification. If you would like to connect to an API that only supports these versions of the standard please [contact support][support] so that we can continue to gauge interest. +## Supported OAuth flows + +The OAuth2 protocol supports a variety of flows, also known as grant types, which specify how exactly credentials are exchanged. The Pack SDK currently supports two of these flows: + +**Authorization Code** (`grant_type=authorization_code`) +: This is the standard OAuth2 flow that most people are familiar with, meant for accessing a user's private data. The user at the keyboard is redirected to a screen where they login to the application, approve access, and then are redirected back. + + To use this flow in the Pack SDK select the authentication type [`OAuth2`][OAuth2Authentication]. + +**Client Credentials** (`grant_type=client_credentials`) +: This OAuth2 flow doesn't usually involve the user and the keyboard at all, but is a way for the Pack to authenticate itself with the application. It's essentially a more secure version of an API key, since it uses short-lived tokens. + + To use this flow in the Pack SDK select the authentication type [`OAuth2ClientCredentials`][OAuth2ClientCredentialsAuthentication]. + +Other OAuth2 flows are not currently supported. The majority of this guide will assume you are using the Authorization Code flow, but see the section [Client credentials flow](#client_credentials) for more information about that flow specifically. + + ## Setup OAuth authentication To enable your Pack to authenticate users with OAuth you need to configure the OAuth flow and enter your developer credentials. @@ -200,10 +217,30 @@ pack.setUserAuthentication({ ``` +## Client credentials flow {: #client_credentials} + +While the Authorization Code flow discussed above is used to access private user data, the Client Credentials flow is typically just used to authenticate the integration itself. Therefore it's most commonly implemented as a system-wide form of authentication, although per-user authentication is also supported. + +To setup the authentication all you need to do is set the type and provide the URL used to token exchange. + +```ts +pack.setSystemAuthentication({ + type: coda.AuthenticationType.OAuth2ClientCredentials, + // This URL comes from the API's developer documentation. + tokenUrl: "https://api.example.com/token", +}); +``` + +If using system-wide authentication you'll need to set the client ID and secret in the Pack settings. If using per-user authentication the user will be prompted for their client ID and secret when connecting their account. + +Like with the Authorization Code flow, a variety of other advanced options are also available to support non-standard OAuth2 implementations. See the class [`OAuth2ClientCredentialsAuthentication`][OAuth2ClientCredentialsAuthentication] for more information. + + [oauth_definition]: https://oauth.net/2/ [authentication]: index.md [OAuth]: ../../../reference/sdk/enums/core.AuthenticationType.md#oauth2 [OAuth2Authentication]: ../../../reference/sdk/interfaces/core.OAuth2Authentication.md +[OAuth2ClientCredentialsAuthentication]: ../../../reference/sdk/interfaces/core.OAuth2ClientCredentialsAuthentication.md [oauth2_code]: https://www.oauth.com/oauth2-servers/server-side-apps/authorization-code/ [oauth2_client]: https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/ [extraOAuthScopes]: ../../../reference/sdk/interfaces/core.BaseFormulaDef.md#extraoauthscopes diff --git a/docs/reference/sdk/interfaces/core.OAuth2Authentication.md b/docs/reference/sdk/interfaces/core.OAuth2Authentication.md index db8bb901fe..8ad47f35a5 100644 --- a/docs/reference/sdk/interfaces/core.OAuth2Authentication.md +++ b/docs/reference/sdk/interfaces/core.OAuth2Authentication.md @@ -8,9 +8,10 @@ search: [core](../modules/core.md).OAuth2Authentication -Authenticate using OAuth2. You must specify the authorization URL, token exchange URL, and -scopes here as part of the pack definition. You'll provide the application's client ID and -client secret in the pack management UI, so that these can be stored securely. +Authenticate using the OAuth2 Authorization Code flow. You must specify the authorization URL, +token exchange URL, and scopes here as part of the pack definition. You'll provide the +application's client ID and client secret in the pack management UI, so that these can be stored +securely. The API must use a (largely) standards-compliant implementation of OAuth2. diff --git a/docs/reference/sdk/interfaces/core.OAuth2ClientCredentialsAuthentication.md b/docs/reference/sdk/interfaces/core.OAuth2ClientCredentialsAuthentication.md index bec132fe0f..d34e95c75b 100644 --- a/docs/reference/sdk/interfaces/core.OAuth2ClientCredentialsAuthentication.md +++ b/docs/reference/sdk/interfaces/core.OAuth2ClientCredentialsAuthentication.md @@ -8,7 +8,7 @@ search: [core](../modules/core.md).OAuth2ClientCredentialsAuthentication -Authenticate using OAuth2 client credentials. +Authenticate using the OAuth2 Client Credentials flow. You must specify the token exchange URL here as part of the pack definition. You'll provide the application's client ID and client secret when authenticating. diff --git a/docs/samples/topic/apis.md b/docs/samples/topic/apis.md index 4aa8c29c06..8c887b7417 100644 --- a/docs/samples/topic/apis.md +++ b/docs/samples/topic/apis.md @@ -73,6 +73,27 @@ pack.setUserAuthentication({ }); {% endraw %} ``` +## Battle.net +Blizzard's Battle.net APIs use the Client Credentials OAuth2 flow. + +```ts +{% raw %} +import * as coda from "@codahq/packs-sdk"; +export const pack = coda.newPack(); + +// System-wide authentication to Blizzard's Battle.net APIs, using the OAuth2 +// client_credentials flow. +// eslint-disable-next-line max-len +// See https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow. +pack.setSystemAuthentication({ + type: coda.AuthenticationType.OAuth2ClientCredentials, + tokenUrl: "https://oauth.battle.net/token", +}); + +// Allow the pack to make requests to Battle.net. +pack.addNetworkDomain("blizzard.com"); +{% endraw %} +``` ## Board Game Atlas The Board Game Atlas API requires the developer to provide their client ID as query parameter. diff --git a/docs/samples/topic/authentication.md b/docs/samples/topic/authentication.md index 574dd91d55..438ce6d522 100644 --- a/docs/samples/topic/authentication.md +++ b/docs/samples/topic/authentication.md @@ -307,7 +307,7 @@ pack.setUserAuthentication({ {% endraw %} ``` ## OAuth2 -Authentication that uses an OAuth2 flow. This sample connects to the Todoist API. +Authentication that uses the Authorization Code OAuth2 flow. This sample connects to the Todoist API. ```ts {% raw %} @@ -339,6 +339,27 @@ pack.setUserAuthentication({ pack.addNetworkDomain("todoist.com"); {% endraw %} ``` +## OAuth2 client credentials +Authentication that uses the Client Credentials OAuth2 flow. This sample connects to Blizzard's Battle.net APIs. + +```ts +{% raw %} +import * as coda from "@codahq/packs-sdk"; +export const pack = coda.newPack(); + +// System-wide authentication to Blizzard's Battle.net APIs, using the OAuth2 +// client_credentials flow. +// eslint-disable-next-line max-len +// See https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow. +pack.setSystemAuthentication({ + type: coda.AuthenticationType.OAuth2ClientCredentials, + tokenUrl: "https://oauth.battle.net/token", +}); + +// Allow the pack to make requests to Battle.net. +pack.addNetworkDomain("blizzard.com"); +{% endraw %} +``` ## Manual endpoint Authentication that requires users to enter the endpoint URL for their account. This sample connects to the Okta API. diff --git a/documentation/generated/examples.json b/documentation/generated/examples.json index bf1ab17d29..1340f6e2c4 100644 --- a/documentation/generated/examples.json +++ b/documentation/generated/examples.json @@ -111,9 +111,14 @@ }, { "name": "OAuth2", - "content": "Authentication that uses an OAuth2 flow. This sample connects to the Todoist API.", + "content": "Authentication that uses the Authorization Code OAuth2 flow. This sample connects to the Todoist API.", "code": "import * as coda from \"@codahq/packs-sdk\";\nexport const pack = coda.newPack();\n\n// Per-user authentication to the Todoist API, using an OAuth2 flow.\n// See https://developer.todoist.com/guides/#oauth\npack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2,\n authorizationUrl: \"https://todoist.com/oauth/authorize\",\n tokenUrl: \"https://todoist.com/oauth/access_token\",\n scopes: [\"data:read_write\"],\n\n // Determines the display name of the connected account.\n getConnectionName: async function (context) {\n let url = coda.withQueryParams(\"https://api.todoist.com/sync/v9/sync\", {\n resource_types: JSON.stringify([\"user\"]),\n });\n let response = await context.fetcher.fetch({\n method: \"GET\",\n url: url,\n });\n return response.body.user?.full_name;\n },\n});\n\n// Allow the pack to make requests to Todoist.\npack.addNetworkDomain(\"todoist.com\");" }, + { + "name": "OAuth2 client credentials", + "content": "Authentication that uses the Client Credentials OAuth2 flow. This sample connects to Blizzard's Battle.net APIs.", + "code": "import * as coda from \"@codahq/packs-sdk\";\nexport const pack = coda.newPack();\n\n// System-wide authentication to Blizzard's Battle.net APIs, using the OAuth2\n// client_credentials flow.\n// eslint-disable-next-line max-len\n// See https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow.\npack.setSystemAuthentication({\n type: coda.AuthenticationType.OAuth2ClientCredentials,\n tokenUrl: \"https://oauth.battle.net/token\",\n});\n\n// Allow the pack to make requests to Battle.net.\npack.addNetworkDomain(\"blizzard.com\");" + }, { "name": "Manual endpoint", "content": "Authentication that requires users to enter the endpoint URL for their account. This sample connects to the Okta API.", @@ -685,6 +690,11 @@ "content": "The Amazon Web Services (AWS) S3 service uses their custom signature method.", "code": "import * as coda from \"@codahq/packs-sdk\";\nexport const pack = coda.newPack();\n\n// Per-user authentication to the AWS S3 service, using AWS Signature Version 4.\n// The user provides the URL of their S3 bucket as the endpoint, along with an\n// access key and secret.\npack.setUserAuthentication({\n type: coda.AuthenticationType.AWSAccessKey,\n instructionsUrl:\n \"https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/\",\n\n // The AWS service to connect to.\n service: \"s3\",\n\n // Prompt the user from their S3 bucket URL.\n requiresEndpointUrl: true,\n endpointDomain: \"amazonaws.com\",\n\n // Use the bucket name as the display name for the account.\n getConnectionName: async function (context) {\n return context.endpoint.split(\"//\")[1].split(\".\")[0];\n },\n});" }, + { + "name": "Battle.net", + "content": "Blizzard's Battle.net APIs use the Client Credentials OAuth2 flow.", + "code": "import * as coda from \"@codahq/packs-sdk\";\nexport const pack = coda.newPack();\n\n// System-wide authentication to Blizzard's Battle.net APIs, using the OAuth2\n// client_credentials flow.\n// eslint-disable-next-line max-len\n// See https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow.\npack.setSystemAuthentication({\n type: coda.AuthenticationType.OAuth2ClientCredentials,\n tokenUrl: \"https://oauth.battle.net/token\",\n});\n\n// Allow the pack to make requests to Battle.net.\npack.addNetworkDomain(\"blizzard.com\");" + }, { "name": "Board Game Atlas", "content": "The Board Game Atlas API requires the developer to provide their client ID as query parameter.", diff --git a/documentation/generated/pack.code-snippets b/documentation/generated/pack.code-snippets index bdc798724b..67e828fc7c 100644 --- a/documentation/generated/pack.code-snippets +++ b/documentation/generated/pack.code-snippets @@ -91,8 +91,14 @@ }, "setUserAuthentication:OAuth2": { "prefix": "/setUserAuthentication:OAuth2", - "description": "Sets per-user, OAuth2 authentication for the Pack.", - "body": "// When registering your app in the API's developer console set the redirect URL\n// to: https://coda.io/packsAuth/oauth2/{PACK ID}\n// After building your Pack, remember to visit the Settings tab to set your\n// client ID and secret.\npack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2,\n // The following two URLs are will be found in the API's documentation.\n authorizationUrl: \"${1:https://example.com/authorize}\",\n tokenUrl: \"${2:https://example.com/token}\",\n scopes: [\n // TODO: List the API scopes to request, if any.\n ],\n getConnectionName: async function (context) {\n // TODO: Fetch the name of the account.\n let name = \"\";\n return name;\n },\n});", + "description": "Sets per-user, OAuth2 authentication for the Pack using the Authorization Code flow.", + "body": "// When registering your app in the API's developer console set the redirect URL\n// to: https://coda.io/packsAuth/oauth2/{PACK ID}\n// After building your Pack, remember to visit the Settings tab to set your\n// client ID and secret.\npack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2,\n // The following two URLs will be found in the API's documentation.\n authorizationUrl: \"${1:https://example.com/authorize}\",\n tokenUrl: \"${2:https://example.com/token}\",\n scopes: [\n // TODO: List the API scopes to request, if any.\n ],\n getConnectionName: async function (context) {\n // TODO: Fetch the name of the account.\n let name = \"\";\n return name;\n },\n});", + "scope": "javascript,typescript" + }, + "setUserAuthentication:OAuth2ClientCredentials": { + "prefix": "/setUserAuthentication:OAuth2ClientCredentials", + "description": "Sets per-user, OAuth2 authentication for the Pack using the Client Credentials flow.", + "body": "pack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2ClientCredentials,\n // The following URL will be found in the API's documentation.\n tokenUrl: \"${1:https://example.com/token}\",\n});", "scope": "javascript,typescript" }, "setUserAuthentication:QueryParam": { @@ -137,6 +143,12 @@ "body": "pack.setSystemAuthentication({\n type: coda.AuthenticationType.MultiQueryParamToken,\n params: [\n { name: \"${1:myToken}\", description: \"${2:My token description}\" },\n { name: \"${3:myKey}\", description: \"${4:My key description}\" },\n // TODO: Add more parameters, if needed.\n ],\n});", "scope": "javascript,typescript" }, + "setSystemAuthentication:OAuth2ClientCredentials": { + "prefix": "/setSystemAuthentication:OAuth2ClientCredentials", + "description": "Sets system-wide, OAuth2 authentication for the Pack using the Client Credentials flow.", + "body": "pack.setSystemAuthentication({\n type: coda.AuthenticationType.OAuth2ClientCredentials,\n // The following URL will be found in the API's documentation.\n tokenUrl: \"${1:https://example.com/token}\",\n});", + "scope": "javascript,typescript" + }, "setSystemAuthentication:QueryParam": { "prefix": "/setSystemAuthentication:QueryParam", "description": "Sets system-wide authentication for the Pack, using a token passed in a URL query parameter.", diff --git a/documentation/generated/snippets.json b/documentation/generated/snippets.json index b34ec8f998..b360a1b0d8 100644 --- a/documentation/generated/snippets.json +++ b/documentation/generated/snippets.json @@ -142,10 +142,18 @@ "triggerTokens": [ "setUserAuthentication:OAuth2", "OAuth2", - "OAuth2Authentication" + "OAuth2Authentication", + "authorization_code" ], - "content": "Sets per-user, OAuth2 authentication for the Pack.", - "code": "// When registering your app in the API's developer console set the redirect URL\n// to: https://coda.io/packsAuth/oauth2/{PACK ID}\n// After building your Pack, remember to visit the Settings tab to set your\n// client ID and secret.\npack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2,\n // The following two URLs are will be found in the API's documentation.\n authorizationUrl: \"${1:https://example.com/authorize}\",\n tokenUrl: \"${2:https://example.com/token}\",\n scopes: [\n // TODO: List the API scopes to request, if any.\n ],\n getConnectionName: async function (context) {\n // TODO: Fetch the name of the account.\n let name = \"\";\n return name;\n },\n});" + "content": "Sets per-user, OAuth2 authentication for the Pack using the Authorization Code flow.", + "code": "// When registering your app in the API's developer console set the redirect URL\n// to: https://coda.io/packsAuth/oauth2/{PACK ID}\n// After building your Pack, remember to visit the Settings tab to set your\n// client ID and secret.\npack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2,\n // The following two URLs will be found in the API's documentation.\n authorizationUrl: \"${1:https://example.com/authorize}\",\n tokenUrl: \"${2:https://example.com/token}\",\n scopes: [\n // TODO: List the API scopes to request, if any.\n ],\n getConnectionName: async function (context) {\n // TODO: Fetch the name of the account.\n let name = \"\";\n return name;\n },\n});" + }, + { + "triggerTokens": [ + "setUserAuthentication:OAuth2ClientCredentials" + ], + "content": "Sets per-user, OAuth2 authentication for the Pack using the Client Credentials flow.", + "code": "pack.setUserAuthentication({\n type: coda.AuthenticationType.OAuth2ClientCredentials,\n // The following URL will be found in the API's documentation.\n tokenUrl: \"${1:https://example.com/token}\",\n});" }, { "triggerTokens": [ @@ -202,6 +210,16 @@ "content": "Sets system-wide authentication for the Pack, using multiple tokens passed in URL query parameters.", "code": "pack.setSystemAuthentication({\n type: coda.AuthenticationType.MultiQueryParamToken,\n params: [\n { name: \"${1:myToken}\", description: \"${2:My token description}\" },\n { name: \"${3:myKey}\", description: \"${4:My key description}\" },\n // TODO: Add more parameters, if needed.\n ],\n});" }, + { + "triggerTokens": [ + "setSystemAuthentication:OAuth2ClientCredentials", + "OAuth2ClientCredentials", + "OAuth2ClientCredentialsAuthentication", + "client_credentials" + ], + "content": "Sets system-wide, OAuth2 authentication for the Pack using the Client Credentials flow.", + "code": "pack.setSystemAuthentication({\n type: coda.AuthenticationType.OAuth2ClientCredentials,\n // The following URL will be found in the API's documentation.\n tokenUrl: \"${1:https://example.com/token}\",\n});" + }, { "triggerTokens": [ "setSystemAuthentication:QueryParam" diff --git a/documentation/samples/packs/authentication/battlenet.ts b/documentation/samples/packs/authentication/battlenet.ts new file mode 100644 index 0000000000..51657361f1 --- /dev/null +++ b/documentation/samples/packs/authentication/battlenet.ts @@ -0,0 +1,14 @@ +import * as coda from "@codahq/packs-sdk"; +export const pack = coda.newPack(); + +// System-wide authentication to Blizzard's Battle.net APIs, using the OAuth2 +// client_credentials flow. +// eslint-disable-next-line max-len +// See https://develop.battle.net/documentation/guides/using-oauth/client-credentials-flow. +pack.setSystemAuthentication({ + type: coda.AuthenticationType.OAuth2ClientCredentials, + tokenUrl: "https://oauth.battle.net/token", +}); + +// Allow the pack to make requests to Battle.net. +pack.addNetworkDomain("blizzard.com"); diff --git a/documentation/samples/snippets/authentication/system_oauth2_client_credentials.ts b/documentation/samples/snippets/authentication/system_oauth2_client_credentials.ts new file mode 100644 index 0000000000..7b34431b9f --- /dev/null +++ b/documentation/samples/snippets/authentication/system_oauth2_client_credentials.ts @@ -0,0 +1,11 @@ +import * as coda from "@codahq/packs-sdk"; + +const pack = coda.newPack(); + +// BEGIN + +pack.setSystemAuthentication({ + type: coda.AuthenticationType.OAuth2ClientCredentials, + // The following URL will be found in the API's documentation. + tokenUrl: "${1:https://example.com/token}", +}); diff --git a/documentation/samples/snippets/authentication/user_oauth2.ts b/documentation/samples/snippets/authentication/user_oauth2.ts index a0ca977884..a9788320cf 100644 --- a/documentation/samples/snippets/authentication/user_oauth2.ts +++ b/documentation/samples/snippets/authentication/user_oauth2.ts @@ -10,7 +10,7 @@ const pack = coda.newPack(); // client ID and secret. pack.setUserAuthentication({ type: coda.AuthenticationType.OAuth2, - // The following two URLs are will be found in the API's documentation. + // The following two URLs will be found in the API's documentation. authorizationUrl: "${1:https://example.com/authorize}", tokenUrl: "${2:https://example.com/token}", scopes: [ diff --git a/documentation/samples/snippets/authentication/user_oauth2_client_credentials.ts b/documentation/samples/snippets/authentication/user_oauth2_client_credentials.ts new file mode 100644 index 0000000000..c03514a6a9 --- /dev/null +++ b/documentation/samples/snippets/authentication/user_oauth2_client_credentials.ts @@ -0,0 +1,11 @@ +import * as coda from "@codahq/packs-sdk"; + +const pack = coda.newPack(); + +// BEGIN + +pack.setUserAuthentication({ + type: coda.AuthenticationType.OAuth2ClientCredentials, + // The following URL will be found in the API's documentation. + tokenUrl: "${1:https://example.com/token}", +}); diff --git a/documentation/scripts/documentation_config.ts b/documentation/scripts/documentation_config.ts index 8b3ff85514..857f7965f3 100644 --- a/documentation/scripts/documentation_config.ts +++ b/documentation/scripts/documentation_config.ts @@ -80,10 +80,15 @@ export const Snippets: AutocompleteSnippet[] = [ codeFile: './samples/snippets/authentication/user_multi_query_param.ts', }, { - triggerTokens: ['setUserAuthentication:OAuth2', 'OAuth2', 'OAuth2Authentication'], - content: 'Sets per-user, OAuth2 authentication for the Pack.', + triggerTokens: ['setUserAuthentication:OAuth2', 'OAuth2', 'OAuth2Authentication', 'authorization_code'], + content: 'Sets per-user, OAuth2 authentication for the Pack using the Authorization Code flow.', codeFile: './samples/snippets/authentication/user_oauth2.ts', }, + { + triggerTokens: ['setUserAuthentication:OAuth2ClientCredentials'], + content: 'Sets per-user, OAuth2 authentication for the Pack using the Client Credentials flow.', + codeFile: './samples/snippets/authentication/user_oauth2_client_credentials.ts', + }, { triggerTokens: ['setUserAuthentication:QueryParam', 'QueryParamToken', 'QueryParamTokenAuthentication'], content: 'Sets per-user authentication for the Pack, using a token passed in a URL query parameter.', @@ -119,6 +124,11 @@ export const Snippets: AutocompleteSnippet[] = [ content: 'Sets system-wide authentication for the Pack, using multiple tokens passed in URL query parameters.', codeFile: './samples/snippets/authentication/system_multi_query_param.ts', }, + { + triggerTokens: ['setSystemAuthentication:OAuth2ClientCredentials', 'OAuth2ClientCredentials', 'OAuth2ClientCredentialsAuthentication', 'client_credentials'], + content: 'Sets system-wide, OAuth2 authentication for the Pack using the Client Credentials flow.', + codeFile: './samples/snippets/authentication/system_oauth2_client_credentials.ts', + }, { triggerTokens: ['setSystemAuthentication:QueryParam'], content: 'Sets system-wide authentication for the Pack, using a token passed in a URL query parameter.', @@ -368,9 +378,14 @@ export const Examples: Example[] = [ }, { name: 'OAuth2', - content: 'Authentication that uses an OAuth2 flow. This sample connects to the Todoist API.', + content: 'Authentication that uses the Authorization Code OAuth2 flow. This sample connects to the Todoist API.', codeFile: './samples/packs/todoist/auth_oauth2.ts', }, + { + name: 'OAuth2 client credentials', + content: 'Authentication that uses the Client Credentials OAuth2 flow. This sample connects to Blizzard\'s Battle.net APIs.', + codeFile: './samples/packs/authentication/battlenet.ts', + }, { name: 'Manual endpoint', content: @@ -933,6 +948,11 @@ export const Examples: Example[] = [ content: 'The Amazon Web Services (AWS) S3 service uses their custom signature method.', codeFile: './samples/packs/authentication/aws.ts', }, + { + name: 'Battle.net', + content: 'Blizzard\'s Battle.net APIs use the Client Credentials OAuth2 flow.', + codeFile: './samples/packs/authentication/battlenet.ts', + }, { name: 'Board Game Atlas', content: 'The Board Game Atlas API requires the developer to provide their client ID as query parameter.', diff --git a/types.ts b/types.ts index 609dc54a0d..f186637d1c 100644 --- a/types.ts +++ b/types.ts @@ -525,9 +525,10 @@ export interface BaseOAuthAuthentication extends BaseAuthentication { } /** - * Authenticate using OAuth2. You must specify the authorization URL, token exchange URL, and - * scopes here as part of the pack definition. You'll provide the application's client ID and - * client secret in the pack management UI, so that these can be stored securely. + * Authenticate using the OAuth2 Authorization Code flow. You must specify the authorization URL, + * token exchange URL, and scopes here as part of the pack definition. You'll provide the + * application's client ID and client secret in the pack management UI, so that these can be stored + * securely. * * The API must use a (largely) standards-compliant implementation of OAuth2. * @@ -590,7 +591,7 @@ export interface OAuth2Authentication extends BaseOAuthAuthentication { } /** - * Authenticate using OAuth2 client credentials. + * Authenticate using the OAuth2 Client Credentials flow. * You must specify the token exchange URL here as part of the pack definition. * You'll provide the application's client ID and client secret when authenticating. *