Concepts

OAuth Providers

Integrating OAuth Providers for API Access

With Stack, users can connect multiple OAuth accounts, enabling access to provider-specific data and services such as Google Drive, Microsoft Calendar, GitHub repositories, and more.

Connecting with an OAuth Provider Post Sign-in

Users can connect with an OAuth provider during sign-in or after signing in using other methods. For the latter, use the user.useConnectedAccount('<provider_name>', { or: 'redirect' }) method. If the account is already connected, the method returns a Connection object; otherwise, it redirects the user to the provider’s authorization page.

In order to connect accounts after sign-in, you need to set up your own OAuth client ID and client secret with the provider. See more details in the section Going to Production

Here’s how to connect with Google:

1'use client';
2
3import { useUser } from "@stackframe/stack";
4
5export default function Page() {
6 const user = useUser({ or: 'redirect' });
7 // Redirects to Google authorization if not already connected
8 const account = user.useConnectedAccount('google', { or: 'redirect' });
9 // Account is always defined because of the redirect
10 return <div>Google account connected</div>;
11}

Connecting with Extra Scopes

You can request extra scopes when connecting with an OAuth provider. For instance, to access Google Drive, pass the https://www.googleapis.com/auth/drive.readonly scope. Here’s an example:

1'use client';
2
3import { useUser } from "@stackframe/stack";
4
5export default function Page() {
6 const user = useUser({ or: 'redirect' });
7 // Redirects to the Google authorization page, requesting access to Google Drive
8 const account = user.useConnectedAccount('google', { or: 'redirect', scopes: ['https://www.googleapis.com/authdrive.readonly'] });
9 // Account is always defined because of the redirect
10 return <div>Google Drive connected</div>;
11}

Retrieving the Access Token

Once connected with an OAuth provider, obtain the access token using the account.getAccessToken() method. Use this token to access the provider’s API endpoints. Here’s an example of using the access token to interact with Google Drive API:

1'use client';
2
3import { useEffect, useState } from 'react';
4import { useUser } from "@stackframe/stack";
5
6export default function Page() {
7 const user = useUser({ or: 'redirect' });
8 const account = user.useConnectedAccount('google', { or: 'redirect', scopes: ['https://www.googleapis.com/auth/drive.readonly'] });
9 const tokens = account.useAccessToken();
10 const [response, setResponse] = useState<any>();
11
12 useEffect(() => {
13 fetch('https://www.googleapis.com/drive/v3/files', {
14 headers: { Authorization: `Bearer ${tokens.accessToken}` }
15 })
16 .then((res) => res.json())
17 .then((data) => setResponse(data))
18 .catch((err) => console.error(err));
19 }, [tokens]);
20
21 return <div>{response ? JSON.stringify(response) : 'Loading...'}</div>;
22}

Requesting Extra Scopes During Sign-in

To avoid showing the authorization page twice, you can request extra scopes during the sign-in process. This approach is optional and depends on your application’s design. Some applications may prefer to request extra permissions only when needed, while others might want to obtain all necessary permissions upfront.

Configure the StackServerApp with the required scopes:

stack.ts
1// imports ...
2
3export const stackServerApp = new StackServerApp({
4 // your other settings ...
5 oauthScopesOnSignIn: {
6 google: ['https://www.googleapis.com/authdrive.readonly']
7 }
8});

By setting this up, users will be prompted for all necessary permissions during the initial sign-in, avoiding the need for them to approve additional permissions later. Choose the approach that best fits your application’s user experience and workflow.