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:3000for 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
- 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>
- 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
| Field | Required | Default | Description |
|---|---|---|---|
clientId | Yes | - | Your Civic Auth client ID from auth.civic.com |
targetContainerElement | No | - | DOM element where embedded iframe will be rendered |
redirectUrl | No | Current URL | OAuth redirect URL after authentication |
displayMode | No | modal | How the auth UI is displayed: embedded, modal, redirect, or new_tab |
scopes | No | ['openid', 'profile', 'email'] | OAuth scopes to request |
loginUrl | No | - | Backend URL for login redirect (enables backend integration) |
backendEndpoints | No | See below | Custom 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 elementmodal: The auth UI opens in a modal overlay on top of your current pageredirect: Full page navigation to the Civic auth server and back to your sitenew_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