bolt-lightningQuickstart: Stack Auth

Integrate GL IAM with Stack Auth for modern, managed authentication.

circle-info

What you'll build: A FastAPI app with authenticated and role-protected endpoints using GL IAM + Stack Auth.

chevron-rightPrerequisiteshashtag

Setup Stack Auth

  1. Go to Stack Auth Dashboardarrow-up-right and create a new project

  2. Note your Project ID, Publishable Client Key, and Secret Server Key

  3. Go to Team Settings → turn on "Create a personal team for each user on sign-up"

Step-by-Step

1

Install GL IAM

uv init --bare
uv add --extra-index-url "https://oauth2accesstoken:$(gcloud auth print-access-token)@glsdk.gdplabs.id/gen-ai-internal/simple/" "gl-iam[fastapi,stackauth]"
uv add python-dotenv uvicorn
2

Create .env

STACKAUTH_BASE_URL=https://api.stack-auth.com
STACKAUTH_PROJECT_ID=your-project-id
STACKAUTH_PUBLISHABLE_CLIENT_KEY=pck_your_key
STACKAUTH_SECRET_SERVER_KEY=ssk_your_key
3

Create main.py

This is the complete application — provider setup, authentication, and role-based access in one file:

import os
from contextlib import asynccontextmanager

from dotenv import load_dotenv
from fastapi import Depends, FastAPI

from gl_iam import IAMGateway, User
from gl_iam.fastapi import get_current_user, require_org_member, set_iam_gateway
from gl_iam.providers.stackauth import StackAuthConfig, StackAuthProvider

load_dotenv()


@asynccontextmanager
async def lifespan(app: FastAPI):
    config = StackAuthConfig(
        base_url=os.getenv("STACKAUTH_BASE_URL"),
        project_id=os.getenv("STACKAUTH_PROJECT_ID"),
        publishable_client_key=os.getenv("STACKAUTH_PUBLISHABLE_CLIENT_KEY"),
        secret_server_key=os.getenv("STACKAUTH_SECRET_SERVER_KEY"),
    )
    provider = StackAuthProvider(config)
    gateway = IAMGateway.from_fullstack_provider(provider)
    set_iam_gateway(gateway, default_organization_id=os.getenv("STACKAUTH_PROJECT_ID"))
    yield
    await provider.close()


app = FastAPI(lifespan=lifespan)


@app.get("/me")
async def get_me(user: User = Depends(get_current_user)):
    return {"email": user.email, "roles": user.roles}


@app.get("/member-area")
async def member_area(
    user: User = Depends(get_current_user),
    _: None = Depends(require_org_member()),
):
    return {"message": f"Welcome {user.email}!", "access_level": "member"}

What's happening:

  1. StackAuthProvider connects GL IAM to your Stack Auth project

  2. IAMGateway.from_fullstack_provider() creates a unified auth gateway

  3. get_current_user validates the Stack Auth token and returns a User

  4. require_org_member() enforces that the user has the ORG_MEMBER role (or higher)

4

Run

uv run uvicorn main:app --reload
5

Test

Sign up a user:

curl -s -X POST https://api.stack-auth.com/api/v1/auth/password/sign-up \
  -H "Content-Type: application/json" \
  -H "x-stack-access-type: client" \
  -H "x-stack-project-id: $STACKAUTH_PROJECT_ID" \
  -H "x-stack-publishable-client-key: $STACKAUTH_PUBLISHABLE_CLIENT_KEY" \
  -d '{"email": "test@example.com", "password": "SecurePass123", "verification_callback_url": "http://localhost:3000/verify"}'

Copy the access_token from the response, then test your GL IAM endpoints:

TOKEN="<paste access_token here>"

curl http://localhost:8000/me -H "Authorization: Bearer $TOKEN"
# {"email":"test@example.com","roles":["admin"]}

curl http://localhost:8000/member-area -H "Authorization: Bearer $TOKEN"
# {"message":"Welcome test@example.com!","access_level":"member"}
circle-exclamation
circle-check

How Roles Work

GL IAM maps Stack Auth team permissions to standard roles:

Stack Auth
GL IAM
Passes

team_admin

ORG_ADMIN

require_org_member(), require_org_admin()

team_member

ORG_MEMBER

require_org_member()

When "Create personal team on sign-up" is enabled, each user gets a personal team with team_admin on sign-up — so roles work automatically.

chevron-rightTroubleshooting: /me returns empty roleshashtag

If /me returns "roles": [] and /member-area returns 500, your user has no team. This happens when "Create personal team on sign-up" is not enabled in your Stack Auth project.

Fix — Option A: Enable it in the Stack Auth dashboard → Team Settings.

Fix — Option B: Load your .env values and create a team manually:

Then sign in again to get a fresh token.

chevron-rightGetting tokens from React/Next.jshashtag

circle-info

Found an issue on this page? Report it on our feedback formarrow-up-right.

Last updated

Was this helpful?