pub struct UserApproval<'a> { /* private fields */ }Expand description
A statement, by the HOST, that a resource owner saw one validated authorization request and
agreed to it. The only thing AuthorizationServer::issue_authorization_code will mint from.
§Why this type exists
The http feature’s ServiceBuilder REFUSES TO BUILD without a consent resolver, so a host on
that path cannot reach code issuance without having written the word “approve”. The direct API
had no such step, and the direct API is the path this crate’s DEFAULT BUILD invites: no HTTP
surface, no listener, the host owning its own routes. issue_authorization_code(&validated, "alice") read like a lookup, compiled, passed the host’s own tests, and shipped an
authorization server that approved everything. The refusal existed on one of two supported
adoption paths, which is the same as not existing.
§What it is, and what it is not
It is NOT a proof, and no type this crate could define would be one: this library has no user,
no session and no screen, so “the user agreed” is a fact only the host holds. Nor is it weaker
than the seam it mirrors. A host can wire |_| ApprovalDecision::Approve into the http path
just as it can call UserApproval::granted here, so what BOTH seams buy is the same and is
the whole of what a library at this boundary can buy: the approval becomes a sentence the host
WROTE rather than a default it inherited, and the host that never considered RFC 6749 section
10.12 gets a compile error naming it instead of a working forgery endpoint.
It also closes a bug class the two-argument form left open. The approval BORROWS the request it
approves, so there is no second request parameter left to disagree with it: a host cannot prompt
for one request and issue for another, approving a read and minting a read write.
§Allocation
A borrow plus the subject String, which is the same one allocation the old
subject: impl Into<String> argument made on its way into the record. Nothing on the token path
changes, and nothing here is on it.
Implementations§
Source§impl<'a> UserApproval<'a>
impl<'a> UserApproval<'a>
Sourcepub fn granted(
request: &'a ValidatedAuthorizationRequest,
subject: impl Into<String>,
) -> Self
pub fn granted( request: &'a ValidatedAuthorizationRequest, subject: impl Into<String>, ) -> Self
The resource owner named by subject approved request.
CALLING THIS IS AN ASSERTION. It says a real user was really asked about really this request, in whatever the deployment’s consent step is, and said yes. This crate cannot check that and will not try; what it can do is refuse to mint anything until someone writes it.
subject is the authenticated resource owner, in the host’s own vocabulary for users, and
is what the issued code and every token it mints will carry.
Sourcepub fn granted_at(
request: &'a ValidatedAuthorizationRequest,
subject: impl Into<String>,
decided_at: SystemTime,
) -> Self
pub fn granted_at( request: &'a ValidatedAuthorizationRequest, subject: impl Into<String>, decided_at: SystemTime, ) -> Self
The same approval, dated.
WHAT THIS IS FOR, and it is not bookkeeping. A revocation barrier refuses a write whose
GRANT predates the revocation, and the grant instant a code carries is the instant of the
decision it rests on. For a host that prompted the user during this request those are the
same moment and UserApproval::granted is right. For a host acting on a STANDING
approval — a remembered consent it read at the top of the request — they are not, and
dating a months-old approval at this instant makes it outrank a withdrawal recorded in
between.
The failure that costs is precise. The user opens the authorization page; the host reads
their standing consent; the user, elsewhere, clicks “remove this application”, and the
withdrawal cascades away every token and records its barrier; the first request then
resumes and mints a code on the strength of the pre-withdrawal snapshot. Nothing refuses
the code — put_authorization_code is deliberately barrier-exempt — and at redemption a
code dated NOW postdates the barrier, so the token is issued and its refresh chain
inherits the same instant, rotating happily long after the barrier is swept.
Pass the instant the decision was made: the standing record’s own granted_at, or the
instant the request was received, whichever the host can honestly claim. Both are earlier
than any withdrawal that has not yet been read, which is the whole of what is needed.
Sourcepub fn decided_at(&self) -> Option<SystemTime>
pub fn decided_at(&self) -> Option<SystemTime>
When the decision was made, if the host said. See UserApproval::granted_at.
Sourcepub fn request(&self) -> &'a ValidatedAuthorizationRequest
pub fn request(&self) -> &'a ValidatedAuthorizationRequest
The request this approves.
Trait Implementations§
Source§impl Debug for UserApproval<'_>
Hand-written: subject is a user identifier, and this crate does not print those into whatever
caught a {:?}. Which REQUEST is being approved stays visible, because that is the whole of
what anybody debugging an issuance needs.
impl Debug for UserApproval<'_>
Hand-written: subject is a user identifier, and this crate does not print those into whatever
caught a {:?}. Which REQUEST is being approved stays visible, because that is the whole of
what anybody debugging an issuance needs.