Skip to main content
AGG supports four authentication providers. All flows deliver tokens automatically — no extra API calls needed after the user authenticates.

How It Works

Every provider follows the same pattern:
  1. Call authStart with the provider name
  2. User authenticates (signs a message, clicks an OAuth link, or clicks a magic link in their email)
  3. Tokens are delivered to your app
The only difference is how the user authenticates in step 2:
ProviderStep 2
SIWEUser signs a message in their wallet. Tokens returned directly from verify.
Google / TwitterUser is redirected to the provider’s login page. After approval, AGG redirects back to your app with tokens in the URL hash fragment.
EmailUser receives a magic link via email. After clicking, AGG redirects to your app with tokens in the URL hash fragment.

SIWE (Wallet)

SIWE is fully client-side — no redirects:
import { createAggClient } from "@agg-market/sdk";

const client = createAggClient({ baseUrl: "https://api.agg.market", appId: "your-app-id" });

// 1. Get a nonce
const { nonce } = await client.authStart({ provider: "siwe" });

// 2. Build and sign the SIWE message
const message = client.buildSiweMessage({
  address: walletAddress,
  chainId: 1,
  nonce,
  domain: window.location.host,
  uri: window.location.origin,
});
const signature = await signMessage({ message }); // wagmi or ethers

// 3. Verify — tokens returned directly
const { accessToken, refreshToken, user } = await client.verify({ message, signature });
These three providers all use the same redirect-based flow. Pass the page you want the user to land on after sign-in as redirectUrl — typically your dashboard or home page:
const { url } = await client.authStart({
  provider: "google",
  redirectUrl: "https://yourapp.com/dashboard",
});
window.location.href = url; // redirect to Google
After the user authenticates, AGG redirects them to your redirectUrl with tokens in the URL hash fragment:
https://yourapp.com/dashboard#access_token=eyJ...&refresh_token=eyJ...&user_id=user-123&token_type=bearer
Hash fragments are never sent to your server — they’re only accessible via JavaScript in the browser, preventing token leakage.

Reading Tokens from the Hash

On any page that could be a redirect target, check for tokens in the hash on load:
function checkForAuthTokens() {
  const hash = window.location.hash.substring(1);
  if (!hash) return;

  const params = new URLSearchParams(hash);
  const accessToken = params.get("access_token");
  const refreshToken = params.get("refresh_token");
  const userId = params.get("user_id");

  if (accessToken && refreshToken) {
    // Store tokens in the SDK
    client.setSession({ accessToken, refreshToken, user: { id: userId } });

    // Clean the hash from the URL so tokens aren't visible
    window.history.replaceState(null, "", window.location.pathname + window.location.search);
  }
}

// Call on page load
checkForAuthTokens();

Using React Hooks

With @agg-market/hooks, the SIWE flow is handled automatically:
import { useAggAuth } from "@agg-market/hooks";
import { useAccount, useSignMessage } from "wagmi";

function SignIn() {
  const { address, chainId } = useAccount();
  const { signMessageAsync } = useSignMessage();
  const { signIn, signOut, isAuthenticated, user, isLoading } = useAggAuth({
    address,
    chainId,
    signMessage: signMessageAsync,
  });

  if (isAuthenticated) {
    return (
      <div>
        <p>Signed in as {user.id}</p>
        <button onClick={signOut}>Sign Out</button>
      </div>
    );
  }

  return <button onClick={signIn} disabled={isLoading}>Sign in with Ethereum</button>;
}

Token Storage

The SDK automatically stores tokens in localStorage (keyed by appId) and restores them on construction.