Skip to Content
React SDKAuthentication
View .md

Authentication

Authenticate users in your Alien mini app. The host app provides a JWT token that identifies the user, which you can verify on your backend.

How It Works

  1. User opens your mini app inside the Alien app
  2. Host app injects a JWT token via window.__ALIEN_AUTH_TOKEN__
  3. AlienProvider reads the token and exposes it via useAlien()
  4. Your mini app sends the token to your backend in the Authorization header
  5. Backend verifies the token using @alien_org/auth-client (fetches public keys from JWKS)
  6. Backend extracts the user’s unique Alien ID from the sub claim

Registration is implicit — on first API call, the user is automatically created in the database via a find-or-create pattern. No signup flow needed.

Frontend Setup

Install the SDK

npm install @alien_org/react

Configure the Provider

Wrap your app with AlienProvider to enable authentication:

function App() { return ( <AlienProvider> <YourApp /> </AlienProvider> ); }

Get the Auth Token

Use the useAlien hook to access the authentication token:

function Profile() { const { authToken, isBridgeAvailable } = useAlien(); if (!isBridgeAvailable) { return <p>Open this app inside Alien to authenticate.</p>; } if (!authToken) { return <p>Loading...</p>; } return <p>Authenticated</p>; }

Available context values:

PropertyTypeDescription
authTokenstring | undefinedJWT token from the host app
isBridgeAvailablebooleantrue if running inside Alien app
contractVersionVersion | undefinedSDK protocol version
ready() => voidSignal the host app that the miniapp is ready

The ready function is only needed when autoReady is false.

Using Launch Parameters

For additional context about the launch environment, use useLaunchParams:

function App() { const launchParams = useLaunchParams(); if (!launchParams) { return <div>Running outside Alien App</div>; } return <div>Platform: {launchParams.platform}</div>; }
ParameterTypeDescription
authTokenstring | undefinedJWT token
contractVersionVersion | undefinedSDK protocol version
platform'ios' | 'android' | undefinedPlatform identifier
startParamstring | undefinedCustom parameter from deeplink
hostAppVersionstring | undefinedVersion of the Alien app
safeAreaInsetsSafeAreaInsets | undefinedSafe area insets
displayModeDisplayModeDisplay mode of the mini app

Backend Setup

Install the Auth Client

npm install @alien_org/auth-client

Verify Tokens

Create an auth client and verify incoming tokens:

const authClient = createAuthClient(); async function verifyRequest(req: Request) { const token = req.headers.get('Authorization')?.replace('Bearer ', ''); if (!token) { throw new Error('Missing authorization token'); } const tokenInfo = await authClient.verifyToken(token); // tokenInfo.sub contains the user's unique Alien ID return tokenInfo; }

The auth client automatically fetches the public keys from the JWKS endpoint:

https://sso.alien-api.com/oauth/jwks

Token Fields

Verified tokens contain these standard JWT claims:

FieldTypeDescription
issstringToken issuer
substringUser’s unique Alien ID
audstring | string[]Token audience
expnumberExpiration timestamp (Unix)
iatnumberIssued at timestamp (Unix)
noncestring | undefinedNonce (if provided during auth)
auth_timenumber | undefinedTime of authentication (Unix)

Complete Example

Frontend Component

function UserProfile() { const { authToken, isBridgeAvailable } = useAlien(); const [user, setUser] = useState<{ alienId: string } | null>(null); const [error, setError] = useState<string | null>(null); useEffect(() => { if (!authToken) return; fetch('/api/me', { headers: { Authorization: `Bearer ${authToken}`, }, }) .then((res) => { if (!res.ok) throw new Error('Authentication failed'); return res.json(); }) .then(setUser) .catch((err) => setError(err.message)); }, [authToken]); if (!isBridgeAvailable) { return <p>Please open this app inside Alien.</p>; } if (error) { return <p>Error: {error}</p>; } if (!user) { return <p>Loading...</p>; } return <p>Alien ID: {user.alienId}</p>; } function App() { return ( <AlienProvider> <UserProfile /> </AlienProvider> ); }

Backend API Route (Next.js)

const authClient = createAuthClient(); export async function GET(request: Request) { const token = request.headers .get('Authorization') ?.replace('Bearer ', ''); if (!token) { return NextResponse.json( { error: 'Missing authorization token' }, { status: 401 }, ); } try { const { sub } = await authClient.verifyToken(token); // sub is the user's unique Alien ID // Use find-or-create to register users implicitly const user = await findOrCreateUser(sub); return NextResponse.json({ id: user.id, alienId: user.alienId, createdAt: user.createdAt.toISOString(), updatedAt: user.updatedAt.toISOString(), }); } catch (error) { if (error instanceof JwtErrors.JWTExpired) { return NextResponse.json( { error: 'Token expired' }, { status: 401 }, ); } if (error instanceof JwtErrors.JOSEError) { return NextResponse.json( { error: 'Invalid token' }, { status: 401 }, ); } return NextResponse.json( { error: 'Internal server error' }, { status: 500 }, ); } }

Express.js Middleware

const authClient = createAuthClient(); interface AuthenticatedRequest extends Request { user?: { alienId: string; exp: number; iat: number; }; } async function authMiddleware( req: AuthenticatedRequest, res: Response, next: NextFunction, ) { const token = req.headers.authorization?.replace('Bearer ', ''); if (!token) { return res.status(401).json({ error: 'Missing authorization token' }); } try { const tokenInfo = await authClient.verifyToken(token); req.user = { alienId: tokenInfo.sub, exp: tokenInfo.exp, iat: tokenInfo.iat, }; next(); } catch (error) { if (error instanceof JwtErrors.JWTExpired) { return res.status(401).json({ error: 'Token expired' }); } return res.status(401).json({ error: 'Invalid token' }); } } // Usage app.get('/api/profile', authMiddleware, (req: AuthenticatedRequest, res) => { res.json({ alienId: req.user?.alienId }); });

Security Considerations

  • Always verify tokens on your backend. Never trust the frontend.
  • Check token expiration. The exp claim indicates when the token expires. The auth client handles this automatically.
  • Use HTTPS. Always transmit tokens over secure connections.
  • Do not log tokens. Avoid logging full tokens in production.
  • Handle JWT errors. Use JwtErrors.JWTExpired and JwtErrors.JOSEError for specific error handling.

Next Steps

Last updated on