> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hexclave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ConnectedAccount

> Reference for ConnectedAccount types for OAuth connections.

export const MethodReturns = ({type, children}) => <ContentSection title="Returns">
    <code className="inline-flex rounded-md border border-zinc-950/10 bg-zinc-950/[0.04] px-2 py-0.5 text-[13px] font-medium text-zinc-950 dark:border-white/10 dark:bg-white/[0.08] dark:text-white">
      {type}
    </code>
    {children ? <div className="text-sm leading-6 text-zinc-700 dark:text-zinc-300">{children}</div> : null}
  </ContentSection>;

export const MethodLayout = ({children}) => <div className="grid gap-4 md:grid-cols-2 md:items-start xl:gap-6">
    {children}
  </div>;

export const MethodContent = ({children}) => <div className="min-w-0 space-y-4">{children}</div>;

export const MethodAside = ({title, children}) => <div className="min-w-0 self-start space-y-4 rounded-2xl border border-zinc-950/10 bg-zinc-950/[0.02] p-4 dark:border-white/10 dark:bg-white/[0.03]">
    {title ? <p className="m-0 text-sm font-medium text-zinc-950 dark:text-white">{title}</p> : null}
    <div className="space-y-4">{children}</div>
  </div>;

export const ContentSection = ({title, children}) => <div className="space-y-3">
    {title ? <p className="m-0 text-sm font-medium text-zinc-950 dark:text-white">{title}</p> : null}
    <div className="space-y-3">{children}</div>
  </div>;

export const CollapsibleTypesSection = ({type, property, signature, defaultOpen = false, deprecated = false, badge, children}) => {
  const id = `${String(type ?? "").toLowerCase().replace(/[^a-z0-9]/g, "")}${String(property ?? "").toLowerCase().replace(/[^a-z0-9]/g, "")}`;
  const [isOpen, setIsOpen] = useState(defaultOpen);
  useEffect(() => {
    if (typeof window === "undefined") {
      return undefined;
    }
    const syncWithHash = () => {
      if (window.location.hash === `#${id}`) {
        setIsOpen(true);
      }
    };
    syncWithHash();
    window.addEventListener("hashchange", syncWithHash);
    return () => window.removeEventListener("hashchange", syncWithHash);
  }, [id]);
  const label = signature ? `${property}(${signature})` : property;
  const fullLabel = type ? `${type}.${label}` : label;
  return <details id={id} open={isOpen} onToggle={event => setIsOpen(event.currentTarget.open)} className={`not-prose my-4 scroll-mt-24 overflow-hidden rounded-2xl border bg-white dark:bg-zinc-950 ${deprecated ? "border-orange-400/40 dark:border-orange-500/30" : "border-zinc-950/10 dark:border-white/10"}`}>
      <summary className="cursor-pointer list-none px-4 py-4 [&::-webkit-details-marker]:hidden">
        <div className="flex items-center gap-3">
          <code className={`text-[15px] font-medium ${deprecated ? "text-zinc-500 line-through decoration-zinc-400/60 dark:text-zinc-400 dark:decoration-zinc-500/60" : "text-zinc-950 dark:text-white"}`}>{fullLabel}</code>
          <span className="ml-auto flex items-center gap-2">
            {deprecated ? <Badge color="orange" size="sm" shape="pill">deprecated</Badge> : null}
            {badge ?? null}
            <span aria-hidden="true" className="text-sm text-zinc-500 transition-transform dark:text-zinc-400">
              {isOpen ? "▾" : "›"}
            </span>
          </span>
        </div>
      </summary>

      <div className="border-t border-zinc-950/10 px-4 py-5 dark:border-white/10">
        {children}
      </div>
    </details>;
};

export const ClickableTableOfContents = ({title, code}) => {
  const lines = String(code ?? "").replace(/\r\n/g, "\n").split("\n");
  return <div className="not-prose my-6 overflow-hidden rounded-2xl border border-zinc-950/10 bg-zinc-950/[0.03] dark:border-white/10 dark:bg-white/[0.03]">
      {title ? <div className="border-b border-zinc-950/10 px-4 py-3 text-sm font-medium text-zinc-950/80 dark:border-white/10 dark:text-white/80">
          {title}
        </div> : null}

      <pre className="overflow-x-auto px-2 py-3 text-[13px] leading-6 text-zinc-900 dark:text-zinc-100">
        <code>
          {lines.map((line, index) => {
    if (line.trim().startsWith("// NEXT_LINE_PLATFORM")) {
      return null;
    }
    const match = line.match(/^(.*?)(?:\s*\/\/\s*\$stack-link-to:(#[a-zA-Z0-9_-]+))\s*$/);
    const href = match?.[2] ?? null;
    const text = match?.[1] ?? line;
    if (text.trim() === "") {
      return <span key={`blank-${index}`} className="block h-6" />;
    }
    const content = <span className="block whitespace-pre rounded-lg px-3 py-0.5">
                {text.replace(/\s+$/, "")}
              </span>;
    if (!href) {
      return <span key={`line-${index}`} className="block text-zinc-700 dark:text-zinc-300">
                  {content}
                </span>;
    }
    return <a key={`line-${index}`} href={href} className="block no-underline transition-colors hover:bg-zinc-950/[0.04] hover:text-zinc-950 dark:hover:bg-white/[0.05] dark:hover:text-white">
                {content}
              </a>;
  })}
        </code>
      </pre>
    </div>;
};

export const AsideSection = ({title, children}) => <div className="space-y-3">
    {title ? <p className="m-0 text-sm font-medium text-zinc-950 dark:text-white">{title}</p> : null}
    <div className="space-y-3">{children}</div>
  </div>;

export const ConnectionSection = props => <CollapsibleTypesSection badge={<Badge color="zinc" size="sm" shape="pill">
        connection
      </Badge>} {...props} />;

export const OAuthConnectionSection = props => <CollapsibleTypesSection badge={<Badge color="green" size="sm" shape="pill">
        oauthConnection
      </Badge>} {...props} />;

`OAuthConnection` represents an OAuth connection to an external provider (like Google, GitHub, etc.) that is linked to a user. You can use connected accounts to access the user's data on those platforms, such as reading Google Drive files or sending emails via Gmail.

For a guide on how to use connected accounts, see the [Connected Accounts guide](/guides/apps/authentication/connected-accounts).

On this page:

* [`Connection`](#connection)
* [`OAuthConnection`](#oauthconnection)

# `Connection`

Basic information about a connected account. This is the base type that `OAuthConnection` extends.

## Table of Contents

<ClickableTableOfContents
  title="Connection Table of Contents"
  code={`type Connection = {
id: string; //$stack-link-to:#connectionid
provider: string; //$stack-link-to:#connectionprovider
providerAccountId: string; //$stack-link-to:#connectionprovideraccountid
};`}
/>

## Properties

<ConnectionSection type="connection" property="id" deprecated defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      The provider config ID. Same as `provider` and exists for backward compatibility.

      <Warning>Deprecated: Use `provider` instead.</Warning>
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const id: string; `
    </MethodAside>
  </MethodLayout>
</ConnectionSection>

<ConnectionSection type="connection" property="provider" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      The provider config ID (for example, `"google"` or `"github"`).
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const provider: string; `
    </MethodAside>
  </MethodLayout>
</ConnectionSection>

<ConnectionSection type="connection" property="providerAccountId" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      The account ID from the OAuth provider, such as the Google user ID.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const providerAccountId: string; `
    </MethodAside>
  </MethodLayout>
</ConnectionSection>

***

# `OAuthConnection`

Extends `Connection` with methods to retrieve OAuth access tokens. Get it with:

* [`user.getConnectedAccount({ provider, providerAccountId })`](/sdk/types/user#currentusergetconnectedaccount)
* [`user.useConnectedAccount({ provider, providerAccountId })`](/sdk/types/user#currentuseruseconnectedaccount) (React hook)
* [`user.listConnectedAccounts()`](/sdk/types/user#currentuserlistconnectedaccounts)
* [`user.useConnectedAccounts()`](/sdk/types/user#currentuseruseconnectedaccounts) (React hook)
* [`user.getOrLinkConnectedAccount(provider)`](/sdk/types/user#currentusergetorlinkconnectedaccount)
* [`user.useOrLinkConnectedAccount(provider)`](/sdk/types/user#currentuseruseorlinkconnectedaccount) (React hook)

## Table of Contents

<ClickableTableOfContents
  title="OAuthConnection Table of Contents"
  code={`type OAuthConnection =
// Inherits all properties from Connection
& Connection; //$stack-link-to:#connection
& {
getAccessToken(options?): Promise<Result>; //$stack-link-to:#oauthconnectiongetaccesstoken
useAccessToken(options?): Result; //$stack-link-to:#oauthconnectionuseaccesstoken
};`}
/>

## Methods

<OAuthConnectionSection type="oauthConnection" property="getAccessToken" signature="[options]" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Gets an OAuth access token for this connected account. The token can be used to call the provider's APIs on the user's behalf.

      Returns a `Result` object:

      * On success: `{ status: "ok", data: { accessToken: string } }`
      * On error: `{ status: "error", error: OAuthAccessTokenNotAvailable }` if the refresh token has been revoked or expired, or if the requested scopes are not available.

      <ContentSection title="Parameters">
        <ParamField body="options.scopes" type="string[]">
          If provided, only returns a token that has all of these scopes. If the current token does not have the required scopes, the result will be an error.
        </ParamField>
      </ContentSection>

      <MethodReturns type="Promise<Result<{ accessToken: string }, OAuthAccessTokenNotAvailable>>" />
    </MethodContent>

    <MethodAside>
      <AsideSection title="Signature">
        ```typescript theme={null}
        declare function getAccessToken(options?: {
          scopes?: string[];
        }): Promise<Result<{ accessToken: string }, OAuthAccessTokenNotAvailable>>;
        ```
      </AsideSection>

      <AsideSection title="Examples">
        ```typescript theme={null}
        const result = await account.getAccessToken();
        if (result.status === "ok") {
          const { accessToken } = result.data;
        }
        ```

        ```typescript theme={null}
        const result = await account.getAccessToken({
          scopes: ["https://www.googleapis.com/auth/drive.readonly"],
        });
        ```
      </AsideSection>
    </MethodAside>
  </MethodLayout>
</OAuthConnectionSection>

<OAuthConnectionSection type="oauthConnection" property="useAccessToken" signature="[options]" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      React hook version of `getAccessToken`. Returns the access token result reactively.

      <ContentSection title="Parameters">
        <ParamField body="options.scopes" type="string[]">
          If provided, only returns a token that has all of these scopes.
        </ParamField>
      </ContentSection>

      <MethodReturns type="Result<{ accessToken: string }, OAuthAccessTokenNotAvailable>" />
    </MethodContent>

    <MethodAside>
      <AsideSection title="Signature">
        ```typescript theme={null}
        declare function useAccessToken(options?: {
          scopes?: string[];
        }): Result<{ accessToken: string }, OAuthAccessTokenNotAvailable>;
        ```
      </AsideSection>

      <AsideSection title="Examples">
        ```tsx theme={null}
        function MyComponent() {
          const user = useUser({ or: "redirect" });
          const accounts = user.useConnectedAccounts();
          const googleAccount = accounts.find(
            (account) => account.provider === "google",
          );
          const result = googleAccount?.useAccessToken();

          if (result?.status === "ok") {
            return <div>Token: {result.data.accessToken}</div>;
          }

          return <div>No Google token available</div>;
        }
        ```
      </AsideSection>
    </MethodAside>
  </MethodLayout>
</OAuthConnectionSection>

<Info>
  For practical usage instructions, see the [Connected Accounts guide](/guides/apps/authentication/connected-accounts).
</Info>
