Quick Start

Prerequisites

  • A Civic Auth Client ID (get it from auth.civic.com)
  • Configure your redirect URL in the Civic Auth dashboard (typically http://localhost:3000 for development)

Installation

NPM
npm install @civic/auth
We highly recommend using Vite for the best development experience with modern JavaScript features, fast hot reloading, and seamless ES module support.
npm create vite@latest my-civic-app -- --template vanilla
cd my-civic-app
npm install
npm install @civic/auth

Simple Setup

  1. HTML:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My App with Civic Auth</title>
  </head>
  <body>
    <h1>My App</h1>

    <button id="loginButton">Sign In</button>
    <button id="logoutButton">Sign Out</button>

    <!-- Only needed for embedded display mode -->
    <div id="authContainer"></div>

    <script type="module" src="main.js"></script>
  </body>
</html>
  1. JavaScript (main.js):
import { CivicAuth } from "@civic/auth/vanillajs";

// Initialize auth directly with top-level await
const authClient = await CivicAuth.create({
  clientId: "YOUR_CLIENT_ID",
});

// Sign in
document.getElementById("loginButton").addEventListener("click", async () => {
  try {
    const { user } = await authClient.startAuthentication();
  } catch (error) {
    console.error("Authentication failed:", error);
  }
});

// Sign out
document.getElementById("logoutButton").addEventListener("click", async () => {
  await authClient?.logout();
});
That’s it! Replace YOUR_CLIENT_ID with your actual client ID and you’re done.

Alternative: Backend Integration

If you prefer backend session management, you can configure the client to get login URLs from your Express backend. The magic is the loginUrl option:
import { CivicAuth } from "@civic/auth/vanillajs";

// Configure client to use your backend for login URLs
const authClient = await CivicAuth.create({
  loginUrl: "https://your-backend.com/auth/login-url", // The magic!
});

// Now authentication works through your backend
const { user } = await authClient.startAuthentication();

Custom Backend Endpoints

When using backend integration, you can customize the API endpoints that the client calls on your backend:
import { CivicAuth } from "@civic/auth/vanillajs";

const authClient = await CivicAuth.create({
  loginUrl: "https://your-backend.com/auth/login-url",
  backendEndpoints: {
    refresh: "/api/v1/auth/refresh", // default: "/auth/refresh"
    logout: "/api/v1/auth/logout", // default: "/auth/logout"
    user: "/api/v1/auth/user", // default: "/auth/user"
  },
});
The backendEndpoints configuration is only used when loginUrl is provided. Each endpoint is optional - if not specified, the default will be used.

Configuration Options

FieldRequiredDefaultDescription
clientIdYes-Your Civic Auth client ID from auth.civic.com
targetContainerElementNo-DOM element where embedded iframe will be rendered
redirectUrlNoCurrent URLOAuth redirect URL after authentication
displayModeNomodalHow the auth UI is displayed: embedded, modal, redirect, or new_tab
scopesNo['openid', 'profile', 'email']OAuth scopes to request
loginUrlNo-Backend URL for login redirect (enables backend integration)
backendEndpointsNoSee belowCustom backend API endpoints (only used with loginUrl)

Backend Endpoints Default Values

When using loginUrl for backend integration, the following default endpoints are used:
backendEndpoints: {
  refresh: "/auth/refresh",  // Token refresh endpoint
  logout: "/auth/logout",    // Logout endpoint
  user: "/auth/user"         // User info endpoint
}

Display Modes

The displayMode option controls how the authentication UI is presented:
  • embedded (default): The auth UI loads in an iframe within your specified container element
  • modal: The auth UI opens in a modal overlay on top of your current page
  • redirect: Full page navigation to the Civic auth server and back to your site
  • new_tab: Opens auth flow in a new browser tab/popup window

Logout

Logging out is very simple.
const logout = async () => {
  await authClient?.logout();
  // ...
};
User object access:
  • Use authClient.getCurrentUser() to retrieve current user information before logout
  • Use authClient.isAuthenticated() to check if user is currently logged in

Troubleshooting

Module Resolution Error

If you encounter an error like Failed to resolve module specifier "@civic/auth/vanillajs", this is typically caused by a corrupted module cache or installation issue. Solution:
# Clear node_modules and package-lock.json, then reinstall
rm -rf node_modules package-lock.json
npm install
For Vite users:
# Also clear Vite's cache
rm -rf node_modules package-lock.json .vite
npm install
This issue can occur when switching between different versions of the @civic/auth package or when the package installation is interrupted.

Common Issues

  • CORS errors: Ensure your redirect URL in the Civic Auth dashboard exactly matches your development server URL
  • Authentication not starting: Verify your client ID is correct and your redirect URL is properly configured
  • Container element not found: Make sure the target container element exists in the DOM before initializing Civic Auth

API Reference

CivicAuth Class

startAuthentication()

Initiates the authentication process. Returns: Promise that resolves when authentication completes or rejects on error

getCurrentUser()

Retrieves the current authenticated user’s information. Returns: Promise that resolves to a user object or null if not authenticated

isAuthenticated()

Checks if a user is currently authenticated. Returns: Promise that resolves to a boolean indicating authentication status

logout()

Logs out the user. Returns a boolean or throws an error if unsuccessful