Skip to content

Sign in with Google & Apple

Client-side OAuth sign-in with Google and Apple, exchanged for Truememory tokens.

Updated View as Markdown

All requests go to the Truememory Auth base URL (see Before you start for prerequisites: base URL, CORS whitelisting, OAuth client IDs).

OAuth Sign-In (Google / Apple)

For OAuth, the frontend handles the provider interaction (consent screen, token retrieval) and the resulting provider token is exchanged with Truememory Auth for Truememory tokens. Truememory Auth creates or links the user account automatically on first sign-in — no separate registration step needed.

The examples below route that exchange through your own backend, so the returned refresh_token never reaches browser JavaScript — see Suggested implementation for why, and for the route handler these examples call. A frontend with no backend can call /auth/oauth/token directly; that trade-off is documented on the same page.

Flow

sequenceDiagram
accTitle: OAuth Sign-In Flow
accDescr: Shows how a frontend app authenticates a user via Google or Apple through Truememory Auth

    participant User
    participant Frontend
    participant Provider as Google / Apple
    participant Backend as Your backend
    participant Truememory as Truememory Auth
    participant GIP as Google Identity Platform

    User->>Frontend: Click "Sign in with Google/Apple"
    Frontend->>Provider: Open consent screen
    Provider-->>Frontend: id_token (JWT)
    Frontend->>Backend: POST /api/auth/oauth { provider, id_token }
    Backend->>Truememory: POST /auth/oauth/token { provider, id_token }
    Truememory->>GIP: Verify token
    GIP-->>Truememory: Verified user info
    Truememory->>Truememory: Create or link user account
    Truememory-->>Backend: { id_token, refresh_token, expires_in, user }
    Backend-->>Frontend: id_token in body, refresh_token in httpOnly cookie

Endpoint

POST https://your-auth-host/auth/oauth/token
Content-Type: application/json

{
  "provider": "google",
  "id_token": "<token-from-provider-sdk>"
}
Provider provider value
Google google
Apple apple

Response shape is the same as registration.

Google Sign-In (Frontend — React)

npm install @react-oauth/google

Wrap your app root with the Google OAuth provider. The GOOGLE_CLIENT_ID is the OAuth 2.0 Client ID from your GCP project:

// providers.tsx
import { GoogleOAuthProvider } from "@react-oauth/google";

const GOOGLE_CLIENT_ID = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || "";

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <GoogleOAuthProvider clientId={GOOGLE_CLIENT_ID}>
      {children}
    </GoogleOAuthProvider>
  );
}

Add the login button. It posts the Google credential to your own backend route, which exchanges it with Truememory Auth and sets the refresh-token cookie:

// login-page.tsx
import { GoogleLogin, type CredentialResponse } from "@react-oauth/google";

function LoginPage() {
  const handleGoogleSuccess = async (response: CredentialResponse) => {
    if (!response.credential) return;

    const res = await fetch("/api/auth/oauth", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        provider: "google",
        id_token: response.credential,
      }),
    });
    if (!res.ok) {
      console.error("Sign-in failed");
      return;
    }

    // Your route returns { id_token, expires_in, user } and keeps the
    // refresh token in an httpOnly cookie. Hold the ID token in memory only.
    const data = await res.json();
    setIdToken(data.id_token, Number(data.expires_in));
  };

  return (
    <GoogleLogin
      onSuccess={handleGoogleSuccess}
      onError={() => console.error("Google sign-in failed")}
      size="large"
      theme="outline"
    />
  );
}

Apple Sign-In (Frontend — React)

npm install react-apple-signin-auth

Replace APPLE_CLIENT_ID with the Service ID from your Apple Developer account. As with Google, the provider token goes to your own backend route:

import AppleSignin from "react-apple-signin-auth";

function LoginPage() {
  const handleAppleSuccess = async (response: any) => {
    const idToken = response.authorization?.id_token;
    if (!idToken) return;

    const res = await fetch("/api/auth/oauth", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        provider: "apple",
        id_token: idToken,
      }),
    });
    if (!res.ok) {
      console.error("Sign-in failed");
      return;
    }

    const data = await res.json();
    setIdToken(data.id_token, Number(data.expires_in));
  };

  return (
    <AppleSignin
      authOptions={{
        clientId: APPLE_CLIENT_ID,
        scope: "email name",
        redirectURI: window.location.origin,
        usePopup: true,
      }}
      onSuccess={handleAppleSuccess}
    />
  );
}
Navigation

Type to search…

↑↓ navigate↵ selectEsc close