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)"><</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)">></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)"><</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)">></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)"><</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)">></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)"><</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)">></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)"><</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)">></span></span>
<span></span>
Parameters:
--name
(required): Unique connection name (lowercase, alphanumeric and hyphens only)--type
(required): Authentication type (currently onlyTYPE_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)"><</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)">></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)"><</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)">></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)"><</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)">></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:
- Starts a local HTTP server for OAuth2 callback
- Opens your browser to the provider's authorization page
- Handles the callback after authorization
- Exchanges the authorization code for tokens using stored client secret
- 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)"><</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)">></span></span>
<span></span>
Provider Configuration Examples
Google OAuth2
First, create OAuth2 credentials in Google Cloud Console:
- Go to "APIs & Services" > "Credentials"
- Create OAuth 2.0 Client ID
- 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)">"https://accounts.google.com"</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)">"https://accounts.google.com"</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)">"YOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.com"</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)">"YOUR_GOOGLE_CLIENT_SECRET"</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)">"https://www.googleapis.com/auth/admin.directory.user.readonly"</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:
- Go to "Azure Active Directory" > "App registrations"
- Create new registration
- Configure redirect URIs under "Authentication"
- 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)">"https://login.microsoftonline.com/YOUR_TENANT_ID"</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)">"https://login.microsoftonline.com/YOUR_TENANT_ID/v2.0"</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)">"YOUR_AZURE_APP_CLIENT_ID"</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)">"YOUR_AZURE_APP_CLIENT_SECRET"</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)">"https://graph.microsoft.com/.default"</span></span>
<span></span>
Replace YOUR_TENANT_ID
with your Azure AD tenant ID or use common
for multi-tenant applications.
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:
- Create a new app
- Select OAuth 2.0 for authorization
- Configure redirect URIs
- 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)">"https://appcenter.intuit.com/connect/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)">--issuer-url</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"https://oauth.platform.intuit.com/op/v1"</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)">"YOUR_QUICKBOOKS_CLIENT_ID"</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)">"YOUR_QUICKBOOKS_CLIENT_SECRET"</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 APIcom.intuit.quickbooks.payment
- Payments APIopenid
- OpenID Connectprofile
- User profile informationemail
- 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)">=></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)">'google-oauth'</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)">'https://www.googleapis.com/oauth2/v2/userinfo'</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)">'Authorization'</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)">=></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)">'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-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)">'ms365-oauth'</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)">'https://www.googleapis.com/oauth2/v2/userinfo'</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)">'Authorization'</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)">'https://graph.microsoft.com/v1.0/me'</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)">'Authorization'</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)">'Failed to fetch user data:'</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
- Client Secrets: Treat OAuth2 client secrets as passwords. Rotate them regularly.
- HTTPS Only: Always use HTTPS for redirect URIs in production.
- Scope Management: Configure minimal required scopes for your application needs.
- 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)">"https://accounts.google.com"</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)">"DEV_CLIENT_ID.apps.googleusercontent.com"</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)">"DEV_CLIENT_SECRET"</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)">"https://accounts.google.com"</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)">"PROD_CLIENT_ID.apps.googleusercontent.com"</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)">"PROD_CLIENT_SECRET"</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
- Learn about Function service - Understand Function runtime capabilities
- Secret Manager documentation - Secure secret storage patterns
- Auth service overview - Complete authentication system
- Function examples - More Function integration patterns