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
- User opens your mini app inside the Alien app
- Host app injects a JWT token via
window.__ALIEN_AUTH_TOKEN__ AlienProviderreads the token and exposes it viauseAlien()- Your mini app sends the token to your backend in the
Authorizationheader - Backend verifies the token using
@alien_org/auth-client(fetches public keys from JWKS) - Backend extracts the user’s unique Alien ID from the
subclaim
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/reactConfigure 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:
| Property | Type | Description |
|---|---|---|
authToken | string | undefined | JWT token from the host app |
isBridgeAvailable | boolean | true if running inside Alien app |
contractVersion | Version | undefined | SDK protocol version |
ready | () => void | Signal 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>;
}| Parameter | Type | Description |
|---|---|---|
authToken | string | undefined | JWT token |
contractVersion | Version | undefined | SDK protocol version |
platform | 'ios' | 'android' | undefined | Platform identifier |
startParam | string | undefined | Custom parameter from deeplink |
hostAppVersion | string | undefined | Version of the Alien app |
safeAreaInsets | SafeAreaInsets | undefined | Safe area insets |
displayMode | DisplayMode | Display mode of the mini app |
Backend Setup
Install the Auth Client
npm install @alien_org/auth-clientVerify 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/jwksToken Fields
Verified tokens contain these standard JWT claims:
| Field | Type | Description |
|---|---|---|
iss | string | Token issuer |
sub | string | User’s unique Alien ID |
aud | string | string[] | Token audience |
exp | number | Expiration timestamp (Unix) |
iat | number | Issued at timestamp (Unix) |
nonce | string | undefined | Nonce (if provided during auth) |
auth_time | number | undefined | Time 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
expclaim 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.JWTExpiredandJwtErrors.JOSEErrorfor specific error handling.
Next Steps
- Payments — Accept payments in your mini app
- Install Boilerplate — Pre-configured template
Last updated on