7c67e53b1e4476b68e5ae1bf0deb666a376bdbec
ci/woodpecker/push/woodpecker Pipeline was successful
ATNMY STDO Auth
Central JWT auth server for Autonomy Studio and launched apps.
Stack
- Bun
- Hono
- PostgreSQL
- Redis
- Prisma
- JWT access tokens
- Opaque refresh tokens stored in Redis
- One-time handoff tokens for app SSO stored in Redis
Local Run
cp .env.example .env
docker compose up -d postgres redis
bun install
bun run db:generate
bun run db:migrate
bun run db:seed
bun run dev
Default server:
http://localhost:4100
Default backing services:
PostgreSQL: localhost:5434
Redis: localhost:6380
Default seeded admin:
admin@futuredrive.net / admin1234
Change this before using the service outside local development.
API
Login
POST /auth/login
Content-Type: application/json
{
"email": "admin@futuredrive.net",
"password": "admin1234"
}
Returns:
{
"accessToken": "...",
"accessTokenExpiresIn": 900,
"refreshToken": "...",
"refreshTokenExpiresIn": 2592000,
"user": {
"id": "...",
"email": "admin@futuredrive.net",
"name": "ATNMY Studio Admin",
"role": "ADMIN",
"roles": ["ADMIN"]
}
}
Current User
GET /auth/me
Authorization: Bearer <accessToken>
Refresh
POST /auth/refresh
Content-Type: application/json
{
"refreshToken": "<refreshToken>"
}
Refresh tokens are rotated on every use.
Logout
POST /auth/logout
Content-Type: application/json
{
"refreshToken": "<refreshToken>"
}
Create App Handoff Token
Launcher calls this before launching ADS IDE or another app.
POST /auth/handoff
Authorization: Bearer <launcherAccessToken>
Content-Type: application/json
{
"audienceApp": "ADS IDE"
}
Returns a short-lived one-time token:
{
"handoffToken": "...",
"expiresIn": 60,
"audienceApp": "ADS IDE"
}
Exchange App Handoff Token
The launched app calls this on startup.
POST /auth/handoff/exchange
Content-Type: application/json
{
"handoffToken": "...",
"audienceApp": "ADS IDE"
}
Returns the launched app's own access/refresh token pair.
Launcher Integration Sketch
const handoff = await fetch(`${AUTH_URL}/auth/handoff`, {
method: 'POST',
headers: {
authorization: `Bearer ${accessToken}`,
'content-type': 'application/json'
},
body: JSON.stringify({ audienceApp: 'ADS IDE' })
}).then((r) => r.json())
spawn(execBin, [
`--url=${encodeURIComponent(url)}`,
`--handoff-token=${encodeURIComponent(handoff.handoffToken)}`,
`--auth-url=${encodeURIComponent(AUTH_URL)}`
])
ADS IDE then calls /auth/handoff/exchange and stores the returned session.
Description
Languages
TypeScript
99.7%
Dockerfile
0.3%