One sign-in for decePubClient: the root JWT exchanged for a persona's token
The first-party client signs in on /clientapi and exchanges that JWT on /oauth/token (RFC 8693, subject_token_type jwt, avatar_id) for one persona's Mastodon token. Only the seeded public application `decepub` holds the grant; RootJwtSubjectToken validates the JWT through RootJwt, which JwtBearer now shares (signature, lifetime, ban, deletion, session stamp). The issued token names the avatar, never the root. Owner decision recorded in ROADMAP; it supersedes "moving decePubClient onto the Mastodon API is out of scope". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
c7e8760ffe
commit
2cd75176a4
10 files changed
+432
-30
No files matched your search
@@ -28,15 +28,10 @@ namespace PrivaPub.Services
|
||||
? default
|
||||
: await context.HttpContext.RequestServices.GetRequiredService<DbEntities>().RootUsers.MatchID(rootId)
|
||||
.ExecuteFirstAsync(context.HttpContext.RequestAborted);
|
||||
if (root is not { IsBanned: false, DeletedAt: null })
|
||||
var refusal = RootJwt.Refusal(root, context.Principal);
|
||||
if (refusal != default)
|
||||
{
|
||||
context.Fail("The account can no longer be used.");
|
||||
return;
|
||||
}
|
||||
// a password recovery ends every session made before it (RootSessions gives the root a new stamp)
|
||||
if ((root.SessionStamp ?? string.Empty) != (context.Principal.FindFirst(AuthTokenManager.SessionStamp)?.Value ?? string.Empty))
|
||||
{
|
||||
context.Fail("The account's sessions were ended.");
|
||||
context.Fail(refusal);
|
||||
return;
|
||||
}
|
||||
if (context.Principal.Identity is not ClaimsIdentity identity)
|
||||
|
||||
Reference in new issue
Block a user