Skip to content

Repository files navigation

Authdog Web SDK

Drop-in authentication and identity for modern web frameworks.

A curated monorepo of framework-native libraries that make it effortless to add secure sessions, user management, and auth UI to your React, Next.js, Remix, TanStack Start, Vue, Astro, SvelteKit, Gatsby, RedwoodJS, Angular, React Native, Chrome extensions, and Node (Express / Fastify) applications — plus backend SDKs for Python (FastAPI, Flask, Django, Starlette, aiohttp), Go (Gin), Rust (axum, actix-web, Rocket, warp, poem), and Kotlin (Ktor) that speak the same session protocol.

packages-publishCILicense: MITPRs Welcome

Quick Start · Packages · Examples · Development · Contributing


✨ Why Authdog Web SDK?

  • 🧩 Framework-native — idiomatic packages for React, Next.js (App Router), Remix, TanStack Start, Vue, Astro, SvelteKit, Gatsby, RedwoodJS, Angular, React Native, and Node backends (Express / Fastify), plus Python (FastAPI, Flask, Django, Starlette, aiohttp), Go (Gin), Rust (axum, actix-web, Rocket, warp, poem), and Kotlin (Ktor) backends. No glue code.
  • 🌍 Polyglot backends — Node, Python, Go, Rust, and Kotlin services share one authdog-session cookie, one OIDC userinfo flow, and one trusted identity-host allowlist, so a single Authdog environment works across your whole stack.
  • 🔐 Secure by default — token validation, cookie handling, and session lifecycle managed for you.
  • 🎨 Batteries-included UI — ready-made, accessible components (sign-in, user profile, TOTP, navbar) you can drop in or restyle.
  • ⚡ Tiny & tree-shakeable — ESM-first, sideEffects: false, dual CJS/ESM builds via tsup.
  • 🟦 Type-safe end to end — written in TypeScript with first-class types shipped in every package.
  • 🌐 Server & client split — explicit /client and /server entry points keep secrets server-side.

📦 Packages

PackageVersionDescriptionCI
@authdog/react-elementsnpmReact UI components (Account, UserButton, …)react-elements
@authdog/reactnpmFramework-agnostic React SDK (provider, hooks, AccountButton)
@authdog/nextjs-appnpmNext.js App Router SDKnextjs-app
@authdog/remix-nodenpmRemix SDKremix-node
@authdog/tanstack-startnpmTanStack Start SDKtanstack-start
@authdog/vuenpmVue SDKvue
@authdog/astronpmAstro SDKastro
@authdog/sveltekitnpmSvelteKit SDKsveltekit
@authdog/gatsbynpmGatsby SDKgatsby
@authdog/redwoodnpmRedwoodJS SDKredwood
@authdog/angularnpmAngular SDKangular
@authdog/expressnpmExpress SDKexpress
@authdog/fastifynpmFastify SDKfastify
@authdog/react-nativenpmReact Native / Expo SDKreact-native
@authdog/chrome-extensionnpmChrome Extension SDKchrome-extension
@authdog/node-commonsnpmShared Node utilitiesnode-commons

Backend SDKs for other languages

PackageRegistryDescriptionCI
authdog-fastapiPyPIPython SDK — FastAPI, Flask, Django, Starlette, aiohttppython
authdog (Go)github.com/authdog/web-sdk/packages/goGo SDK with Gin middlewarego
authdog-corecrates.ioFramework-agnostic Rust corerust
authdog-axumcrates.ioRust SDK for Axumrust
authdog-actixcrates.ioRust SDK for Actix Webrust
authdog-rocketcrates.ioRust SDK for Rocketrust
authdog-warpcrates.ioRust SDK for Warprust
authdog-poemcrates.ioRust SDK for Poemrust
authdog-ktorMaven CentralKotlin / Ktor SDKkotlin

These backend SDKs mirror the Node @authdog/express / @authdog/fastify packages on the wire (same authdog-session cookie, same userinfo flow, same identity-host allowlist), so they validate sessions issued for the same Authdog environment.

Internal workspace packages

PackageDescription
@authdog/eslint-configShared ESLint configurations
@authdog/typescript-configShared TypeScript configurations

🚀 Quick Start

Pick the package for your framework and install it with your favorite package manager:

# Next.js (App Router)
bun add @authdog/nextjs-app @authdog/react-elements
# Remix
bun add @authdog/remix-node @authdog/react-elements
# TanStack Start
bun add @authdog/tanstack-start @authdog/react-elements
# Vue
bun add @authdog/vue
# Astro
bun add @authdog/astro
# SvelteKit
bun add @authdog/sveltekit
# Gatsby
bun add @authdog/gatsby @authdog/react-elements
# RedwoodJS
bun add @authdog/redwood @authdog/react-elements
# Angular
bun add @authdog/angular
# Express (backend)
bun add @authdog/express
# Fastify (backend)
bun add @authdog/fastify
# React Native / Expo
bun add @authdog/react-native
# Chrome Extension
bun add @authdog/chrome-extension

Backend SDKs for other languages install with their native package managers:

# Python — one install, pick your framework's extra
pip install "authdog-fastapi[fastapi]"# or [flask], [django], [starlette], [aiohttp]# Go (Gin)
go get github.com/authdog/web-sdk/packages/go@latest
# Rust — add the crate for your framework to Cargo.toml
cargo add authdog-axum # or authdog-actix / authdog-rocket / authdog-warp / authdog-poem# Kotlin (Ktor) — add to build.gradle.kts# implementation("com.authdog:authdog-ktor:0.1.0")

Provide your Authdog public key (pk_…). Each framework reads it from a different place — use the variable that matches your package:

FrameworkVariableWhere it's read
Next.js (client)NEXT_PUBLIC_PK_AUTHDOGExposed to the browser by Next.js
Next.js (server)PK_AUTHDOGServer-only (logout, etc.)
RemixPK_AUTHDOGLoaders / actions
TanStack StartPK_AUTHDOGServer functions / route loaders
Express (backend)PK_AUTHDOGcreateAuthdog({ publicKey })
Fastify (backend)AUTHDOG_PKauthdogPlugin({ publicKey })
VueVITE_AUTHDOG_PUBLIC_KEYVite-exposed (use the VITE_ prefix)
AstroPUBLIC_AUTHDOG_PUBLIC_KEYExposed via Astro's PUBLIC_ prefix
SvelteKitPUBLIC_AUTHDOG_PUBLIC_KEYExposed via SvelteKit's PUBLIC_ prefix
Gatsby (client)GATSBY_AUTHDOG_PUBLIC_KEYExposed via Gatsby's GATSBY_ prefix
Gatsby (functions)PK_AUTHDOGGatsby Functions (server-only)
RedwoodJS (web)REDWOOD_ENV_AUTHDOG_PUBLIC_KEYExposed via Redwood's REDWOOD_ENV_ prefix
RedwoodJS (api)PK_AUTHDOGAPI functions / services (server-only)
React Native / ExpoEXPO_PUBLIC_PK_AUTHDOGExposed to the app by Expo
Chrome ExtensionPLASMO_PUBLIC_AUTHDOG_PUBLIC_KEYExposed to the extension by Plasmo
AngularPassed directly to provideAuthdog(...)
Python (all)PK_AUTHDOGAuthdog(public_key=...)
Go (Gin)PK_AUTHDOGauthdog.New(authdog.Config{PublicKey})
Rust (all)PK_AUTHDOGAuthdog::new(...)
Kotlin (Ktor)PK_AUTHDOGAuthdog(System.getenv("PK_AUTHDOG"))
# Next.js (App Router)
NEXT_PUBLIC_PK_AUTHDOG=pk_xxxxxxxxxxxxxxxx

Your public key (pk_…) is available in the Authdog dashboard. It is safe to expose to the browser. Your secret key (sk_…), used only by backend packages, must never be committed or shipped to the client.

🧪 Examples

Next.js (App Router)

Wrap your app with the provider in app/layout.tsx:

import"@authdog/react-elements/styles.css";import{AuthdogProvider}from"@authdog/nextjs-app/client";exportdefaultfunctionRootLayout({
children,}: {children: React.ReactNode;}){return(<htmllang="en"><body><AuthdogProvider>{children}</AuthdogProvider></body></html>);}

Read the current user from any client component:

"use client";import{useUser}from"@authdog/nextjs-app";import{UserProfile}from"@authdog/react-elements";exportdefaultfunctionProfile(){const{ user, isLoading }=useUser();return<UserProfileloading={isLoading}user={user}/>;}

Vue

<script setup lang="ts">import { AuthdogProvider } from"@authdog/vue/client";import { useUser } from"@authdog/vue";const { user, isLoading } =useUser();</script>
<template>
<AuthdogProvider>
<pv-if="isLoading">Loading…</p>
<pv-else>Welcome, {{ user?.name }}</p>
</AuthdogProvider>
</template>

Astro

Wire the middleware once (SSR mode), then read the session anywhere via Astro.locals.authdog:

// src/middleware.tsimport{defineMiddleware}from"astro:middleware";import{authdogMiddleware}from"@authdog/astro/server";exportconstonRequest=defineMiddleware(authdogMiddleware({publicKey: import.meta.env.PUBLIC_AUTHDOG_PUBLIC_KEY}),);
---// src/pages/profile.astroimport { createAuthdogServer } from"@authdog/astro/server";const authdog =createAuthdogServer({ publicKey: import.meta.env.PUBLIC_AUTHDOG_PUBLIC_KEY });const user =Astro.locals.authdog.isAuthenticated?awaitauthdog.getUser(Astro.request) :null;---{user? <p>Welcome, {user.user?.displayName}</p> : <ahref="/login">Sign in</a>}

SvelteKit

Wire the handle hook once, then read the session anywhere via event.locals.authdog:

// src/hooks.server.tsimport{createAuthdogHandle}from"@authdog/sveltekit/server";exportconsthandle=createAuthdogHandle({publicKey: import.meta.env.PUBLIC_AUTHDOG_PUBLIC_KEY,});
// src/routes/profile/+page.server.tsimport{createAuthdogServer}from"@authdog/sveltekit/server";importtype{PageServerLoad}from"./$types";constauthdog=createAuthdogServer({publicKey: import.meta.env.PUBLIC_AUTHDOG_PUBLIC_KEY,});exportconstload: PageServerLoad=async({ request, locals })=>{constuser=locals.authdog.isAuthenticated
? awaitauthdog.getUser(request)
: null;return{user: user?.user??null};};

Gatsby

Wrap the app once via wrapRootElement, then gate a Gatsby Function with requireAuth:

// gatsby-browser.jsimport{AuthdogProvider}from"@authdog/gatsby/client";exportconstwrapRootElement=({ element })=>(<AuthdogProvider>{element}</AuthdogProvider>);
// src/api/me.tsimport{createAuthdog}from"@authdog/gatsby/server";constauthdog=createAuthdog({publicKey: process.env.PK_AUTHDOG!});exportdefaultauthdog.requireAuth(async(req,res)=>{res.json(req.authdog.user);});

RedwoodJS

Wrap the web app in web/src/App.tsx, then gate an API function with requireAuth:

// web/src/App.tsximport{AuthdogProvider}from"@authdog/redwood/web";constApp=()=>(<AuthdogProvider><RedwoodProvider><Routes/></RedwoodProvider></AuthdogProvider>);
// api/src/functions/me.tsimport{createAuthdog}from"@authdog/redwood/api";constauthdog=createAuthdog({publicKey: process.env.PK_AUTHDOG!});exportconsthandler=authdog.requireAuth(async(event)=>({statusCode: 200,body: JSON.stringify(event.authdog.user),}));

Remix

// app/routes/_index.tsximport{remixAuthLoader}from"@authdog/remix-node";exportconstloader=remixAuthLoader;

TanStack Start

Resolve the session from a server function (TanStack Start speaks the Web Fetch API, so the loader returns a standard Response):

// app/routes/index.tsximport{createServerFn}from"@tanstack/react-start";import{getWebRequest}from"@tanstack/react-start/server";import{identityLoader}from"@authdog/tanstack-start";exportconstloadIdentity=createServerFn({method: "GET"}).handler(async()=>{constresponse=awaitidentityLoader()({request: getWebRequest()});returnresponse.json();},);

Wrap your app with the provider (strips the ?token=… from the URL after the server persists the session):

import{AuthdogProvider}from"@authdog/tanstack-start/client";<AuthdogProvider>{children}</AuthdogProvider>;

Angular

Register the SDK (standalone, app.config.ts) and add the interceptor to your HttpClient:

import{provideHttpClient,withInterceptors}from"@angular/common/http";import{provideAuthdog,authdogInterceptor}from"@authdog/angular";exportconstappConfig={providers: [provideAuthdog({publicKey: "pk_xxxxxxxxxxxxxxxx"}),provideHttpClient(withInterceptors([authdogInterceptor])),],};

Read auth state from the signals-based AuthdogService:

import{Component,inject}from"@angular/core";import{AuthdogService}from"@authdog/angular";
@Component({/* … */})exportclassProfileComponent{readonlyauth=inject(AuthdogService);// auth.isLoading(), auth.token(), auth.user() — signals// auth.signIn(), auth.signUp(), auth.signOut(), auth.fetchUser()}

Express

importexpressfrom"express";import{createAuthdog}from"@authdog/express";constapp=express();constauthdog=createAuthdog({publicKey: process.env.PK_AUTHDOG!});app.use(authdog.attachSession());// resolves `req.authdog` for every requestapp.get("/me",authdog.requireAuth,(req,res)=>res.json(req.authdog!.user));app.get("/logout",authdog.logout);

Fastify

importFastifyfrom"fastify";import{authdogPlugin}from"@authdog/fastify";constapp=Fastify();awaitapp.register(authdogPlugin,{publicKey: process.env.AUTHDOG_PK!});// `request.authdog` is now available everywhere; `app.authdog.requireAuth`// is the server-side enforcement point.app.get("/me",{preHandler: app.authdog.requireAuth},async(req)=>req.authdog!.user,);app.get("/logout",(req,reply)=>app.authdog.logout(req,reply));

Python (FastAPI)

importosfromfastapiimportDepends, FastAPI, Requestfromauthdog.fastapiimportAuthdogapp=FastAPI()
authdog=Authdog(public_key=os.environ["PK_AUTHDOG"])
@app.get("/me")asyncdefme(user=Depends(authdog.require_auth)): # require_auth is the gatereturnuser@app.get("/logout")asyncdeflogout(request: Request):
returnauthdog.logout(request)

The same Authdog surface ships for other Python frameworks — import the matching module: authdog.flask (@authdog.require_auth decorator), authdog.django (middleware + decorator), authdog.starlette (ASGI middleware), or authdog.aiohttp (@web.middleware). All share one framework-agnostic core.

Go (Gin)

ad, _:=authdog.New(authdog.Config{PublicKey: os.Getenv("PK_AUTHDOG")})
r:=gin.Default()
r.Use(ad.AttachSession()) // resolves *authdog.Context per requestr.GET("/me", ad.RequireAuth(), func(c*gin.Context) {
c.JSON(http.StatusOK, authdog.FromGin(c).User)
})
r.GET("/logout", ad.Logout)

Rust (axum)

let authdog = Authdog::new(&std::env::var("PK_AUTHDOG").unwrap()).unwrap();let app = Router::new().route("/me",get(me).layer(middleware::from_fn(require_auth))).route("/logout",get(logout)).layer(middleware::from_fn_with_state(authdog.clone(), attach_session)).with_state(authdog);asyncfnme(ctx:AuthContext) -> Json<Value>{Json(ctx.user.unwrap_or(Value::Null))}

The same surface ships as a dedicated crate per framework on top of the shared authdog-core: authdog-axum, authdog-actix (extractors + middleware), authdog-rocket (request guards + catcher), authdog-warp (composable filters), and authdog-poem (extractors + middleware).

Kotlin (Ktor)

importcom.authdog.Authdogfun Application.module() {
val authdog =Authdog(System.getenv("PK_AUTHDOG"))
routing {
get("/me") {
val ctx = authdog.requireAuth(call) ?:return@get // requireAuth is the gate
call.respondText(ctx.user.toString())
}
get("/logout") { authdog.logout(call) }
}
}

React Native / Expo

Wrap your app with the provider, backed by hardware-secure storage, and handle the login deep link:

import*asSecureStorefrom"expo-secure-store";import{AuthdogProvider,createSecureStoreAdapter,}from"@authdog/react-native";exportdefaultfunctionApp(){return(<AuthdogProviderpublicKey={process.env.EXPO_PUBLIC_PK_AUTHDOG!}storage={createSecureStoreAdapter(SecureStore)}><RootNavigator/></AuthdogProvider>);}
import{useSignIn,useRedirectHandler}from"@authdog/react-native";// signIn("myapp://callback") opens Universal Login; handleRedirect(url)// validates the returned token and persists it via your secure storage.

Chrome Extension

Use Chrome's Identity API for hosted authentication and persist the session in chrome.storage.local:

import{AuthdogProvider,SignedIn,SignedOut,SignInButton,}from"@authdog/chrome-extension";<AuthdogProviderpublicKey={process.env.PLASMO_PUBLIC_AUTHDOG_PUBLIC_KEY!}><SignedOut><SignInButton/></SignedOut><SignedIn>Signed in</SignedIn></AuthdogProvider>;

Runnable examples

Each framework ships a runnable demo under examples/. Set PK_AUTHDOG (or the framework's public-key variable) and start one with moon:

ExamplePackage showcasedRun
examples/nextjs-app@authdog/nextjs-app + @authdog/react-elementsmoon run nextjs-app-sample:dev
examples/remix@authdog/remix-node + @authdog/react-elementsmoon run remix-playground:dev
examples/vue-app@authdog/vue (home, login, signup, profile, permissions)moon run vue-app:dev
examples/astro@authdog/astro (SSR middleware, server getUser, logout)moon run astro-app:dev
examples/sveltekit@authdog/sveltekit (SSR handle hook, server getUser, logout)moon run sveltekit-app:dev
examples/gatsby@authdog/gatsby (client provider, Functions requireAuth, logout)moon run gatsby-app:dev
examples/redwood@authdog/redwood (web provider, API requireAuth, logout)moon run redwood-app:type-check
examples/angular@authdog/angular (interceptor, guard, signals)moon run angular-app:dev
examples/express@authdog/express (attachSession, requireAuth, logout)moon run express-api:dev
examples/fastify@authdog/fastify (plugin, requireAuth, logout)moon run fastify-api:dev
examples/react-native@authdog/react-native (Expo, deep-link sign-in, secure store)moon run react-native-app:dev

🛠 Development

This is a Bun + moon monorepo.

Prerequisites

Setup

git clone https://github.com/authdog/web-sdk.git
cd web-sdk
bun install

Common tasks

The repo ships a Justfile for ergonomic shortcuts:

CommandDescription
just buildBuild all publishable packages
just dev-nextRun the Next.js demo app
just dev-remixRun the Remix demo app
just uiLaunch the Storybook component explorer
just storybookAlias for just ui
just ciRun the full CI pipeline locally

Prefer raw scripts? bun run build, bun run dev, bun run test, bun run lint, and bun run check-types all work via moon.

Repository layout

web-sdk/
├── examples/ # Runnable demo apps (Next.js, Remix, Vue, Astro, SvelteKit, Gatsby, RedwoodJS, Angular, Express, Fastify, React Native)
├── packages/ # Published SDK packages + shared configs
│ ├── react-elements/ # React UI components
│ ├── nextjs-app/ # Next.js App Router SDK
│ ├── remix/ # Remix SDK (@authdog/remix-node)
│ ├── tanstack-start/ # TanStack Start SDK
│ ├── vue/ # Vue SDK
│ ├── astro/ # Astro SDK
│ ├── sveltekit/ # SvelteKit SDK
│ ├── gatsby/ # Gatsby SDK
│ ├── redwood/ # RedwoodJS SDK
│ ├── angular/ # Angular SDK
│ ├── express/ # Express SDK
│ ├── fastify/ # Fastify SDK
│ ├── react-native/ # React Native / Expo SDK
│ ├── chrome-extension/ # Chrome Extension SDK
│ ├── node-commons/ # Shared Node utilities
│ ├── python/ # Python SDK (FastAPI, Flask, Django, Starlette, aiohttp) — authdog-fastapi
│ ├── go/ # Go SDK (Gin)
│ ├── rust/ # Rust workspace (axum, actix, rocket, warp, poem) — authdog-core + crates
│ ├── kotlin/ # Kotlin SDK (Ktor) — authdog-ktor
│ ├── eslint/ # Shared ESLint config
│ └── typescript-config/# Shared tsconfig presets
└── .moon/ # moon workspace & toolchain config

Releasing

Versioning and changelogs are handled with Changesets:

bun run changeset # describe your change
bun run publish-packages # build + publish to npm

🤝 Contributing

Contributions are welcome and appreciated! To get started:

  1. Fork the repository and create a feature branch.
  2. Make your changes and add a changeset (bun run changeset).
  3. Ensure bun run ci passes.
  4. Open a pull request describing your change.

Please report bugs and request features via GitHub Issues.

🔒 Security

Found a vulnerability? Please do not open a public issue. See our Security Policy for responsible disclosure instructions.

📄 License

MIT © Authdog

Built with ❤️ by the Authdog team and contributors.

About

Web related resources to integrate Authdog functionality in your projects

Topics

Resources

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages