Outcome
List external sign-in providers linked to one visible user.
These examples prove local handler behavior with real isolated SQL and explicitly simulated identity/permission dependencies.
Before you start
-
Verify the intended authenticated identity and the current credential-scoped action before preparing input. Self and managed-user security operations have different authority; a session id does not authorize a different user.
-
Use authorized identity and user/session discovery. Recovery security data and session/device identifiers must remain inside the caller-approved workflow.
Discover the target
topolo whoami --json
topolo apps --json
topolo actions get app_topolo_auth.user_oauth_providers.list --detail --json
Use the caller subject or a user returned by authorized users discovery. Read user_oauth_providers.list for that exact user before unlinking a returned provider name; providerUserId is an external identity. Unlock requires target-user management authority.
Input fields
| Field | Required | Meaning |
|---|---|---|
userId | Yes | Existing Auth user id from authorized identity or user discovery. Provider links allow self or authorized managed-user access; account unlock requires target-user management authority even for a self request. |
Effects
- Reads existing external sign-in associations for self or an authorized managed user. Does not establish an alternate working sign-in method.
Interpret the response
HTTP 200 successes use raw target success/message/data/timestamp, which CLI/MCP can wrap or project. Record times are epoch seconds; the envelope timestamp is ISO text. Local fixtures use real canonical SQL and target-user authority with simulated token identity and user organization lookup. They prove neither live permissions nor actual sign-in.
providers is the complete stored link list for the selected user, sorted by provider name; there is no pagination or continuation. provider identifies the linked system and providerUserId is its external identity, not a Topolo user id, credential or application grant. Usernames/emails/avatar URLs can be null. Keep this identity data inside the authorized workflow.
An empty successful list means no stored links at this read, not that password, recovery or another authentication method is configured and usable. Missing target user returns NOT_FOUND instead. SQL failures return SERVER_ERROR. Bearer takes precedence over access cookies for these provider handlers.
Worked examples
These are complete raw target-handler responses, not CLI/gateway envelopes or live authorization proof. Replace synthetic identifiers using authorized discovery. Save only the reviewed input as payload.json; inspect validation and plan before executing. --confirm assumes the intended operation is approved. Storage read-back and actual sign-in outcomes require separate verification. Provider unlink does not revoke external accounts, consent or existing Auth sessions. Cookies and Bearer tokens must identify the intended principal consistently.
Self reads linked providers sorted by provider name
Input · payload.json:
{
"userId": "usr_self"
}
CLI:
topolo actions validate app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions plan app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions call app_topolo_auth.user_oauth_providers.list --data @payload.json --json
MCP call after validation and plan review:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.user_oauth_providers.list",
"input": {
"userId": "usr_self"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "OAuth providers fetched",
"data": {
"providers": [
{
"provider": "github",
"providerUserId": "external_github_usr_self",
"providerUsername": "fixture-usr_self",
"providerEmail": "usr_self@example.test",
"avatarUrl": null,
"createdAt": 1,
"updatedAt": 1
},
{
"provider": "google",
"providerUserId": "external_google_usr_self",
"providerUsername": "fixture-usr_self",
"providerEmail": "usr_self@example.test",
"avatarUrl": null,
"createdAt": 1,
"updatedAt": 1
}
]
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
userId identity alias supports self provider discovery
Input · payload.json:
{
"userId": "usr_self"
}
CLI:
topolo actions validate app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions plan app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions call app_topolo_auth.user_oauth_providers.list --data @payload.json --json
MCP call after validation and plan review:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.user_oauth_providers.list",
"input": {
"userId": "usr_self"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "OAuth providers fetched",
"data": {
"providers": [
{
"provider": "github",
"providerUserId": "external_github_usr_self",
"providerUsername": "fixture-usr_self",
"providerEmail": "usr_self@example.test",
"avatarUrl": null,
"createdAt": 1,
"updatedAt": 1
},
{
"provider": "google",
"providerUserId": "external_google_usr_self",
"providerUsername": "fixture-usr_self",
"providerEmail": "usr_self@example.test",
"avatarUrl": null,
"createdAt": 1,
"updatedAt": 1
}
]
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Administrator reads only its authorized managed user
Input · payload.json:
{
"userId": "usr_managed"
}
CLI:
topolo actions validate app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions plan app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions call app_topolo_auth.user_oauth_providers.list --data @payload.json --json
MCP call after validation and plan review:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.user_oauth_providers.list",
"input": {
"userId": "usr_managed"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "OAuth providers fetched",
"data": {
"providers": [
{
"provider": "github",
"providerUserId": "external_github_usr_managed",
"providerUsername": "fixture-usr_managed",
"providerEmail": "usr_managed@example.test",
"avatarUrl": null,
"createdAt": 1,
"updatedAt": 1
}
]
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Read after unlink retains the other linked provider
Input · payload.json:
{
"userId": "usr_self"
}
CLI:
topolo actions validate app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions plan app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions call app_topolo_auth.user_oauth_providers.list --data @payload.json --json
MCP call after validation and plan review:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.user_oauth_providers.list",
"input": {
"userId": "usr_self"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "OAuth providers fetched",
"data": {
"providers": [
{
"provider": "google",
"providerUserId": "external_google_usr_self",
"providerUsername": "fixture-usr_self",
"providerEmail": "usr_self@example.test",
"avatarUrl": null,
"createdAt": 1,
"updatedAt": 1
}
]
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Empty list after removal of the sole provider does not prove alternate sign-in works
Input · payload.json:
{
"userId": "usr_managed"
}
CLI:
topolo actions validate app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions plan app_topolo_auth.user_oauth_providers.list --data @payload.json --json
topolo actions call app_topolo_auth.user_oauth_providers.list --data @payload.json --json
MCP call after validation and plan review:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.user_oauth_providers.list",
"input": {
"userId": "usr_managed"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "OAuth providers fetched",
"data": {
"providers": []
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Verify the result
-
Keep the exact selected Topolo user id alongside each provider. Use provider, not providerUserId, for unlink input; the external identity is not a Topolo user id.
-
Before reviewing any unlink, verify an alternate approved authentication path can sign in as the same user. An empty link list cannot prove this.
Errors and recovery
Foreign organization target is refused
Captured local refusal · HTTP 403:
{
"input": {
"userId": "usr_foreign"
},
"response": {
"success": false,
"error": {
"message": "Insufficient permissions",
"code": "FORBIDDEN",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Unknown user is a not-found identity, not an empty provider list
Captured local refusal · HTTP 404:
{
"input": {
"userId": "usr_missing"
},
"response": {
"success": false,
"error": {
"message": "User not found",
"code": "NOT_FOUND",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Anonymous provider discovery is refused
Captured local refusal · HTTP 401:
{
"input": {
"userId": "usr_self"
},
"response": {
"success": false,
"error": {
"message": "Access token required",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Invalid token is the current handler server error
Captured local refusal · HTTP 500:
{
"input": {
"userId": "usr_self"
},
"response": {
"success": false,
"error": {
"message": "Invalid fixture token",
"code": "SERVER_ERROR",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Published recovery guidance
-
AUTH_ERROR(HTTP 401): Verify the intended identity and transport. Unlock AUTH_ERROR can mean authenticated target-user authority denial; refresh only a genuinely expired token for the approved context. -
FORBIDDEN(HTTP 403): Preserve the target-user authority denial. Use only an approved identity authorized for this exact user/organization; do not switch contexts automatically. -
NOT_FOUND(HTTP 404): Refresh authorized user/provider discovery. Repeated unlink reports a missing link; do not create a fictitious link or infer external account deletion. -
SERVER_ERROR(HTTP 500): Preserve the original error, verify the approved authentication and inspect current target state before reviewing any retry. Invalid-token exceptions and repository errors are both possible.
Recovery boundaries
Read-only. Preserve user-specific provider identity data within the authorized workflow and refresh discovery after a separately approved link change.
Discovery and evidence
This record belongs to app_topolo_auth. Local tests prove real canonical provider/security SQL, target-user authorization and handler responses with simulated tokens and identity lookup. They do not prove live permission, alternate sign-in, external-provider token/consent revocation, actual user login, deployment or production completion.