Skip to main content

Vanilla JavaScript

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
tip

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"
},
});
note

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