JSPM

@usetransactional/better-auth

0.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 3
  • Score
    100M100P100Q32229F
  • License MIT

Better Auth plugin for Transactional Auth

Package Exports

  • @usetransactional/better-auth
  • @usetransactional/better-auth/client

Readme

transactional-better-auth

Official Better Auth plugin for Transactional Auth.

Installation

npm install transactional-better-auth better-auth

Quick Start

Server Setup

// lib/auth.ts
import { betterAuth } from "better-auth";
import { transactional } from "transactional-better-auth";

export const auth = betterAuth({
  database: { /* your database config */ },
  plugins: [
    transactional({
      clientId: process.env.TRANSACTIONAL_CLIENT_ID!,
      clientSecret: process.env.TRANSACTIONAL_CLIENT_SECRET!,
      authDomain: "your-app.auth.usetransactional.com",
    })
  ]
});

Client Setup

// lib/auth-client.ts
import { createAuthClient } from "better-auth/react";
import { transactionalClient } from "transactional-better-auth/client";

export const authClient = createAuthClient({
  plugins: [transactionalClient()]
});

export const { signIn, signOut, useSession } = authClient;

Login

// Sign in with Transactional Auth
signIn.oauth2({
  providerId: "transactional",
  callbackURL: "/dashboard"
});

Or use the helper function:

import { createTransactionalSignInOptions } from "transactional-better-auth/client";

// Creates { providerId: "transactional", callbackURL: "/dashboard" }
signIn.oauth2(createTransactionalSignInOptions({
  callbackURL: "/dashboard"
}));

Configuration

Required Options

Option Type Description
clientId string OAuth client ID from Transactional dashboard
clientSecret string OAuth client secret from Transactional dashboard
authDomain string Your app's auth domain (e.g., your-app.auth.usetransactional.com)

Optional Options

Option Type Default Description
providerId string "transactional" Unique provider identifier
scopes string[] ["openid", "profile", "email"] OAuth scopes to request
pkce boolean true Enable PKCE (required by Transactional)
mapProfileToUser function (see below) Custom profile mapping
disableSignUp boolean false Disable automatic sign-up
prompt string - OAuth prompt behavior
accessType string - Use "offline" for refresh tokens

Redirect URI

Add this redirect URI in your Transactional dashboard:

https://yourapp.com/api/auth/callback/transactional

Examples

Basic Usage

transactional({
  clientId: process.env.TRANSACTIONAL_CLIENT_ID!,
  clientSecret: process.env.TRANSACTIONAL_CLIENT_SECRET!,
  authDomain: "your-app.auth.usetransactional.com",
})

Custom Scopes

transactional({
  clientId: "...",
  clientSecret: "...",
  authDomain: "...",
  scopes: ["openid", "profile", "email", "offline_access"],
})

Custom Profile Mapping

transactional({
  clientId: "...",
  clientSecret: "...",
  authDomain: "...",
  mapProfileToUser: (profile) => ({
    id: profile.sub as string,
    name: profile.name as string,
    email: profile.email as string,
    companyId: profile.org_id,
    role: profile.org_role,
    avatarUrl: profile.picture,
  }),
})

Disable Auto Sign-Up

transactional({
  clientId: "...",
  clientSecret: "...",
  authDomain: "...",
  disableSignUp: true,
})

Force Re-authentication

transactional({
  clientId: "...",
  clientSecret: "...",
  authDomain: "...",
  prompt: "login",
})

Custom Authorization Parameters

transactional({
  clientId: "...",
  clientSecret: "...",
  authDomain: "...",
  authorizationUrlParams: {
    organization: "org_123",
    login_hint: "user@company.com",
  },
})

Override Discovery URLs

transactional({
  clientId: "...",
  clientSecret: "...",
  authDomain: "...",
  authorizationUrl: "https://custom.auth.com/auth",
  tokenUrl: "https://custom.auth.com/token",
  userInfoUrl: "https://custom.auth.com/me",
})

Custom Provider ID

// Server
transactional({
  clientId: "...",
  clientSecret: "...",
  authDomain: "...",
  providerId: "my-transactional",
})

// Client - must match!
transactionalClient({
  providerId: "my-transactional",
})

// Sign in with custom provider ID
signIn.oauth2({
  providerId: "my-transactional",
  callbackURL: "/dashboard"
});

Default Profile Mapping

By default, the plugin maps Transactional OIDC claims to Better Auth user fields:

{
  id: profile.sub,
  name: profile.name,
  email: profile.email,
  image: profile.picture,
  emailVerified: profile.email_verified,
  // Organization info (if present)
  organizationId: profile.org_id,
  organizationName: profile.org_name,
  organizationRole: profile.org_role,
}

API Reference

Server Plugin

import { transactional } from "transactional-better-auth";

const plugin = transactional(options: TransactionalOptions);

Client Plugin

import { transactionalClient, createTransactionalSignInOptions } from "transactional-better-auth/client";

// Add the plugin
const authClient = createAuthClient({
  plugins: [transactionalClient()]
});

// Sign in using oauth2 method
authClient.signIn.oauth2({
  providerId: "transactional",
  callbackURL: "/dashboard",
  errorCallbackURL: "/login?error=true",
  newUserCallbackURL: "/welcome",
  disableRedirect: false,
  scopes: ["custom:scope"],
  requestSignUp: true,
});

// Or use the helper function
authClient.signIn.oauth2(createTransactionalSignInOptions({
  callbackURL: "/dashboard"
}));

How It Works

This plugin wraps Better Auth's genericOAuth plugin with Transactional-specific defaults:

  1. Auto-discovers endpoints from https://{authDomain}/.well-known/openid-configuration
  2. Maps user profile from Transactional's OIDC claims to Better Auth's user model
  3. Configures PKCE (required by Transactional Auth)
  4. Provides type-safe client with signIn.oauth2() using the "transactional" provider
  5. Handles organization claims - extracts org_id from ID token

License

MIT