Embed your app
You can embed your web app directly in the product, making it accessible from the navigation sidebar or from asset profile tabs. Your app runs on your own infrastructure and is loaded in a sandboxed iframe, with authenticated user context shared securely via a handshake mechanism.
This page guides you through deploying your app, configuring CSP so the product can load it in an iframe, adding authentication so your app receives user context, and registering the app. If you want to develop and test on localhost first, see Develop your app.
Prerequisites
Before you begin, make sure you have:
- A web application that runs in a browser (React, Vue, plain HTML, or similar).
- An Atlan tenant URL (for example,
https://your-tenant.atlan.com).
Configure app
Use these steps to deploy your app and configure it so Atlan can load it in an iframe.
-
Once you have developed locally and tested your app, deploy it to a publicly reachable HTTPS endpoint, such as
https://app.company.com.Atlan doesn't host or run your code. It loads your app in an iframe from the URL you provide. If you haven't built your app yet, see Develop your app first.
-
Configure Content Security Policy (CSP) so Atlan can embed your app. Add the CSP header on the server that responds for your app URL (for example, your reverse proxy, app server, or CDN).
frame-ancestorsmust be set as an HTTP response header.Your app must include Atlan as a
frame-ancestorsorigin:Content-Security-Policy: frame-ancestors 'self' https://*.atlan.com;Verify the header is present on your deployed URL:
curl -I https://app.company.com | grep -i content-security-policyIf you set
X-Frame-Options, make sure it doesn't block embedding. Values likeDENYandSAMEORIGINprevent the product from loading your app in an iframe. -
Add authentication code in your app's startup code (for example,
index.html,main.ts, orApp.tsx). Initialize authentication as early as possible so Atlan can load the iframe and pass user context to your app.
Set up authentication
Configure the Atlan tenant origin (for example, https://your-tenant.atlan.com). Use the SDK (recommended) or implement the postMessage protocol manually.
-
In your app's client entry point, add the Atlan Auth SDK and initialize it with your Atlan tenant origin. Replace
https://your-tenant.atlan.comwith your tenant URL. -
Use the
onReadycallback so your app receives user context when Atlan loads it in the iframe. Render your UI or call Atlan APIs insideonReady. The context includes token, user, and page (for example, the asset GUID when your app is an asset profile tab). For the full payload shape, see Auth payload.
- SDK (recommended)
- Manual postMessage
Use the Atlan Auth SDK so handshake and token refresh are handled for you. Choose your framework below.
- Plain HTML
- React
- Vue 3
- Other frameworks
-
In your HTML entry point (for example,
index.html), add the SDK script tag. -
Initialize the SDK with your Atlan tenant origin and use
onReadyto render your app when the iframe has user context.
Example: If you want to show a greeting and profile card when your app is embedded (same pattern as the Develop your app profile app), you can use the following:
<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: async (context) => {
const user = context.user
const whoami = await atlan.api.get('/api/service/whoami')
document.getElementById('app').innerHTML = `
`
},
onError: (error) => {
document.getElementById('app').textContent = 'Authentication failed: ' + (error.message || error)
},
})
atlan.init()
</script>
-
In your client entry point or root component (for example,
App.tsx), add the SDK and initialize it with your Atlan tenant origin. -
Use
onReadyto set state and render your UI when the iframe has user context.
Example: If you want to show a greeting and call the whoami API when embedded, you can use the following:
import { useEffect, useState } from 'react'
import { AtlanAuth } from '@atlanhq/atlan-auth'
export function App() {
const [username, setUsername] = useState<string>()
const [error, setError] = useState<string>()
useEffect(() => {
const atlan = new AtlanAuth({
origin: 'https://your-tenant.atlan.com',
onReady: async (context) => {
setUsername(context.user.username)
// Example: call an Atlan API after authentication
const whoami = await atlan.api.get('/api/service/whoami')
console.log('whoami:', whoami)
},
onError: (e) => setError(e.message),
})
atlan.init()
}, [])
if (error) return <div>Authentication failed: {error}</div>
if (!username) return <div>Loading…</div>
return <div>Hello {username}</div>
}
-
In your client entry point (for example,
main.ts) or root component, add the SDK and initialize it with your Atlan tenant origin. -
Use
onReadyto set refs and render your UI when the iframe has user context.
Example: If you want to show a greeting when embedded, you can use the following:
<template>
<div v-if="error">Authentication failed: {{ error }}</div>
<div v-else-if="!username">Loading…</div>
<div v-else>Hello {{ username }}</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { AtlanAuth } from '@atlanhq/atlan-auth'
const username = ref<string>()
const error = ref<string>()
onMounted(() => {
const atlan = new AtlanAuth({
origin: 'https://your-tenant.atlan.com',
onReady: async (context) => {
username.value = context.user.username
// Example: call an Atlan API after authentication
const whoami = await atlan.api.get('/api/service/whoami')
console.log('whoami:', whoami)
},
onError: (e) => (error.value = e.message),
})
atlan.init()
})
</script>
-
In the earliest client-side entry point for your app, add the SDK and initialize it with your Atlan tenant origin.
-
Use
onReadyto run your app logic when the iframe has user context.
Example: If you want to log the user and call the whoami API when embedded, you can use the following:
import { AtlanAuth } from '@atlanhq/atlan-auth'
const atlan = new AtlanAuth({
origin: 'https://your-tenant.atlan.com',
onReady: async (context) => {
console.log('Authenticated as:', context.user.username)
// Example: call an Atlan API after authentication
const whoami = await atlan.api.get('/api/service/whoami')
console.log('whoami:', whoami)
},
onError: (error) => {
console.error('Authentication failed:', error)
},
})
atlan.init()
Use this approach if you don't use the SDK and you want to implement the handshake yourself.
Example: Minimal handshake
// Must match your Atlan tenant origin
const ATLAN_ORIGIN = 'https://your-tenant.atlan.com'
let authContext: any = null
window.addEventListener('message', (event: MessageEvent) => {
// Always validate origin
if (event.origin !== ATLAN_ORIGIN) return
const { type, payload } = (event.data || {}) as { type?: string; payload?: any }
switch (type) {
case 'ATLAN_HANDSHAKE':
// Required: respond quickly or Atlan shows a timeout
window.parent.postMessage({ type: 'IFRAME_READY' }, ATLAN_ORIGIN)
break
case 'ATLAN_AUTH_CONTEXT':
authContext = payload
console.log('Authenticated as:', payload.user?.username)
break
case 'ATLAN_LOGOUT':
authContext = null
break
}
})
Example: If you want to show your UI only after authentication, render a loading state until you receive ATLAN_AUTH_CONTEXT. Then render the app using payload.user and payload.token. For the auth payload fields (token, user, page), see Auth payload. For token refresh, IFRAME_TOKEN_REQUEST, and message types, see Send and receive messages.
Register your app
Once you have deployed your app and added authentication, you need to register it so Atlan can load it in the product. External apps are registered through tenant configuration. For step-by-step guidance on what to provide and how to share it with your admin or support, see Register your app.
Need help?
If you run into issues while embedding your app, see the troubleshooting guide. If you have any issues related to configuring the app, contact Atlan support: Submit a request.
Next steps
- Register your app: Step-by-step registration guide