Initial commit: YouTube Studio Flow (backend, frontend, infrastructure, docs)
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
# Auth API
|
||||
|
||||
Base path: `/api/v1/auth`
|
||||
|
||||
All endpoints require `Authorization: Bearer <jwt>` unless noted otherwise.
|
||||
|
||||
Related: [[02 - Authentication]], [[09 - Teams API]]
|
||||
|
||||
---
|
||||
|
||||
## Endpoints
|
||||
|
||||
### GET /auth/google
|
||||
|
||||
Initiates the Google OAuth flow. Redirects the browser to the Google consent screen.
|
||||
|
||||
> No authentication required.
|
||||
|
||||
---
|
||||
|
||||
### GET /auth/google/callback
|
||||
|
||||
OAuth callback handler. Called by Google after the user grants consent. Sets JWT tokens and redirects to the frontend.
|
||||
|
||||
> No authentication required. Handled entirely by the backend.
|
||||
|
||||
---
|
||||
|
||||
### POST /auth/refresh
|
||||
|
||||
Refreshes the access token using a valid refresh token.
|
||||
|
||||
**Request body:**
|
||||
|
||||
```json
|
||||
{ "refreshToken": "string" }
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "string",
|
||||
"refreshToken": "string"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST /auth/logout
|
||||
|
||||
Invalidates the current refresh token. Requires authentication.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "message": "Logged out" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GET /auth/me
|
||||
|
||||
Returns the currently authenticated user.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "cuid",
|
||||
"email": "user@example.com",
|
||||
"name": "User Name",
|
||||
"teamId": "cuid",
|
||||
"teamRole": "EDITOR"
|
||||
}
|
||||
```
|
||||
|
||||
**Possible `teamRole` values:** `OWNER`, `ADMIN`, `EDITOR`, `REVIEWER`, `READONLY`
|
||||
|
||||
---
|
||||
|
||||
### POST /auth/switch-team
|
||||
|
||||
Switch the active team context. Returns a new access token scoped to the requested team. The caller must be a member of the target team.
|
||||
|
||||
**Request body:**
|
||||
|
||||
```json
|
||||
{ "teamId": "cuid" }
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "accessToken": "string" }
|
||||
```
|
||||
|
||||
Replace the stored access token with the returned one. All subsequent requests will be scoped to the new team. The refresh token is unchanged.
|
||||
|
||||
> **Note:** The response does not include `teamRole`. The new role is encoded inside the JWT payload (`teamRole` claim). Clients that need the role without decoding the JWT must call `GET /users/me` after switching teams. See the backlog for a possible improvement.
|
||||
|
||||
> **Frontend status:** No UI exists for team switching. This endpoint is only reachable via direct API call. Use `GET /teams/mine` to enumerate the teams available to switch to.
|
||||
|
||||
---
|
||||
|
||||
### GET /users/me/preferences
|
||||
|
||||
Returns the current user's preferences as a freeform JSON object.
|
||||
|
||||
**Response:** `Record<string, unknown>`
|
||||
|
||||
---
|
||||
|
||||
### PATCH /users/me/preferences
|
||||
|
||||
Merges new key/value pairs into the user's stored preferences. Existing keys not present in the request body are preserved.
|
||||
|
||||
**Request body:** `Record<string, unknown>`
|
||||
|
||||
**Response:** Updated preferences object
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Access tokens are short-lived JWTs signed with `JWT_SECRET`.
|
||||
- Refresh tokens are stored encrypted and are invalidated on logout.
|
||||
- YouTube OAuth tokens (for channel connections) are separate from user auth tokens and are AES-256 encrypted in the database using `TOKEN_ENCRYPTION_KEY`. If that key changes, all channel connections must be re-authenticated.
|
||||
- See [[06 - Authentication]] for the full auth flow and guard usage.
|
||||
Reference in New Issue
Block a user