You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Namespace the credential subject by verified issuer #222
Today
The minted credential records who the caller is but not who vouched for them, so every issuer's subjects share one flat namespace. That subject is also part of the proxy's cache key, so a collision affects cached authorization results too.
Do
Rewrite the principal into an issuer-qualified form before it reaches the Source API, derived from the verifiediss claim.
Done when
Two issuers using the same subject string resolve to different accounts and do not share a cache entry.
Watch
Derive the namespace from the verified claim, not from Role config — one Role may trust several issuers, which would collapse them back into one namespace.
Why it blocks GitHub
GitHub counts as a second issuer. This must land before GitHub is trusted, not only before user-registered issuers.
This is not a localized rewrite. The mint site is inside multistore-sts (lib.rs, where sub becomes source_identity), not the proxy; the proxy's only hook sees the Role id, never the token. So it is a breaking wire-format change across three repositories — multistore release → proxy version bump → Resolve accounts by (issuer, subject) source.coop#543 — and authenticateWithOidcToken treats sub as a bare Ory identity id, so an issuer-qualified subject 401s every request until the app side lands.
Dual-format window. Subjects are sealed into live session tokens for up to STS_MAX_SESSION_DURATION_SECS, and the Workers cache holds old-format keys for up to 300s. Both formats are live during rollout; the rollout plan should say so.
Ride along: the analytics schema records user_id un-namespaced by issuer too, so historical rows are already ambiguous. Qualifying it here is cheap. Audit logging of exchanges belongs here as an acceptance criterion.
Contract change from source-cooperative/source.coop#566: the API no longer resolves (issuer, subject) to an account. Instead, after verifying a platform-IdP token and reading the account from RoleArn, the proxy calls POST /api/v1/accounts/{account_id}/trusts/exchanges with { issuer, subject } (the verifiediss and sub), authenticated as that account — the same way it calls the keys exchanges route. 200 {trusted: true} means mint; 403 means deny. The principal it then forwards on proxied requests is the account id, as for API keys. Ory tokens are unchanged. Cache the answer like the keys standing (60s).
Activity
alukach commentedon Sep 21, 2026
Scope notes from reconciling this with source-cooperative/source.coop#491:
multistore-sts(lib.rs, wheresubbecomessource_identity), not the proxy; the proxy's only hook sees the Role id, never the token. So it is a breaking wire-format change across three repositories — multistore release → proxy version bump → Resolve accounts by (issuer, subject) source.coop#543 — andauthenticateWithOidcTokentreatssubas a bare Ory identity id, so an issuer-qualified subject 401s every request until the app side lands.STS_MAX_SESSION_DURATION_SECS, and the Workers cache holds old-format keys for up to 300s. Both formats are live during rollout; the rollout plan should say so.user_idun-namespaced by issuer too, so historical rows are already ambiguous. Qualifying it here is cheap. Audit logging of exchanges belongs here as an acceptance criterion.feat(accounts): resolve accounts by (issuer, subject) (#565)
alukach commentedon Sep 23, 2026
Contract change from source-cooperative/source.coop#566: the API no longer resolves
(issuer, subject)to an account. Instead, after verifying a platform-IdP token and reading the account fromRoleArn, the proxy callsPOST /api/v1/accounts/{account_id}/trusts/exchangeswith{ issuer, subject }(the verifiedissandsub), authenticated as that account — the same way it calls the keysexchangesroute. 200{trusted: true}means mint; 403 means deny. The principal it then forwards on proxied requests is the account id, as for API keys. Ory tokens are unchanged. Cache the answer like the keys standing (60s).feat(sts): serve the FullAccess and ReadOnly roles (#236)
feat(sts): let platform IdP tokens act as accounts that trust them (#237