feat(auth)!: unified session model and a reliable session lifecycle #124
Labels
No labels
breaking-change
bug
documentation
duplicate
enhancement
good first issue
help wanted
performance
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/ATProto.NET#124
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of the v0.7.0 update cycle (wave 5). Session handling has several correctness bugs, and two parallel persistence abstractions, one of which is never read.
Bugs
deleteSessionrequires the refresh JWT but is sent the access JWT, and the error is swallowed. OAuth logout never calls the revocation endpoint. Fix both:deleteSession(refreshJwt), and RFC 7009 revocation with DPoP for OAuth. Surface failures after local teardown.RefreshTokensAsyncnever checks the HTTP status, so aninvalid_grantbody becomes an empty access token that the client then uses.ResumeSessionAsyncon a fresh client throws "No session to refresh" instead of refreshing, which the docs promise it does.Server.CreateSessionAsync/CreateAccountAsync/DeleteSessionAsync). Make sub-clients stateless; onlyAtProtoClientinstalls sessions. Add aCreateAccountAndLoginAsyncconvenience.ExpiredTokenor DPoPinvalid_token.Model
abstract record AtProtoSession(Did, Handle, Uri ServiceEndpoint)withPasswordSessionandOAuthSession(immutable,ExpiresAtinstead ofExpiresIn+ obtained-at).AtProtoClient.Sessionbecomes the single property. Addevent SessionChanged(Created / Refreshed / Expired / Removed).ISessionStore(whoseLoadAsyncthe SDK never calls) andIAtProtoTokenStore. Keep the in-memory, file and EF implementations working, and document the EF migration if the schema changes.DelegatingHandler: proactive refresh beforeExpiresAt - skew(decodeexpfrom legacy JWTs instead of assuming 115 min), and a single-flight reactive refresh plus one retry onExpiredToken/invalid_token, with a refresh generation check so concurrent callers don't refresh twice. The background timer becomes optional.LoginAsync(AtIdentifier, password): when no service URL was configured explicitly, resolve handle → DID → PDS through the identity resolver, and adopt thedidDocPDS thatcreateSessionreturns.Lifetime
DisposeAsyncis primary. SynchronousDisposemust not block up to 35 s waiting for the timer.ServiceAuthGenerator(…, ownsKey: false)).CHANGELOG
Breaking changes(session types, store interface,deleteSessionsignature, sub-client side effects) with migration notes;Fixedfor every bug.