@authaz/sdk
v1.0.16
Published
Authaz SDK for session management
Readme
Authaz SDK for JavaScript
Official JavaScript/TypeScript SDK for Authaz authentication platform. Provides secure user authentication, OAuth2/OIDC Universal Login, and session management for modern web applications.
Features
- Universal Login Flow - OAuth2/OIDC authentication with PKCE
- User Management - Profile retrieval and user data management
- Session Management - Secure cookie-based session handling
- Type Safety - Full TypeScript support with comprehensive type definitions
- Next.js Integration - Built-in support for Next.js applications
- Automatic Token Management - Handles CSRF, session, and API tokens automatically
- Environment Detection - Automatic configuration for development and production
Installation
npm install @authaz/sdkRequirements
- Node.js 16 or higher
- Next.js 13 or higher
- TypeScript 4.5 or higher (recommended)
Quick Start
Initialize the SDK
import { ApiService } from '@authaz/sdk'
const authaz = new ApiService(
'your-client-id',
'your-client-secret',
'your-auth-pool-id',
'your-organization-id',
'https://yourapp.com/callback',
'your-tenant-id'
)Start Universal Login Flow
// Generate the login URL
const loginResponse = await authaz.getUniversalLoginUrl()
if (loginResponse.status === 'success') {
// Store the code verifier securely (e.g., in session storage)
sessionStorage.setItem('codeVerifier', loginResponse.codeVerifier)
// Redirect user to Authaz login page
window.location.href = loginResponse.url
}Handle OAuth Callback
// After user is redirected back to your app
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')
const state = urlParams.get('state')
const codeVerifier = sessionStorage.getItem('codeVerifier')
if (code && state && codeVerifier) {
const tokenResponse = await authaz.getUniversalLoginAccessToken(
code,
state,
codeVerifier
)
if (tokenResponse.status === 'success') {
// Store tokens and create session
const { accessToken, refreshToken } = tokenResponse
// Get user profile
const userProfile = await authaz.getMe(accessToken.value)
if (userProfile.status === 'success') {
console.log('User:', userProfile.user)
}
}
}Configuration
The SDK automatically configures URLs based on your environment:
Production (NODE_ENV=production)
baseUrl: 'https://api.authaz.com'
authazDomain: 'https://authaz.com'
universalLoginUrl: 'https://authaz.com'Development (default)
baseUrl: 'http://localhost:5138/api'
authazDomain: 'http://localhost:5138'
universalLoginUrl: 'http://localhost:5138'Environment Variables
NODE_ENV=production
AUTHAZ_CLIENT_ID=your-client-id
AUTHAZ_CLIENT_SECRET=your-client-secret
AUTHAZ_AUTH_POOL_ID=your-auth-pool-id
AUTHAZ_ORGANIZATION_ID=your-organization-id
AUTHAZ_REDIRECT_URI=https://yourapp.com/callback
AUTHAZ_TENANT_ID=your-tenant-idCore Features
Universal Login
The SDK implements OAuth2/OIDC authentication with PKCE (Proof Key for Code Exchange) for enhanced security.
Generate Login URL
const loginResponse = await authaz.getUniversalLoginUrl()
if (loginResponse.status === 'success') {
console.log('Login URL:', loginResponse.url)
console.log('Code Verifier:', loginResponse.codeVerifier) // Store securely
}Exchange Authorization Code for Tokens
const tokenResponse = await authaz.getUniversalLoginAccessToken(
authorizationCode,
stateParameter,
codeVerifier
)
if (tokenResponse.status === 'success') {
const { accessToken, refreshToken } = tokenResponse
// Both tokens have { type: 'Bearer', value: 'token-string' }
}User Profile
Retrieve authenticated user information:
const userResponse = await authaz.getMe(accessToken)
switch (userResponse.status) {
case 'success':
console.log('User:', userResponse.user)
// user: { id, email, name, role }
break
case 'unauthorized':
console.error('Invalid or expired token')
break
case 'token_expired':
console.error('Token expired, refresh required')
break
case 'user_not_found':
console.error('User not found')
break
case 'error':
console.error('Error:', userResponse.message)
break
}Session Management
The SDK provides utilities for managing user sessions with secure cookie storage:
import { createSession, getSession, clearSession } from '@authaz/sdk'
// Create session after successful login
await createSession({
accessToken: tokenResponse.accessToken.value,
refreshToken: tokenResponse.refreshToken.value,
expires_in: 3600 // seconds
})
// Get current session
const session = await getSession()
if (session) {
console.log('Access token:', session.accessToken)
console.log('Expires at:', new Date(session.expires_at))
}
// Clear session (logout)
await clearSession()Session cookies are configured with security best practices:
- HttpOnly flag (prevents JavaScript access)
- Secure flag in production (HTTPS only)
- SameSite=Lax (CSRF protection)
- 7-day expiration
Utility Functions
Token Validation
import { validateToken } from '@authaz/sdk'
if (validateToken(accessToken)) {
// Token exists and is not empty
}Secure Headers
import { createSecureHeaders } from '@authaz/sdk'
const headers = createSecureHeaders()
// Returns security headers:
// - Cache-Control: private, no-cache, no-store, must-revalidate
// - X-Content-Type-Options: nosniff
// - X-Frame-Options: DENY
// - X-XSS-Protection: 1; mode=blockResponse Validation
import { validateApiResponse, extractErrorMessage } from '@authaz/sdk'
if (validateApiResponse(response)) {
// Response is OK (status 200-299)
} else {
const errorMessage = await extractErrorMessage(response)
console.error('Error:', errorMessage)
}TypeScript Support
The SDK is written in TypeScript and provides comprehensive type definitions.
Response Types
All SDK methods return typed responses with discriminated unions for type-safe error handling:
import type {
UniversalLoginResponse,
UniversalLoginAccessTokenResponse,
UserResponse
} from '@authaz/sdk'
// Universal Login URL generation
const loginResponse: UniversalLoginResponse = await authaz.getUniversalLoginUrl()
// Token exchange
const tokenResponse: UniversalLoginAccessTokenResponse =
await authaz.getUniversalLoginAccessToken(code, state, verifier)
// User profile
const userResponse: UserResponse = await authaz.getMe(accessToken)HTTP Types
Access raw HTTP response types for custom integrations:
import type { HttpTypes } from '@authaz/sdk'
// Raw server responses
type ApiTokenResponse = HttpTypes.RawApiTokenResponse
type UserProfile = HttpTypes.RawUserProfileResponse
type ErrorResponse = HttpTypes.RawErrorResponseType Guards
Use built-in type guards for response checking:
import { isSuccess, isError, requiresMfa } from '@authaz/sdk'
const response = await authaz.getUniversalLoginUrl()
if (isSuccess(response)) {
// TypeScript knows response has success properties
console.log(response.url)
} else if (isError(response)) {
// TypeScript knows response has error properties
console.error(response.message)
}Common Types
import type {
AccessToken,
RefreshToken,
Session,
User,
ApiResult
} from '@authaz/sdk'
// Token structure
const accessToken: AccessToken = {
type: 'Bearer',
value: 'token-string'
}
// Session structure
const session: Session = {
accessToken: 'token-string',
refreshToken: 'token-string',
expires_at: 1234567890
}
// User structure
const user: User = {
id: 'user-id',
email: '[email protected]',
name: 'User Name',
role: 'admin'
}Error Handling
All SDK methods return responses with a status field for consistent error handling:
Status Codes
UniversalLoginResponse
success- Login URL generated successfullyerror- Error during URL generation
UniversalLoginAccessTokenResponse
success- Access token retrieved successfullyerror- Error during token exchange
UserResponse
success- User data retrieved successfullyunauthorized- Invalid or missing access tokentoken_expired- Access token has expireduser_not_found- User does not existerror- Generic error
Error Handling Pattern
const response = await authaz.getMe(accessToken)
switch (response.status) {
case 'success':
// Handle success
handleUserProfile(response.user)
break
case 'unauthorized':
// Redirect to login
redirectToLogin()
break
case 'token_expired':
// Refresh token and retry
await refreshAccessToken()
break
case 'user_not_found':
// Handle missing user
handleUserNotFound()
break
case 'error':
// Handle generic error
console.error(response.message)
break
}Best Practices
Security
Never expose client secrets in frontend code
// BAD - Don't do this in browser code const authaz = new ApiService(clientId, clientSecret, ...) // GOOD - Use a backend API route // pages/api/auth/init.ts export default function handler(req, res) { const authaz = new ApiService( process.env.AUTHAZ_CLIENT_ID, process.env.AUTHAZ_CLIENT_SECRET, // ... other config ) }Store code verifier securely
// Store in session storage, not local storage sessionStorage.setItem('codeVerifier', loginResponse.codeVerifier)Validate state parameter
// Generate and store state before redirecting const state = crypto.randomUUID() sessionStorage.setItem('oauth_state', state) // Validate state after callback if (callbackState !== sessionStorage.getItem('oauth_state')) { throw new Error('Invalid state parameter') }Use HTTPS in production
// Sessions automatically use secure cookies in production await createSession(tokens) // Secure flag set when NODE_ENV=production
Token Management
Implement token refresh
async function getValidAccessToken() { const session = await getSession() if (!session) { redirectToLogin() return null } // Check if token is expired if (Date.now() >= session.expires_at) { // Implement refresh token logic const newTokens = await refreshAccessToken(session.refreshToken) await createSession(newTokens) return newTokens.accessToken } return session.accessToken }Handle token expiration gracefully
const response = await authaz.getMe(accessToken) if (response.status === 'token_expired' || response.status === 'unauthorized') { await clearSession() redirectToLogin() }
Next.js Integration
Create an API route for initialization
// pages/api/auth/login.ts import { ApiService } from '@authaz/sdk' export default async function handler(req, res) { const authaz = new ApiService( process.env.AUTHAZ_CLIENT_ID, process.env.AUTHAZ_CLIENT_SECRET, process.env.AUTHAZ_AUTH_POOL_ID, process.env.AUTHAZ_ORGANIZATION_ID, process.env.AUTHAZ_REDIRECT_URI, process.env.AUTHAZ_TENANT_ID ) const loginResponse = await authaz.getUniversalLoginUrl() res.json(loginResponse) }Create a callback handler
// pages/api/auth/callback.ts import { ApiService, createSession } from '@authaz/sdk' export default async function handler(req, res) { const { code, state, codeVerifier } = req.body const authaz = new ApiService(/* ... */) const tokenResponse = await authaz.getUniversalLoginAccessToken( code, state, codeVerifier ) if (tokenResponse.status === 'success') { await createSession({ accessToken: tokenResponse.accessToken.value, refreshToken: tokenResponse.refreshToken.value, expires_in: 3600 }) res.json({ success: true }) } else { res.status(400).json(tokenResponse) } }Use session in pages
// pages/profile.tsx import { getSession } from '@authaz/sdk' import { GetServerSideProps } from 'next' export const getServerSideProps: GetServerSideProps = async (context) => { const session = await getSession(context) if (!session) { return { redirect: { destination: '/login', permanent: false, }, } } return { props: { session }, } }
API Reference
ApiService
Main service class for interacting with Authaz.
Constructor
new ApiService(
clientId: string,
clientSecret: string,
authPoolId: string,
organizationId: string,
redirectUri: string,
tenantId: string
)Methods
getUniversalLoginUrl()
async getUniversalLoginUrl(): Promise<UniversalLoginResponse>Generates an OAuth2 authorization URL with PKCE. Returns the URL and code verifier.
getUniversalLoginAccessToken()
async getUniversalLoginAccessToken(
code: string,
state: string,
codeVerifier: string
): Promise<UniversalLoginAccessTokenResponse>Exchanges authorization code for access and refresh tokens.
getMe()
async getMe(accessToken: string): Promise<UserResponse>Retrieves the authenticated user's profile information.
Session Functions
createSession()
async createSession(loginResponse: {
accessToken: string
refreshToken: string
expires_in: number
}): Promise<void>Creates a secure session cookie.
getSession()
async getSession(ctx?: NextPageContext): Promise<Session | null>Retrieves the current session. Optional context parameter for server-side rendering.
clearSession()
async clearSession(): Promise<void>Clears the session cookie (logout).
Utility Functions
validateToken()
validateToken(token: string | undefined): booleanValidates that a token exists and is not empty.
createSecureHeaders()
createSecureHeaders(): Record<string, string>Returns security headers for HTTP responses.
validateApiResponse()
validateApiResponse(response: Response): booleanChecks if an HTTP response is successful (status 200-299).
extractErrorMessage()
async extractErrorMessage(response: Response): Promise<string>Extracts error message from failed HTTP response.
Type Guards
isSuccess()
isSuccess<T extends { status: string }>(response: T): booleanChecks if response status is 'success'.
isError()
isError<T extends { status: string }>(response: T): booleanChecks if response status is 'error'.
requiresMfa()
requiresMfa<T extends { status: string }>(response: T): booleanChecks if response requires MFA verification.
Examples
Complete Authentication Flow
import { ApiService, createSession, getSession, clearSession } from '@authaz/sdk'
class AuthManager {
private authaz: ApiService
constructor() {
this.authaz = new ApiService(
process.env.AUTHAZ_CLIENT_ID!,
process.env.AUTHAZ_CLIENT_SECRET!,
process.env.AUTHAZ_AUTH_POOL_ID!,
process.env.AUTHAZ_ORGANIZATION_ID!,
process.env.AUTHAZ_REDIRECT_URI!,
process.env.AUTHAZ_TENANT_ID!
)
}
async startLogin() {
const response = await this.authaz.getUniversalLoginUrl()
if (response.status === 'success') {
// Store code verifier securely
sessionStorage.setItem('pkce_verifier', response.codeVerifier)
// Redirect to login page
window.location.href = response.url
return true
}
console.error('Failed to generate login URL:', response.message)
return false
}
async handleCallback(code: string, state: string) {
const codeVerifier = sessionStorage.getItem('pkce_verifier')
if (!codeVerifier) {
throw new Error('Code verifier not found')
}
const tokenResponse = await this.authaz.getUniversalLoginAccessToken(
code,
state,
codeVerifier
)
if (tokenResponse.status === 'success') {
// Create session
await createSession({
accessToken: tokenResponse.accessToken.value,
refreshToken: tokenResponse.refreshToken.value,
expires_in: 3600
})
// Get user profile
const userResponse = await this.authaz.getMe(
tokenResponse.accessToken.value
)
if (userResponse.status === 'success') {
return userResponse.user
}
}
throw new Error('Authentication failed')
}
async getCurrentUser() {
const session = await getSession()
if (!session) {
return null
}
const response = await this.authaz.getMe(session.accessToken)
if (response.status === 'success') {
return response.user
}
// Handle expired session
if (response.status === 'token_expired' || response.status === 'unauthorized') {
await clearSession()
}
return null
}
async logout() {
await clearSession()
window.location.href = '/login'
}
}
export const authManager = new AuthManager()Usage in React Component
import { useEffect, useState } from 'react'
import { authManager } from './auth-manager'
function ProfilePage() {
const [user, setUser] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
authManager.getCurrentUser()
.then(setUser)
.catch(console.error)
.finally(() => setLoading(false))
}, [])
if (loading) return <div>Loading...</div>
if (!user) return <div>Not authenticated</div>
return (
<div>
<h1>Welcome, {user.name}</h1>
<p>Email: {user.email}</p>
<button onClick={() => authManager.logout()}>
Logout
</button>
</div>
)
}Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Setup
# Install dependencies
npm install
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Lint code
npm run lint
# Build
npm run buildLicense
MIT License - see LICENSE file for details
Support
For issues, questions, or contributions, please visit:
- GitHub Issues: https://github.com/authaz/authaz-sdk-js/issues
- Documentation: https://docs.authaz.com
Made with care by the Authaz Team
