npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@atlanhq/atlan-auth

v1.0.0

Published

Official Atlan Authentication SDK for seamless external app integration

Downloads

56

Readme

@atlanhq/atlan-auth

Official Authentication SDK for integrating external applications with Atlan, featuring seamless authentication via Keycloak.

Features

  • 🔐 Automatic Authentication: Auto-detects embedded vs standalone mode
  • 🎫 Keycloak Integration: Uses Keycloak with PKCE for secure, browser-safe auth
  • 🔄 Auto Token Refresh: Tokens refresh automatically before expiration
  • 🎯 Type-Safe: Full TypeScript support
  • 📦 Small Bundle: ~52KB gzipped (includes Keycloak)
  • 🚀 Zero Config: Just provide your Atlan origin URL

Installation

CDN (For plain HTML/JS apps)

<script src="https://unpkg.com/@atlanhq/atlan-auth@latest/dist/atlan-auth.umd.min.js"></script>
<script>
    const { AtlanAuth } = window.AtlanAuthSDK
    // SDK ready to use!
</script>

npm (For React/Vue/Angular apps)

# Add to .npmrc:
# @atlanhq:registry=https://npm.pkg.github.com

npm install @atlanhq/atlan-auth keycloak-js
# or
yarn add @atlanhq/atlan-auth keycloak-js
# or
pnpm add @atlanhq/atlan-auth keycloak-js

Note: When using npm, you need to install keycloak-js as a peer dependency. CDN users get it bundled automatically.

Quick Start

The SDK works in two modes automatically:

  1. Embedded Mode: When your app runs inside an Atlan iframe (production)
  2. Standalone Mode: When developing locally or running outside Atlan

Embedded Mode (Inside Atlan iframe)

const atlan = new AtlanAuth({
    origin: 'https://your-tenant.atlan.com',
})

await atlan.init()
// ✅ Instant authentication via postMessage
console.log('User:', atlan.getUser())
console.log('Token:', atlan.getToken())

Standalone Mode (Local development)

const atlan = new AtlanAuth({
    origin: 'http://localhost:3333', // Your local Atlan instance
})

await atlan.init()
// 🔄 Redirects to Atlan login page
// ✅ Returns after successful authentication
console.log('User:', atlan.getUser())

What happens in standalone mode:

  1. SDK detects you're not in an iframe
  2. Silently checks for existing session (no redirect if already logged in!)
  3. If no session: Redirects to {origin}/auth/realms/default/login
  4. You log in with your Atlan credentials
  5. Keycloak redirects back to your app with auth code
  6. SDK exchanges code for token (PKCE flow)
  7. Your app is now authenticated!

Note: The SDK uses "silent SSO check" by default, so returning users won't see a redirect flash!

Complete Example

// CDN usage
const { AtlanAuth } = window.AtlanAuthSDK

// npm usage: import { AtlanAuth } from '@atlanhq/atlan-auth'

const atlan = new AtlanAuth({
    origin: 'https://jpmc.atlan.com',
    onReady: (context) => {
        console.log('✅ SDK Ready!')
        console.log('Mode:', context.mode) // 'embedded' or 'standalone'
        console.log('User:', context.user)
        console.log('Tenant:', context.tenant)
    },
    onError: (error) => {
        console.error('❌ SDK Error:', error)
    },
    debug: true, // Enable console logging
})

// Initialize (async)
try {
    await atlan.init()

    // Make API calls
    const assets = await atlan.api.get('/api/meta/search')
    console.log('Assets:', assets.data)
} catch (error) {
    console.error('Initialization failed:', error)
}

Handling Loading States

To prevent a flash of content before authentication, use CSS-first loading patterns:

Recommended Pattern (CSS-First)

<head>
    <style>
        /* Hide app until authenticated */
        body.loading #app {
            display: none;
        }
        body.loading::before {
            content: '🔐 Authenticating...';
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
    </style>
</head>
<body class="loading">
    <div id="app">
        <!-- Your app content -->
    </div>

    <script src="https://unpkg.com/@atlanhq/atlan-auth@latest/dist/atlan-auth.umd.min.js"></script>
    <script>
        const { AtlanAuth } = window.AtlanAuthSDK

        const atlan = new AtlanAuth({
            origin: 'https://your-tenant.atlan.com',
            onReady: (context) => {
                // Remove loading state
                document.body.classList.remove('loading')
            },
        })

        atlan.init()
    </script>
</body>

Why CSS-first? CSS loads before JavaScript, so the loading state is visible from the first paint—no flash!

Alternative: Using Callbacks

const atlan = new AtlanAuth({
    origin: 'https://your-tenant.atlan.com',
    onStateChange: (state) => {
        if (state === 'initializing') {
            showLoader()
        } else if (state === 'authenticated') {
            hideLoader()
        }
    },
})

await atlan.init()

Note: In standalone mode, the SDK uses "silent SSO check"—returning users authenticate instantly without redirect!

API Reference

Constructor

new AtlanAuth(config: AtlanAuthConfig)

Config Options:

interface AtlanAuthConfig {
    origin: string // Atlan instance URL (required)
    onReady?: (context: AuthContext) => void // Success callback
    onError?: (error: AuthError) => void // Error callback
    onStateChange?: (state: AuthState, prevState: AuthState) => void // State change callback
    onTokenRefresh?: (token: string) => void // Token refresh callback
    onTokenExpired?: () => void // Token expired callback
    onLogout?: () => void // Logout callback
    keycloak?: KeycloakConfig // Keycloak customization
    interceptors?: Interceptors // Request/response interceptors
    debug?: boolean // Enable debug logging (default: false)
}

Methods

init(): Promise<AuthContext>

Initialize the SDK and authenticate. Must be called before using other methods.

const context = await atlan.init()

Returns:

interface AuthContext {
    token: string
    user: User
    tenant: string
    mode: 'embedded' | 'standalone'
}

getToken(): string | null

Get the current authentication token.

const token = atlan.getToken()

getUser(): User | null

Get the current user information.

const user = atlan.getUser()
// { id, username, email, firstName, lastName }

getTenant(): string | null

Get the current tenant name.

const tenant = atlan.getTenant()
// e.g., 'jpmc'

getMode(): 'embedded' | 'standalone'

Get the current authentication mode.

const mode = atlan.getMode()

isLoading(): boolean

Check if the SDK is currently loading or initializing. Safe to call before init().

const atlan = new AtlanAuth({ origin: '...' })

if (atlan.isLoading()) {
    console.log('SDK is initializing...')
}

Returns true if the SDK state is initializing or refreshing.

willRedirect(): boolean

Check if the SDK will redirect to the login page (standalone mode only). Safe to call before init().

const atlan = new AtlanAuth({ origin: '...' })

if (atlan.willRedirect()) {
    // Show loading UI - redirect is about to happen
    document.body.innerHTML = '<h2>Redirecting to login...</h2>'
}

await atlan.init() // Will redirect if willRedirect() returned true

Returns:

  • false in embedded mode (never redirects)
  • false in standalone mode if returning from login (has auth code)
  • true in standalone mode if no active session (will redirect)

Use case: Display appropriate loading UI before the redirect happens, preventing a flash of your app's content.

isInitialized(): boolean

Check if SDK is initialized.

if (atlan.isInitialized()) {
    // SDK ready
}

getState(): AuthState

Get the current authentication state.

const state = atlan.getState()
// 'idle' | 'initializing' | 'authenticated' | 'refreshing' | 'error' | 'logged_out'

logout(options?): Promise<void>

Logout from the authentication provider.

await atlan.logout({ redirectUri: 'https://myapp.com' })

retry(): Promise<AuthContext>

Retry initialization after an error.

try {
    await atlan.init()
} catch (error) {
    // Retry after error
    await atlan.retry()
}

reset(): void

Reset SDK to idle state.

atlan.reset()

isTokenExpired(): boolean

Check if the current token is expired.

if (atlan.isTokenExpired()) {
    await atlan.retry()
}

getTokenExpiry(): Date | null

Get the token expiry date.

const expiry = atlan.getTokenExpiry()
console.log('Token expires at:', expiry)

API Client

The SDK includes a built-in API client for making authenticated requests to Atlan:

api.get(url, options?)

const response = await atlan.api.get('/api/service/whoami')
console.log(response.data)

api.post(url, data, options?)

const response = await atlan.api.post('/api/meta/entity', {
    typeName: 'Table',
    attributes: { name: 'my_table' },
})

api.put(url, data, options?)

const response = await atlan.api.put('/api/meta/entity/guid/abc-123', {
    attributes: { description: 'Updated' },
})

api.delete(url, options?)

await atlan.api.delete('/api/meta/entity/guid/abc-123')

API Response:

interface ApiResponse<T> {
    data: T
    status: number
    headers: Record<string, string>
}

Framework Examples

React

import { AtlanAuth } from '@atlanhq/atlan-auth'
import { useEffect, useState } from 'react'

function App() {
    const [atlan, setAtlan] = useState(null)
    const [user, setUser] = useState(null)

    useEffect(() => {
        const sdk = new AtlanAuth({
            origin: 'https://your-tenant.atlan.com',
            onReady: (context) => {
                setUser(context.user)
            },
            onError: (error) => {
                console.error(error)
            },
        })

        sdk.init().then(() => setAtlan(sdk))
    }, [])

    if (!user) return <div>Loading...</div>

    return (
        <div>
            <h1>Welcome, {user.username}!</h1>
        </div>
    )
}

Vue 3

<template>
    <div v-if="user">
        <h1>Welcome, {{ user.username }}!</h1>
    </div>
    <div v-else>Loading...</div>
</template>

<script setup>
    import { AtlanAuth } from '@atlanhq/atlan-auth'
    import { ref, onMounted } from 'vue'

    const atlan = ref(null)
    const user = ref(null)

    onMounted(async () => {
        const sdk = new AtlanAuth({
            origin: 'https://your-tenant.atlan.com',
            onReady: (context) => {
                user.value = context.user
            },
        })

        await sdk.init()
        atlan.value = sdk
    })
</script>

Plain HTML/JS

<!DOCTYPE html>
<html>
    <head>
        <title>My Atlan App</title>
    </head>
    <body>
        <div id="app">Loading...</div>

        <script src="https://unpkg.com/@atlanhq/atlan-auth@latest/dist/atlan-auth.umd.min.js"></script>
        <script>
            const { AtlanAuth } = window.AtlanAuthSDK

            const atlan = new AtlanAuth({
                origin: 'https://your-tenant.atlan.com',
                onReady: (context) => {
                    document.getElementById('app').innerHTML = `
                    <h1>Welcome, ${context.user.username}!</h1>
                `
                },
            })

            atlan.init()
        </script>
    </body>
</html>

How It Works

Embedded Mode (Production)

┌─────────────────────────────────────────┐
│ Atlan Frontend (localhost:3333)        │
│                                         │
│  ┌─────────────────────────────────┐   │
│  │ Your App (in iframe)            │   │
│  │                                 │   │
│  │  1. SDK sends: IFRAME_READY ────┼───┤
│  │                                 │   │
│  │  2. ────────── ATLAN_AUTH_CONTEXT   │
│  │     (token, user via postMessage) ◄─┤
│  │                                 │   │
│  │  3. ✅ Instant authentication   │   │
│  └─────────────────────────────────┘   │
└─────────────────────────────────────────┘

Standalone Mode (Development)

┌─────────────────────────────────────────┐
│ Your App (localhost:8000)               │
│                                         │
│  1. SDK detects standalone mode         │
│  2. Redirects to Keycloak login ────────┼─┐
└─────────────────────────────────────────┘ │
                                            │
┌─────────────────────────────────────────┐ │
│ Atlan Keycloak (localhost:3333/auth)   ◄─┘
│                                         │
│  3. User logs in                        │
│  4. Redirects back with auth code ──────┼─┐
└─────────────────────────────────────────┘ │
                                            │
┌─────────────────────────────────────────┐ │
│ Your App (localhost:8000)              ◄─┘
│                                         │
│  5. SDK exchanges code for token (PKCE) │
│  6. ✅ Authenticated                     │
└─────────────────────────────────────────┘

Security

  • No client secrets in browser: Uses Keycloak's PKCE flow (Authorization Code Flow with Proof Key for Code Exchange)
  • Secure token storage: Tokens managed by Keycloak, not stored in localStorage
  • Automatic refresh: Tokens refresh before expiration
  • Origin validation: postMessage communication validates origins

Troubleshooting

Redirect loop in standalone mode

Make sure your Atlan instance is running and accessible at the origin URL.

"Not authenticated" errors

  1. Check that atlan.init() completed successfully
  2. Verify your Atlan instance URL is correct
  3. Enable debug logging: debug: true

TypeScript errors

If using npm, ensure keycloak-js is installed:

npm install keycloak-js

CORS errors

CORS errors only occur in standalone mode. Make sure:

  1. Your Atlan instance allows your app's origin
  2. You're running your app on the same domain as your Atlan instance (e.g., both on localhost)

License

ISC

Support

For issues and questions, please open an issue on GitHub.