Skip to content

authdog/web-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

654 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

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, Angular, React Native, 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-publish CI License: MIT PRs 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, 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

Package Version Description CI
@authdog/react-elements npm React UI components react-elements
@authdog/nextjs-app npm Next.js App Router SDK nextjs-app
@authdog/remix-node npm Remix SDK remix-node
@authdog/tanstack-start npm TanStack Start SDK tanstack-start
@authdog/vue npm Vue SDK vue
@authdog/astro npm Astro SDK astro
@authdog/sveltekit npm SvelteKit SDK sveltekit
@authdog/angular npm Angular SDK angular
@authdog/express npm Express SDK express
@authdog/fastify npm Fastify SDK fastify
@authdog/react-native npm React Native / Expo SDK react-native
@authdog/node-commons npm Shared Node utilities node-commons

Backend SDKs for other languages

Package Registry Description CI
authdog-fastapi PyPI Python SDK β€” FastAPI, Flask, Django, Starlette, aiohttp python
authdog (Go) github.com/authdog/web-sdk/packages/go Go SDK with Gin middleware go
authdog-axum & friends crates.io Rust workspace β€” Axum, Actix, Rocket, Warp, Poem rust
authdog-ktor Maven Central Kotlin / Ktor SDK kotlin

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.

πŸš€ 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

# 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

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:

Framework Variable Where it's read
Next.js (client) NEXT_PUBLIC_PK_AUTHDOG Exposed to the browser by Next.js
Next.js (server) PK_AUTHDOG Server-only (logout, etc.)
Remix PK_AUTHDOG Loaders / actions
TanStack Start PK_AUTHDOG Server functions / route loaders
Express (backend) PK_AUTHDOG createAuthdog({ publicKey })
Fastify (backend) AUTHDOG_PK authdogPlugin({ publicKey })
Vue VITE_AUTHDOG_PUBLIC_KEY Vite-exposed (use the VITE_ prefix)
Astro PUBLIC_AUTHDOG_PUBLIC_KEY Exposed via Astro's PUBLIC_ prefix
SvelteKit PUBLIC_AUTHDOG_PUBLIC_KEY Exposed via SvelteKit's PUBLIC_ prefix
React Native / Expo EXPO_PUBLIC_PK_AUTHDOG Exposed to the app by Expo
Angular β€” Passed directly to provideAuthdog(...)
Python (all) PK_AUTHDOG Authdog(public_key=...)
Go (Gin) PK_AUTHDOG authdog.New(authdog.Config{PublicKey})
Rust (all) PK_AUTHDOG Authdog::new(...)
Kotlin (Ktor) PK_AUTHDOG Authdog(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";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="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";

export default function Profile() {
  const { user, isLoading } = useUser();
  return <UserProfile loading={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>
    <p v-if="isLoading">Loading…</p>
    <p v-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.ts
import { defineMiddleware } from "astro:middleware";
import { authdogMiddleware } from "@authdog/astro/server";

export const onRequest = defineMiddleware(
  authdogMiddleware({ publicKey: import.meta.env.PUBLIC_AUTHDOG_PUBLIC_KEY }),
);
---
// src/pages/profile.astro
import { createAuthdogServer } from "@authdog/astro/server";

const authdog = createAuthdogServer({ publicKey: import.meta.env.PUBLIC_AUTHDOG_PUBLIC_KEY });
const user = Astro.locals.authdog.isAuthenticated ? await authdog.getUser(Astro.request) : null;
---

{user ? <p>Welcome, {user.user?.displayName}</p> : <a href="/login">Sign in</a>}

SvelteKit

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

// src/hooks.server.ts
import { createAuthdogHandle } from "@authdog/sveltekit/server";

export const handle = createAuthdogHandle({
  publicKey: import.meta.env.PUBLIC_AUTHDOG_PUBLIC_KEY,
});
// src/routes/profile/+page.server.ts
import { createAuthdogServer } from "@authdog/sveltekit/server";
import type { PageServerLoad } from "./$types";

const authdog = createAuthdogServer({ publicKey: import.meta.env.PUBLIC_AUTHDOG_PUBLIC_KEY });

export const load: PageServerLoad = async ({ request, locals }) => {
  const user = locals.authdog.isAuthenticated ? await authdog.getUser(request) : null;
  return { user: user?.user ?? null };
};

Remix

// app/routes/_index.tsx
import { remixAuthLoader } from "@authdog/remix-node";

export const loader = 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.tsx
import { createServerFn } from "@tanstack/react-start";
import { getWebRequest } from "@tanstack/react-start/server";
import { identityLoader } from "@authdog/tanstack-start";

export const loadIdentity = createServerFn({ method: "GET" }).handler(async () => {
  const response = await identityLoader()({ request: getWebRequest() });
  return response.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";

export const appConfig = {
  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({ /* … */ })
export class ProfileComponent {
  readonly auth = inject(AuthdogService);
  // auth.isLoading(), auth.token(), auth.user() β€” signals
  // auth.signIn(), auth.signUp(), auth.signOut(), auth.fetchUser()
}

Express

import express from "express";
import { createAuthdog } from "@authdog/express";

const app = express();
const authdog = createAuthdog({ publicKey: process.env.PK_AUTHDOG! });

app.use(authdog.attachSession()); // resolves `req.authdog` for every request
app.get("/me", authdog.requireAuth, (req, res) => res.json(req.authdog!.user));
app.get("/logout", authdog.logout);

Fastify

import Fastify from "fastify";
import { authdogPlugin } from "@authdog/fastify";

const app = Fastify();
await app.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)

import os
from fastapi import Depends, FastAPI, Request
from authdog.fastapi import Authdog

app = FastAPI()
authdog = Authdog(public_key=os.environ["PK_AUTHDOG"])

@app.get("/me")
async def me(user=Depends(authdog.require_auth)):  # require_auth is the gate
    return user

@app.get("/logout")
async def logout(request: Request):
    return authdog.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 request
r.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);

async fn me(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)

import com.authdog.Authdog

fun 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 * as SecureStore from "expo-secure-store";
import { AuthdogProvider, createSecureStoreAdapter } from "@authdog/react-native";

export default function App() {
  return (
    <AuthdogProvider
      publicKey={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.

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:

Example Package showcased Run
examples/nextjs-app @authdog/nextjs-app + @authdog/react-elements moon run nextjs-app-sample:dev
examples/remix @authdog/remix-node + @authdog/react-elements moon 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/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:

Command Description
just build Build all publishable packages
just dev-next Run the Next.js demo app
just dev-remix Run the Remix demo app
just ui Launch the Storybook component explorer
just ci Run 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, 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
β”‚   β”œβ”€β”€ angular/          # Angular SDK
β”‚   β”œβ”€β”€ express/          # Express SDK
β”‚   β”œβ”€β”€ fastify/          # Fastify SDK
β”‚   β”œβ”€β”€ react-native/     # React Native / Expo 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

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors