Connected Apps
The consent screen, the recorded grant, and how users review or revoke access.
Connected Apps
Once a user approves an OAuth client, that approval is recorded. It lets SSO skip the consent screen next time and gives the user a place to see — and revoke — who has access.
The consent screen
GET /api/oauth/authorize sends a signed-in user to the consent screen hosted by
accounts-web at accounts.aetherlabs.agency/oauth/consent.
Two things decide whether they actually see it:
- Already granted — if the user previously approved every scope in this request, the screen is skipped and the code is issued immediately.
prompt=consent— always show the screen, even when nothing is new. Useful after a scope change, or to force a re-confirmation.
The screen reads GET /api/oauth/consent-info (client name, requested scopes,
and what was previously granted) and submits POST /api/oauth/authorize/approve.
Your app never renders consent itself.
Reviewing access
Users manage this at myaccount.aetherlabs.agency → Data & privacy → Connected apps, which lists each connected app with its granted scopes and a Disconnect button.
API
Both endpoints act on the signed-in user and need no special permission.
| Method | Path | Purpose |
|---|---|---|
GET | /api/auth/apps | Every active client, plus this user's grant |
DELETE | /api/auth/apps/:clientId | Disconnect the app |
GET /api/auth/apps returns:
{
"apps": [
{
"id": "client-uuid",
"clientId": "your-client-id",
"name": "Your Product",
"url": "https://yourapp.example.com",
"scopes": ["openid", "profile", "email"],
"connected": true,
"grantedScopes": ["openid", "profile", "email"],
"grantedAt": "2026-09-29T10:24:00.000Z"
}
]
}id vs clientId
The path parameter for disconnect is the client's id (a UUID), not the
public client_id. Use the id field above.
What disconnecting does
DELETE /api/auth/apps/:clientId:
- deletes the recorded grant, so the next
/authorizeshows the consent screen again - revokes every active refresh token that client holds for the user
The app cannot mint new tokens, and any access token it still holds simply
expires (up to 24 hours). Treat invalid_grant from your refresh call as
"signed out" and send the user back through the flow.
Where grants live
Consent is stored per (user, client) pair with the granted scopes. It is
deliberately coarse: approving email after profile widens the recorded set
rather than replacing it.
See also
- OAuth clients — registering the app that appears here.
- Errors — including the reuse cases that revoke sessions.