Next Identity JavaScript SDK
The Next Identity JavaScript SDK provides a simple, framework-agnostic way to integrate OpenID Connect (OIDC) authentication into web applications.
It supports login, signup, profile management, protected pages, and logout using industry-standard OAuth 2.0 with PKCE (Proof Key for Code Exchange) for enhanced security — without requiring server-side code.
Table of Contents
Installation
Initialization
Authentication Actions
Authentication State
Protecting Your Application
Framework-Specific Auth Guards
Authenticated Components
User Interface Components
Events
API Reference
Complete Examples
Troubleshooting
Installation
Add the Next Identity SDK script inside the <head> tag of your HTML file.
<!DOCTYPE html>
<html>
<head>
<title>My Application</title>
<script src="https://idp.dev.nextidentity.io/sdk/ni-auth-js-sdk-1.0.0.min.js"></script>
</head>
<body>
</body>
</html>Important
The SDK must be loaded in the
<head>, not inside the<body>.
Once loaded, the SDK exposes a globalNextIdentityobject.
Initialization
Initialize the SDK at the end of the <body>, after your application content.
<body>
<!-- Your application content -->
<!-- Initialize the SDK at the end of the body -->
<script>
NextIdentity.Init({
client_id: "your-client-id",
issuer: "https://your-tenant.id.nextreason.com",
login_redirect_uri: "https://yoursite.com/dashboard",
logout_redirect_uri: "https://yoursite.com"
});
</script>
</body>
Configuration Options
Option | Type | Required | Default | Description |
|---|---|---|---|---|
client_id | string | Yes | — | Client ID provided by Next Identity |
issuer | string | Yes | — | Your Next Identity tenant URL |
login_redirect_uri | string | No |
| Redirect after login/signup |
logout_redirect_uri | string | No |
| Redirect after logout |
auto_login | boolean | No |
| Automatically trigger login |
Example
NextIdentity.Init({
client_id: "fcdbc9150ff2400d9b72ff8d2022f7ec",
issuer: "https://example.id.nextreason.com",
login_redirect_uri: "https://myapp.com/dashboard",
logout_redirect_uri: "https://myapp.com",
auto_login: false
});
Authentication Actions
1. Trigger Login
Initiates the OIDC authorization flow.
Option A: Programmatic Method
NextIdentity.logIn();
Option B: Data Attribute (Recommended)
Add the data-ni-action="login" attribute to any clickable element:
<button data-ni-action="login">Login</button><a href="#" data-ni-action="login">Sign In</a>Option C: Magic Link
Use the special href value that the SDK automatically detects:
<a href="https://login.nextidentity.io">Sign In</a>
Login Events
window.addEventListener('ni-auth-success', (event) => {
console.log('User:', event.detail.token.user_profile);
});
window.addEventListener('ni-auth-fail', (event) => {
console.error(event.detail.error);
});
2. Trigger Signup
Initiates the OIDC registration flow, redirecting the user to the Next Identity signup page.
Option A: Programmatic Method
NextIdentity.signUp();
Option B: Data Attribute (Recommended)
Add the data-ni-action="signup" attribute to any clickable element:
<button data-ni-action="signup">Sign Up</button><a href="https://signup.nextidentity.io">Create Account</a>Option C: Magic Link
Use the special href value that the SDK automatically detects:
<a href="https://signup.nextidentity.io">Create Account</a>
3. Trigger Profile Management
Redirects the user to the Next Identity account management page where they can update their personal details, change password, and manage their account settings.
Option A: Programmatic Method
NextIdentity.manageProfile();Option B: Data Attribute
Add the data-ni-action="profile" attribute to any clickable element:
<button data-ni-action="profile">Manage Account</button><a href="#" data-ni-action="profile">My Profile</a>Option C: Built-in User Menu
After successful authentication, the SDK automatically renders a user menu dropdown that includes a "Profile" option. See Built-in User Menu for details.
4. Trigger Logout
Ends the user's session by clearing stored tokens and redirecting to the Next Identity logout endpoint.
Option A: Programmatic Method
NextIdentity.logOut();Option B: Data Attribute
Add the data-ni-action="logout" attribute to any clickable element:
<button data-ni-action="logout">Sign Out</button><a href="#" data-ni-action="logout">Logout</a>Option C: Magic Link
Use the special href value that the SDK automatically detects:
<a href="https://logout.nextidentity.io">Sign Out</a>Option D: Built-in User Menu
The SDK's automatically rendered user menu includes a "Logout" option.
Logout Behavior
Clears all tokens from
localStorageClears OIDC state from
sessionStorageRedirects to the Next Identity end session endpoint
After IdP logout, redirects to your configured
logout_redirect_uri
Logout Events
window.addEventListener('ni-logout-fail', (event) => {
console.error('Logout failed:', event.detail.error);
});Authentication State
Check Authentication Status
Returns a boolean indicating whether the user is currently authenticated with a valid, non-expired token.
const isAuthenticated = NextIdentity.isAuthenticated();
if (isLoggedIn) {
console.log('User is authenticated');
} else {
console.log('User is not authenticated');
}
Safe framework pattern
const isAuthenticated =
window.NextIdentity?.isAuthenticated?.() ?? false;
Get Stored Token Data
Retrieves the complete token data object stored after successful authentication. Returns null if the user is not authenticated.
const tokenData = NextIdentity.getTokenData();
if (tokenData) {
console.log('Access Token:', tokenData.access_token);
console.log('ID Token:', tokenData.id_token);
console.log('Refresh Token:', tokenData.refresh_token);
console.log('Expires At:', tokenData.expires_at);
console.log('User Profile:', tokenData.user_profile);
}
Token structure
Property | Type | Description |
|---|---|---|
access_token | string | OAuth access token |
id_token | string | OIDC ID token |
refresh_token | string | Refresh token |
expires_at | number | Expiration timestamp |
user_profile | object | Decoded user claims |
User Profile Structure
Property | Type | Description |
id | string | Unique user identifier (subject claim) |
name | string | User's display name |
string | User's email address | |
username | string | Username (typically the email) |
firstname | string | User's first name |
lastname | string | User's last name |
Example: Using Access Token for API Calls
async function fetchProtectedData() {
const tokenData = NextIdentity.getTokenData();
if (!tokenData) {
throw new Error('User not authenticated');
}
const response = await fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${tokenData.access_token}`
}
});
return response.json();
}
Example: Displaying User Information
function displayUserInfo() {
const tokenData = NextIdentity.getTokenData();
if (tokenData) {
const user = tokenData.user_profile;
document.getElementById('welcome-message').textContent = `Welcome, ${user.firstName}!`;
document.getElementById('user-email').textContent = user.email;
}
}Authentication Check with Redirect
Verifies the user's authentication status and automatically redirects unauthenticated users to the configured logout_redirect_uri. Use this method to protect pages that require authentication.
NextIdentity.checkUserAuth();
Events
// Authentication check successful
window.addEventListener('ni-check-auth-success', (event) => {
console.log('User verified:', event.detail.user);
console.log('Token data:', event.detail.tokenData);
});
// Authentication check failed
window.addEventListener('ni-check-auth-fail', (event) => {
console.error('Auth check failed:', event.detail.error);
});Protecting Your Application
Protect Entire Pages
You can restrict access to entire pages, ensuring only authenticated users can view them. Unauthenticated users are automatically redirected away.
Option A: Body Attribute
Add the data-ni-auth-page attribute to the page's <body> tag:
<!DOCTYPE html>
<html>
<head>
<title>Dashboard - Protected Page</title>
<script src="https://idp.dev.nextidentity.io/sdk/ni-auth-js-sdk-1.0.0.min.js"></script>
</head>
<body data-ni-auth-page>
<h1>Dashboard</h1>
<p>This content is only accessible to authenticated users.</p>
<script>
NextIdentity.Init({
client_id: 'your-client-id',
issuer: 'https://your-tenant.id.nextreason.com',
logout_redirect_uri: 'https://yoursite.com'
});
</script>
</body>
</html>When data-ni-auth-page is present, the SDK automatically checks authentication status on page load. If the user is not authenticated or their token has expired, they are redirected to window.location.origin.
Option B: Programmatic
Use checkUserAuth() at the top of your protected page's script:
NextIdentity.Init({
client_id: 'your-client-id',
issuer: 'https://your-tenant.id.nextreason.com',
logout_redirect_uri: 'https://yoursite.com'
});
// Redirects unauthenticated users to logout_redirect_uri
NextIdentity.checkUserAuth();Option C: Custom Logic
For more control over the redirect behavior, use isAuthenticated():
if (!NextIdentity.isAuthenticated()) {
// Custom redirect logic with return URL
window.location.href = '/?returnUrl=' + encodeURIComponent(window.location.pathname);
} else {
// User is authenticated, initialize the page
initializeDashboard();
}Prevent Flash of Protected Content
To prevent unauthenticated users from briefly seeing protected content before being redirected:
<style>
.protected-content {
visibility: hidden;
}
.protected-content.authenticated {
visibility: visible;
}
</style>
<body data-ni-auth-page>
<div class="protected-content">
<h1>Secret Dashboard</h1>
<!-- Protected content here -->
</div>
<script>
NextIdentity.Init({
client_id: 'your-client-id',
issuer: 'https://your-tenant.id.nextreason.com'
});
window.addEventListener('ni-check-auth-success', () => {
document.querySelector('.protected-content').classList.add('authenticated');
});
</script>
</body>
Page Protection Methods Comparison
Method | Use Case | Redirect Target |
data-ni-auth-page | Simple protection, minimal code | window.location.origin |
checkUserAuth() | Programmatic control |
|
isAuthenticated() | Custom logic, conditional redirects | Your custom URL |
Framework-Specific Auth Guards
For single-page applications (SPAs) using modern frameworks, create an Auth Guard using the appropriate pattern for your framework.
Base Authentication Check
All framework implementations should use this pattern to check authentication:
const isAuthenticated = window.NextIdentity?.isAuthenticated?.() ?? false;React Auth Guard
Create a reusable wrapper component:
// components/AuthGuard.jsx
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
export function AuthGuard({ children }) {
const navigate = useNavigate();
const isAuthenticated = window.NextIdentity?.isAuthenticated?.() ?? false;
useEffect(() => {
if (!isAuthenticated) {
navigate('/');
}
}, [isAuthenticated, navigate]);
if (!isAuthenticated) {
return null; // or a loading spinner
}
return children;
}
Usage:
// App.jsx
import { AuthGuard } from './components/AuthGuard';
function App() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/dashboard" element={
<AuthGuard>
<DashboardPage />
</AuthGuard>
} />
</Routes>
);
}Vue Auth Guard
Create a navigation guard:
// guards/authGuard.js
export function authGuard(to, from, next) {
const isAuthenticated = window.NextIdentity?.isAuthenticated?.() ?? false;
if (!isAuthenticated) {
next('/');
} else {
next();
}
}Usage:
// router/index.js
import { authGuard } from '@/guards/authGuard';
const routes = [
{ path: '/', component: HomePage },
{
path: '/dashboard',
component: DashboardPage,
beforeEnter: authGuard
}
];Angular Auth Guard
Create a CanActivate guard service:
// guards/auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
declare global {
interface Window {
NextIdentity?: {
isAuthenticated?: () => boolean;
};
}
}
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private router: Router) {}
canActivate(): boolean {
const isAuthenticated = window.NextIdentity?.isAuthenticated?.() ?? false;
if (!isAuthenticated) {
this.router.navigate(['/']);
return false;
}
return true;
}
}Usage:
// app-routing.module.ts
const routes: Routes = [
{ path: '', component: HomeComponent },
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuard]
}
];Plain JavaScript / Multi-Page Application (MPA)
Create a reusable function for protected pages:
// auth-guard.js
function requireAuth(redirectUrl = '/') {
const isAuthenticated = window.NextIdentity?.isAuthenticated?.() ?? false;
if (!isAuthenticated) {
window.location.href = redirectUrl;
return false;
}
return true;
}Usage on protected pages:
<script src="/js/auth-guard.js"></script>
<script>
// Redirect to home if not authenticated
requireAuth('/');
</script>Authenticated Components
Mark elements to only be visible when the user is authenticated:
Using Data Attribute
<div data-ni-auth-component="true">
Authenticated content
</div>
Using CSS Class
<div class="ni-auth-component">
<button data-ni-action="profile">My Account</button>
<button data-ni-action="logout">Sign Out</button>
</div>Behavior
Elements are hidden by default (
visibility: hidden)After successful authentication, elements become visible
If the user is not authenticated, elements are removed from the DOM after a short delay
User Interface Components
Login and Signup Buttons
Add login and signup buttons to your application header or navigation:
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<!-- Authentication buttons -->
<button data-ni-action="login">Login</button>
<button data-ni-action="signup">Sign Up</button>
</nav>
</header>
Note: After successful authentication, the SDK automatically hides these buttons and displays a user menu in their place.
Styled Example
<style>
.auth-buttons button {
padding: 8px 16px;
margin-left: 8px;
border-radius: 4px;
cursor: pointer;
}
.auth-buttons button[data-ni-action="login"] {
background: transparent;
border: 1px solid #333;
}
.auth-buttons button[data-ni-action="signup"] {
background: #007bff;
color: white;
border: none;
}
</style>
<div class="auth-buttons">
<button data-ni-action="login">Login</button>
<button data-ni-action="signup">Sign Up</button>
</div>Built-in User Menu
After successful authentication, the SDK automatically creates a user menu dropdown that replaces the login button. The menu displays:
User's initials in a circular avatar
User's name and email
Profile link (redirects to account management)
Logout link
Automatic Rendering
The user menu is automatically rendered when:
The SDK detects a login button (
data-ni-action="login"orhref="https://login.nextidentity.io")The user is authenticated
The menu is injected as a sibling to the login button, wrapped in a .ni-user-info-wrapper container.
Menu Structure
┌─────────────────────┐
│ [AB] ←── Avatar │
├─────────────────────┤
│ Alice Brown │
│ alice@example.com │
├─────────────────────┤
│ 👤 Profile │
│ 🚪 Logout │
└─────────────────────┘Customizing User Menu Styles
The built-in user menu has inline styles, but you can override them:
/* Override wrapper styles */
.ni-user-info-wrapper {
/* Your custom styles */
}
/* Override menu dropdown styles */
.ni-user-info-menu {
/* Your custom styles */
}Events
The SDK dispatches custom events that you can listen to for handling authentication state changes.
Event Reference
Event | Trigger | Description |
|---|---|---|
ni-auth-success | Successful login/signup |
|
ni-auth-fail | Login/signup failed |
|
ni-login-fail | Login initiation failed |
|
ni-logout-fail | Logout failed |
|
ni-check-auth-success | Auth check passed |
|
ni-check-auth-fail | Auth check failed |
|
Listening to Events
// Handle successful authentication
window.addEventListener('ni-auth-success', (event) => {
const { token } = event.detail;
console.log('User logged in:', token.user_profile.name);
// Redirect to dashboard or update UI
window.location.href = '/dashboard';
});
// Handle authentication failure
window.addEventListener('ni-auth-fail', (event) => {
console.error('Authentication failed:', event.detail.error);
showErrorMessage('Login failed. Please try again.');
});
// Handle auth check success (for protected pages)
window.addEventListener('ni-check-auth-success', (event) => {
const { user, tokenData } = event.detail;
console.log('Authenticated user:', user.email);
initializeProtectedPage(tokenData);
});API Reference
Methods
Method | Description | Parameters | Returns |
|---|---|---|---|
Init() | Initialize SDK |
| void |
logIn() | Start login | — | void |
signUp() | Start signup | — | void |
manageProfile() | Open profile | — | void |
logOut() | Logout | — | void |
isAuthenticated() | Auth status | — | boolean |
getTokenData() | Token data | — | object | null |
checkUserAuth() | Verify auth | — | void |
Data Attributes
Attribute | Value | Element | Description |
|---|---|---|---|
|
| Any clickable | Triggers login flow on click |
|
| Any clickable | Triggers signup flow on click |
|
| Any clickable | Triggers logout flow on click |
|
| Any clickable | Triggers profile management on click |
| — |
| Protects entire page, redirects if unauthenticated |
|
| Any element | Shows element only when authenticated |
CSS Classes
Class | Description |
|---|---|
| Shows element only when authenticated |
| Container for the built-in user menu |
| The dropdown menu element |
Magic Links
URL | Action |
|---|---|
| Triggers login flow |
| Triggers signup flow |
| Triggers logout flow |
Complete Examples
Basic HTML Integration
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<script src="https://idp.dev.nextidentity.io/sdk/ni-auth-js-sdk-1.0.0.min.js"></script>
<style>
nav { display: flex; gap: 16px; align-items: center; padding: 16px; }
nav a { text-decoration: none; color: #333; }
.spacer { flex: 1; }
button { padding: 8px 16px; cursor: pointer; }
</style>
</head>
<body>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<span class="spacer"></span>
<button data-ni-action="login">Login</button>
<button data-ni-action="signup">Sign Up</button>
</nav>
<main>
<h1>Welcome to My App</h1>
<!-- Only visible when authenticated -->
<div data-ni-auth-component="true">
<p>You are logged in!</p>
<button data-ni-action="profile">Manage Account</button>
</div>
</main>
<script>
NextIdentity.Init({
client_id: "your-client-id",
issuer: "https://your-tenant.id.nextreason.com",
login_redirect_uri: window.location.origin,
logout_redirect_uri: window.location.origin
});
// Handle successful authentication
window.addEventListener('ni-auth-success', (event) => {
const user = event.detail.token.user_profile;
console.log(`Welcome, ${user.name}!`);
});
</script>
</body>
</html>Protected Dashboard Page
<!DOCTYPE html>
<html>
<head>
<title>Dashboard - My App</title>
<script src="https://idp.dev.nextidentity.io/sdk/ni-auth-js-sdk-1.0.0.min.js"></script>
<style>
.dashboard { padding: 20px; visibility: hidden; }
.dashboard.ready { visibility: visible; }
</style>
</head>
<body data-ni-auth-page>
<nav>
<a href="/">Home</a>
<button data-ni-action="logout">Sign Out</button>
</nav>
<main class="dashboard">
<h1>Dashboard</h1>
<div id="user-info"></div>
</main>
<script>
NextIdentity.Init({
client_id: "your-client-id",
issuer: "https://your-tenant.id.nextreason.com",
logout_redirect_uri: window.location.origin
});
window.addEventListener('ni-check-auth-success', (event) => {
const user = event.detail.user;
// Display user info
document.getElementById('user-info').innerHTML = `
<p>Welcome back, <strong>${user.name}</strong>!</p>
<p>Email: ${user.email}</p>
`;
// Show the dashboard
document.querySelector('.dashboard').classList.add('ready');
});
</script>
</body>
</html>React SPA Integration
// index.html - Add SDK to head
<head>
<script src="https://idp.dev.nextidentity.io/sdk/ni-auth-js-sdk-1.0.0.min.js"></script>
</head>
// App.jsx
import { useEffect } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { AuthGuard } from './components/AuthGuard';
import HomePage from './pages/HomePage';
import DashboardPage from './pages/DashboardPage';
function App() {
useEffect(() => {
window.NextIdentity?.Init({
client_id: "your-client-id",
issuer: "https://your-tenant.id.nextreason.com",
login_redirect_uri: window.location.origin + '/dashboard',
logout_redirect_uri: window.location.origin
});
}, []);
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/dashboard" element={
<AuthGuard>
<DashboardPage />
</AuthGuard>
} />
</Routes>
</BrowserRouter>
);
}
// components/AuthGuard.jsx
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
export function AuthGuard({ children }) {
const navigate = useNavigate();
const [isReady, setIsReady] = useState(false);
useEffect(() => {
const isAuthenticated = window.NextIdentity?.isAuthenticated?.() ?? false;
if (!isAuthenticated) {
navigate('/');
} else {
setIsReady(true);
}
}, [navigate]);
if (!isReady) return <div>Loading...</div>;
return children;
}
// components/Header.jsx
export function Header() {
return (
<header>
<nav>
<a href="/">Home</a>
<button data-ni-action="login">Login</button>
<button data-ni-action="signup">Sign Up</button>
</nav>
</header>
);
}Troubleshooting
SDK not loading
Script must be in
<head>Check network errors
Login not working
Validate
client_idandissuerConfirm redirect URIs
User menu missing
Ensure a login button exists
Check
isAuthenticated()
Debugging
// Check if authenticated
console.log('Authenticated:', NextIdentity.isAuthenticated());
// View token data
console.log('Token data:', NextIdentity.getTokenData());
// View stored tokens (raw)
console.log('Raw tokens:', localStorage.getItem('oidc_tokens'));
