docs: state the one-second blind spot of the account link's auth_time proof
This commit is contained in:
@@ -242,7 +242,12 @@ func requestUsable(req *models.BackendLinkRequest, now time.Time) error {
|
||||
// session token's auth_time claim (bouncer.VerifyAuthTime): the time of the
|
||||
// sign-in itself, which a refresh copies and never renews. It is compared in
|
||||
// whole seconds with the request's created_at because the claim has no
|
||||
// fraction; a zero time is ErrStaleSession. Neither
|
||||
// fraction, which leaves a one-second blind spot: a sign-in earlier in the
|
||||
// same second as the request, but before it, counts as fresh. Telling the
|
||||
// two apart would need a sub-second claim; refusing that whole second
|
||||
// instead would make a sign-in in the request's own second sign in once
|
||||
// more. The window is accepted (it needs a sign-in in the very second the
|
||||
// administrator starts the link). A zero time is ErrStaleSession. Neither
|
||||
// account may be linked already (ErrAlreadyLinked) and the administrator
|
||||
// must still be activated (ErrBackendUserUnavailable). The request is used
|
||||
// up with the link; BackendLinkedEvent fires inside the transaction and the
|
||||
@@ -273,6 +278,7 @@ func (s *BackendLinks) ConfirmLinkRequest(ctx context.Context, plain string, fro
|
||||
if err := requestUsable(req, now); err != nil {
|
||||
return err
|
||||
}
|
||||
// Whole seconds on both sides: see the blind spot above.
|
||||
if sessionAuthTime.IsZero() || sessionAuthTime.Before(req.CreatedAt.Truncate(time.Second)) {
|
||||
return ErrStaleSession
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user