Skip to main content
Sublay supports OAuth 2.0 sign-in with Google, GitHub, Apple, and Facebook. The flow is redirect-based: the user is sent to the provider’s authorization page and returns to a callback URL in your app with tokens embedded in the URL fragment.
OAuth providers must be configured in the Sublay dashboard before use. Each provider requires a client ID, client secret, and a list of allowed redirect URIs.

Web Integration

The useOAuthSignIn hook (from @sublay/react-js) handles the full web OAuth flow.
import { useOAuthSignIn } from "@sublay/react-js";

Initiating Sign-In

Call initiateOAuth with the provider name and the URL your app will redirect back to after authentication.
import { useOAuthSignIn } from "@sublay/react-js";

function SignInWithGoogle() {
  const { initiateOAuth, isLoading, error } = useOAuthSignIn();

  const handleClick = async () => {
    // The user will be redirected to Google's authorization page.
    // isLoading stays true during the redirect.
    await initiateOAuth("google", "https://yourapp.com/auth/callback");
  };

  return (
    <button onClick={handleClick} disabled={isLoading}>
      {isLoading ? "Redirecting..." : "Sign in with Google"}
    </button>
  );
}
Supported provider values: "google", "github", "apple", "facebook".

Handling the Callback

On the page your app redirects back to, call handleOAuthCallback once on mount. It reads the tokens from the URL fragment, stores them in the SDK, and cleans the URL.
import { useEffect } from "react";
import { useOAuthSignIn } from "@sublay/react-js";
import { useNavigate } from "react-router-dom";

function AuthCallbackPage() {
  const { handleOAuthCallback, error } = useOAuthSignIn();
  const navigate = useNavigate();

  useEffect(() => {
    const success = handleOAuthCallback();
    if (success) {
      navigate("/dashboard");
    }
  }, []);

  if (error) return <p>Authentication failed: {error}</p>;

  return <p>Authenticating...</p>;
}
handleOAuthCallback returns true if tokens were found in the URL fragment and false otherwise. If the provider returned an error (for example, the user denied access), the error is surfaced through the error field.

Linking an Additional Provider

Authenticated users can link additional OAuth providers to their account using linkOAuthProvider. This requires the user to already be signed in.
import { useOAuthSignIn } from "@sublay/react-js";

function LinkGitHubButton() {
  const { linkOAuthProvider } = useOAuthSignIn();

  return (
    <button onClick={() => linkOAuthProvider("github", "https://yourapp.com/settings/callback")}>
      Connect GitHub
    </button>
  );
}
The callback page logic is identical for both sign-in and link flows — handleOAuthCallback handles both cases.

Expo Integration

@sublay/expo ships its own useOAuthSignIn hook with the same API as the web hook (initiateOAuth, linkOAuthProvider, handleOAuthCallback, isLoading, error). Instead of a full-page redirect, it opens the Sublay-brokered consent screen in the system browser and returns to your app through a custom-scheme deep link.
Deep links don’t work reliably in Expo Go. You need a custom dev client (npx expo run:ios / npx expo run:android) or an EAS Build.

Setup

1

Install the peer dependencies

The Expo hook relies on expo-web-browser (to open the auth session) and expo-linking (to parse the return URL).
npx expo install expo-web-browser expo-linking
2

Register a URL scheme

Add a custom scheme to your app.json (or app.config.js). This is the scheme your redirectAfterAuth deep link uses.
app.json
{
  "expo": {
    "scheme": "myapp"
  }
}
3

Allow the redirect URI in the dashboard

In your Sublay project’s OAuth provider settings, add the exact deep link you’ll pass as redirectAfterAuth (e.g. myapp://auth/callback) to the provider’s Allowed Redirect URIs.

Initiating Sign-In

redirectAfterAuth is required on mobile — there is no window.location to fall back to. Pass the deep link you registered above.
import { useOAuthSignIn } from "@sublay/expo";

function SignInWithGoogle() {
  const { initiateOAuth, isLoading, error } = useOAuthSignIn();

  const handlePress = () =>
    initiateOAuth({
      provider: "google",
      redirectAfterAuth: "myapp://auth/callback",
    });

  return (
    <Button
      title={isLoading ? "Signing in..." : "Sign in with Google"}
      onPress={handlePress}
      disabled={isLoading}
    />
  );
}
On a successful return, tokens are parsed from the deep link and stored automatically. There is no separate callback page — the result is resolved inline. handleOAuthCallback exists for API parity but is a no-op that always returns false, so you never need to call it on mobile. If the user cancels or dismisses the browser, the flow resolves quietly: isLoading resets to false and error stays null. error is only set on a server failure, a provider error in the redirect, or when no tokens are returned.

Linking an Additional Provider

linkOAuthProvider works exactly like the web flow and requires the user to already be signed in.
import { useOAuthSignIn } from "@sublay/expo";

function LinkGitHubButton() {
  const { linkOAuthProvider } = useOAuthSignIn();

  return (
    <Button
      title="Connect GitHub"
      onPress={() =>
        linkOAuthProvider({
          provider: "github",
          redirectAfterAuth: "myapp://settings",
        })
      }
    />
  );
}

Persistence

Tokens dispatched by the hook are picked up by the SublayProvider’s account manager and written to SecureStore, so the session survives app relaunches automatically. You don’t need to add any storage code.

Web vs. Expo at a glance

Web (@sublay/react-js)Expo (@sublay/expo)
Browser handoffFull-page redirect via window.locationSystem browser via expo-web-browser
redirectAfterAuthOptional (defaults to current URL)Required (a custom-scheme deep link)
Callback handlingCall handleOAuthCallback on the callback pageResolved inline; handleOAuthCallback is a no-op
Token persistencelocalStorageSecureStore

How Tokens Are Returned

After the provider callback, Sublay redirects to your redirectAfterAuth URL with tokens in the URL fragment (not query parameters):
https://yourapp.com/auth/callback#accessToken=...&refreshToken=...
Fragments are not sent to servers and do not appear in server access logs, which prevents token leakage. handleOAuthCallback extracts them automatically.

Managing Linked Identities

Use useOAuthIdentities to list and unlink OAuth identities on the current user’s account.
import { useOAuthIdentities } from "@sublay/react-js";

function LinkedAccounts() {
  const { identities, fetchIdentities, unlinkIdentity, isLoading } = useOAuthIdentities();

  useEffect(() => {
    fetchIdentities();
  }, []);

  return (
    <ul>
      {identities.map((identity) => (
        <li key={identity.id}>
          {identity.provider}{identity.email}
          <button onClick={() => unlinkIdentity(identity.id)}>Unlink</button>
        </li>
      ))}
    </ul>
  );
}
Unlinking an identity is blocked if it is the last identity on the account and the user has no password set. This prevents the user from being locked out.

See Also