init studio auth backend
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```text
|
||||
http://localhost:4100
|
||||
```
|
||||
|
||||
Default backing services:
|
||||
|
||||
```text
|
||||
PostgreSQL: localhost:5434
|
||||
Redis: localhost:6380
|
||||
```
|
||||
|
||||
Default seeded admin:
|
||||
|
||||
```text
|
||||
admin@futuredrive.net / admin1234
|
||||
```
|
||||
|
||||
Change this before using the service outside local development.
|
||||
|
||||
## API
|
||||
|
||||
### Login
|
||||
|
||||
```http
|
||||
POST /auth/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"email": "admin@futuredrive.net",
|
||||
"password": "admin1234"
|
||||
}
|
||||
```
|
||||
|
||||
Returns:
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "...",
|
||||
"accessTokenExpiresIn": 900,
|
||||
"refreshToken": "...",
|
||||
"refreshTokenExpiresIn": 2592000,
|
||||
"user": {
|
||||
"id": "...",
|
||||
"email": "admin@futuredrive.net",
|
||||
"name": "ATNMY Studio Admin",
|
||||
"role": "ADMIN",
|
||||
"roles": ["ADMIN"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Current User
|
||||
|
||||
```http
|
||||
GET /auth/me
|
||||
Authorization: Bearer <accessToken>
|
||||
```
|
||||
|
||||
### Refresh
|
||||
|
||||
```http
|
||||
POST /auth/refresh
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"refreshToken": "<refreshToken>"
|
||||
}
|
||||
```
|
||||
|
||||
Refresh tokens are rotated on every use.
|
||||
|
||||
### Logout
|
||||
|
||||
```http
|
||||
POST /auth/logout
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"refreshToken": "<refreshToken>"
|
||||
}
|
||||
```
|
||||
|
||||
### Create App Handoff Token
|
||||
|
||||
Launcher calls this before launching ADS IDE or another app.
|
||||
|
||||
```http
|
||||
POST /auth/handoff
|
||||
Authorization: Bearer <launcherAccessToken>
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"audienceApp": "ADS IDE"
|
||||
}
|
||||
```
|
||||
|
||||
Returns a short-lived one-time token:
|
||||
|
||||
```json
|
||||
{
|
||||
"handoffToken": "...",
|
||||
"expiresIn": 60,
|
||||
"audienceApp": "ADS IDE"
|
||||
}
|
||||
```
|
||||
|
||||
### Exchange App Handoff Token
|
||||
|
||||
The launched app calls this on startup.
|
||||
|
||||
```http
|
||||
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
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user