AuthConnectionPreview

AuthConnection enables OAuth2 authentication connections with external providers, featuring server-side secret management and seamless Function runtime integration. Unlike traditional auth integrations focused on user authentication, AuthConnection is designed for application-to-application OAuth2 flows where your functions need to access external APIs on behalf of your application.

Overview

AuthConnection provides a secure way to:

  • Manage OAuth2 connections with external providers (Google, Microsoft 365, QuickBooks)
  • Store client secrets server-side eliminating client-side secret exposure
  • Access tokens from Functions
  • Handle token refresh automatically for long-running integrations

Prerequisites

  • A Tailor Platform workspace with Auth service enabled
  • OAuth2 application configured with your chosen provider
  • Basic understanding of OAuth2 flows
  • Function service enabled (for runtime integration)

CLI Commands

The tailorctl workspace authconnection command manages OAuth2 connections in your workspace.

Create an Auth Connection

<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">create</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">connection-nam</span><span style="color: var(--shiki-color-text)">e</span><span style="color: var(--shiki-token-keyword)">&gt;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--type</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">TYPE_OAUTH2</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--provider-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">provider-ur</span><span style="color: var(--shiki-color-text)">l</span><span style="color: var(--shiki-token-keyword)">&gt;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--issuer-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">issuer-ur</span><span style="color: var(--shiki-color-text)">l</span><span style="color: var(--shiki-token-keyword)">&gt;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">client-i</span><span style="color: var(--shiki-color-text)">d</span><span style="color: var(--shiki-token-keyword)">&gt;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-secret</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">client-secre</span><span style="color: var(--shiki-color-text)">t</span><span style="color: var(--shiki-token-keyword)">&gt;</span></span>
<span></span>

Parameters:

  • --name (required): Unique connection name (lowercase, alphanumeric and hyphens only)
  • --type (required): Authentication type (currently only TYPE_OAUTH2 supported)
  • --provider-url (required): OAuth2 provider URL
  • --issuer-url (optional): Token issuer URL for JWT validation
  • --client-id (required): OAuth2 client ID from the provider
  • --client-secret (required): OAuth2 client secret from the provider

List Auth Connections

<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">list</span></span>
<span></span>

Authorize an Auth Connection

<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authorize</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">connection-nam</span><span style="color: var(--shiki-color-text)">e</span><span style="color: var(--shiki-token-keyword)">&gt;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--scopes</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">scope</span><span style="color: var(--shiki-color-text)">s</span><span style="color: var(--shiki-token-keyword)">&gt;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--port</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">callback-por</span><span style="color: var(--shiki-color-text)">t</span><span style="color: var(--shiki-token-keyword)">&gt;</span></span>
<span></span>

Parameters:

  • connection-name (required): Name of the existing auth connection
  • --scopes (optional): OAuth2 scopes to request (default: openid,profile,email)
  • --port (optional): Local callback server port (default: 8080)
  • --no-browser (optional): Don't open browser automatically

This command:

  1. Starts a local HTTP server for OAuth2 callback
  2. Opens your browser to the provider's authorization page
  3. Handles the callback after authorization
  4. Exchanges the authorization code for tokens using stored client secret
  5. Stores tokens securely on the server

Revoke an Auth Connection

<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">revoke</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&lt;</span><span style="color: var(--shiki-token-string)">connection-nam</span><span style="color: var(--shiki-color-text)">e</span><span style="color: var(--shiki-token-keyword)">&gt;</span></span>
<span></span>

Provider Configuration Examples

Google OAuth2

First, create OAuth2 credentials in Google Cloud Console:

  1. Go to "APIs & Services" > "Credentials"
  2. Create OAuth 2.0 Client ID
  3. Configure authorized redirect URIs
<span><span style="color: var(--shiki-token-comment)"># 1. Create the connection</span></span>
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">create</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">google-oauth</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--type</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">TYPE_OAUTH2</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--provider-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://accounts.google.com&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--issuer-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://accounts.google.com&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;YOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.com&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-secret</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;YOUR_GOOGLE_CLIENT_SECRET&quot;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># 2. Authorize and get tokens</span></span>
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authorize</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">google-oauth</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--scopes</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://www.googleapis.com/auth/admin.directory.user.readonly&quot;</span></span>
<span></span>

Common Google OAuth2 URLs:

  • Authorization endpoint: https://accounts.google.com/o/oauth2/v2/auth
  • Token endpoint: https://oauth2.googleapis.com/token
  • User info endpoint: https://www.googleapis.com/oauth2/v2/userinfo

Microsoft 365 / Azure AD

First, register an application in Azure Portal:

  1. Go to "Azure Active Directory" > "App registrations"
  2. Create new registration
  3. Configure redirect URIs under "Authentication"
  4. Create client secret under "Certificates & secrets"
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">create</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">ms365-oauth</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--type</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">TYPE_OAUTH2</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--provider-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://login.microsoftonline.com/YOUR_TENANT_ID&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--issuer-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;YOUR_AZURE_APP_CLIENT_ID&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-secret</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;YOUR_AZURE_APP_CLIENT_SECRET&quot;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># 2. Authorize and get tokens</span></span>
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authorize</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">ms365-oauth</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--scopes</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://graph.microsoft.com/.default&quot;</span></span>
<span></span>

Common Microsoft OAuth2 URLs:

  • Authorization endpoint: https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
  • Token endpoint: https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
  • User info endpoint: https://graph.microsoft.com/v1.0/me

QuickBooks OAuth2

First, create an app in Intuit Developer Portal:

  1. Create a new app
  2. Select OAuth 2.0 for authorization
  3. Configure redirect URIs
  4. Get your client ID and secret from "Keys & OAuth"
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">create</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">quickbooks-oauth</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--type</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">TYPE_OAUTH2</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--provider-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://appcenter.intuit.com/connect/oauth2&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--issuer-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://oauth.platform.intuit.com/op/v1&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;YOUR_QUICKBOOKS_CLIENT_ID&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-secret</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;YOUR_QUICKBOOKS_CLIENT_SECRET&quot;</span></span>
<span></span>

Common QuickBooks OAuth2 URLs:

  • Authorization endpoint: https://appcenter.intuit.com/connect/oauth2
  • Token endpoint: https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer
  • User info endpoint: https://accounts.platform.intuit.com/v1/openid_connect/userinfo

QuickBooks Scopes:

  • com.intuit.quickbooks.accounting - QuickBooks Online API
  • com.intuit.quickbooks.payment - Payments API
  • openid - OpenID Connect
  • profile - User profile information
  • email - User email address

Function Runtime Integration

AuthConnection integrates seamlessly with the Function service, allowing your functions to access OAuth2 tokens and call external APIs.

Basic Usage

<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">default</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">async</span><span style="color: var(--shiki-color-text)"> () </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-comment)">// Get access token for a connection</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">tokens</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">tailor</span><span style="color: var(--shiki-token-function)">.</span><span style="color: var(--shiki-token-constant)">authconnection</span><span style="color: var(--shiki-token-function)">.getConnectionToken</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&#39;google-oauth&#39;</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)">  </span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-comment)">// Use the access token to call external APIs</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">response</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">fetch</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&#39;https://www.googleapis.com/oauth2/v2/userinfo&#39;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    headers</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-string-expression)">&#39;Authorization&#39;</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">`Bearer </span><span style="color: var(--shiki-token-keyword)">${</span><span style="color: var(--shiki-token-constant)">tokens</span><span style="color: var(--shiki-color-text)">.access_token</span><span style="color: var(--shiki-token-keyword)">}</span><span style="color: var(--shiki-token-string-expression)">`</span></span>
<span><span style="color: var(--shiki-color-text)">    }</span></span>
<span><span style="color: var(--shiki-color-text)">  });</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> (</span><span style="color: var(--shiki-token-keyword)">!</span><span style="color: var(--shiki-token-constant)">response</span><span style="color: var(--shiki-color-text)">.ok) {</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">throw</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">new</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">Error</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">`Failed to fetch user info: </span><span style="color: var(--shiki-token-keyword)">${</span><span style="color: var(--shiki-token-constant)">response</span><span style="color: var(--shiki-color-text)">.statusText</span><span style="color: var(--shiki-token-keyword)">}</span><span style="color: var(--shiki-token-string-expression)">`</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)">  }</span></span>
<span><span style="color: var(--shiki-color-text)">  </span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">userInfo</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">response</span><span style="color: var(--shiki-token-function)">.json</span><span style="color: var(--shiki-color-text)">();</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> userInfo;</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>

Advanced Usage with Error Handling

<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">default</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">async</span><span style="color: var(--shiki-color-text)"> () </span><span style="color: var(--shiki-token-keyword)">=&gt;</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">try</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-comment)">// Get tokens for multiple connections</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">googleTokens</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">tailor</span><span style="color: var(--shiki-token-function)">.</span><span style="color: var(--shiki-token-constant)">authconnection</span><span style="color: var(--shiki-token-function)">.getConnectionToken</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&#39;google-oauth&#39;</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">msTokens</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">tailor</span><span style="color: var(--shiki-token-function)">.</span><span style="color: var(--shiki-token-constant)">authconnection</span><span style="color: var(--shiki-token-function)">.getConnectionToken</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&#39;ms365-oauth&#39;</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)">    </span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-comment)">// Call Google API</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">googleResponse</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">fetch</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&#39;https://www.googleapis.com/oauth2/v2/userinfo&#39;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      headers</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">        </span><span style="color: var(--shiki-token-string-expression)">&#39;Authorization&#39;</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">`Bearer </span><span style="color: var(--shiki-token-keyword)">${</span><span style="color: var(--shiki-token-constant)">googleTokens</span><span style="color: var(--shiki-color-text)">.access_token</span><span style="color: var(--shiki-token-keyword)">}</span><span style="color: var(--shiki-token-string-expression)">`</span></span>
<span><span style="color: var(--shiki-color-text)">      }</span></span>
<span><span style="color: var(--shiki-color-text)">    });</span></span>
<span><span style="color: var(--shiki-color-text)">    </span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-comment)">// Call Microsoft Graph API</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">msResponse</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">fetch</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&#39;https://graph.microsoft.com/v1.0/me&#39;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      headers</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">        </span><span style="color: var(--shiki-token-string-expression)">&#39;Authorization&#39;</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">`Bearer </span><span style="color: var(--shiki-token-keyword)">${</span><span style="color: var(--shiki-token-constant)">msTokens</span><span style="color: var(--shiki-color-text)">.access_token</span><span style="color: var(--shiki-token-keyword)">}</span><span style="color: var(--shiki-token-string-expression)">`</span></span>
<span><span style="color: var(--shiki-color-text)">      }</span></span>
<span><span style="color: var(--shiki-color-text)">    });</span></span>
<span><span style="color: var(--shiki-color-text)">    </span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-constant)">googleData</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">msData</span><span style="color: var(--shiki-color-text)">] </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">Promise</span><span style="color: var(--shiki-token-function)">.all</span><span style="color: var(--shiki-color-text)">([</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-constant)">googleResponse</span><span style="color: var(--shiki-token-function)">.json</span><span style="color: var(--shiki-color-text)">()</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-constant)">msResponse</span><span style="color: var(--shiki-token-function)">.json</span><span style="color: var(--shiki-color-text)">()</span></span>
<span><span style="color: var(--shiki-color-text)">    ]);</span></span>
<span><span style="color: var(--shiki-color-text)">    </span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">return</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      google</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> googleData</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      microsoft</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> msData</span></span>
<span><span style="color: var(--shiki-color-text)">    };</span></span>
<span><span style="color: var(--shiki-color-text)">    </span></span>
<span><span style="color: var(--shiki-color-text)">  } </span><span style="color: var(--shiki-token-keyword)">catch</span><span style="color: var(--shiki-color-text)"> (error) {</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-constant)">console</span><span style="color: var(--shiki-token-function)">.error</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&#39;Failed to fetch user data:&#39;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> error);</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">throw</span><span style="color: var(--shiki-color-text)"> error;</span></span>
<span><span style="color: var(--shiki-color-text)">  }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>

Token Properties

The getConnectionToken() method returns an object with the following properties:

  • Name
    access_token
    Type
    string
    Description

    The OAuth2 access token for API calls

  • Name
    refresh_token
    Type
    string
    Description

    The refresh token (if available from provider)

  • Name
    expires_at
    Type
    string
    Description

    Token expiration timestamp in ISO format

  • Name
    token_type
    Type
    string
    Description

    Token type (typically "Bearer")

Best Practices

Security Considerations

  1. Client Secrets: Treat OAuth2 client secrets as passwords. Rotate them regularly.
  2. HTTPS Only: Always use HTTPS for redirect URIs in production.
  3. Scope Management: Configure minimal required scopes for your application needs.
  4. Token Handling: Never log or expose access tokens in your Function code.

Naming Conventions

Use descriptive names that indicate the provider and environment:

  • google-oauth-prod
  • ms365-oauth-dev
  • quickbooks-oauth-staging

Environment-Specific Configurations

For development vs production environments, create separate connections:

<span><span style="color: var(--shiki-token-comment)"># Development</span></span>
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">create</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">google-oauth-dev</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--type</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">TYPE_OAUTH2</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--provider-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://accounts.google.com&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;DEV_CLIENT_ID.apps.googleusercontent.com&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-secret</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;DEV_CLIENT_SECRET&quot;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Production</span></span>
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">workspace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">authconnection</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">create</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">google-oauth-prod</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--type</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">TYPE_OAUTH2</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--provider-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;https://accounts.google.com&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-id</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;PROD_CLIENT_ID.apps.googleusercontent.com&quot;</span><span style="color: var(--shiki-color-text)"> \</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string)">--client-secret</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;PROD_CLIENT_SECRET&quot;</span></span>
<span></span>

Troubleshooting

Common Issues

Invalid Client Error

  • Verify client ID and secret are correct
  • Check if the OAuth2 app is enabled/active in the provider's console

Redirect URI Mismatch

  • Ensure the redirect URI configured in your provider matches exactly with your application

Scope Errors

  • Verify requested scopes are enabled in your OAuth2 application
  • Some providers require admin consent for certain scopes

Token Expiration

  • Implement refresh token flow in your application
  • Monitor token expiration times

Function Runtime Errors

  • Ensure the connection name exists and is authorized
  • Check that the connection has valid, non-expired tokens
  • Verify network connectivity to external APIs

Next Steps

Additional Resources