Skip to content

Commit

Permalink
feat: extend latest and session related consents
Browse files Browse the repository at this point in the history
  • Loading branch information
aarmam committed Mar 25, 2022
1 parent 00100a1 commit d703604
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
7 changes: 7 additions & 0 deletions consent/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,13 @@ func (h *Handler) AcceptConsentRequest(w http.ResponseWriter, r *http.Request, p
h.r.Writer().WriteError(w, r, errorsx.WithStack(err))
return
} else if hr.Skip {
if p.Remember && p.RememberFor > 0 { // TODO: Consider removing 'p.RememberFor > 0' to update consent validity in both ways (limited (RememberFor > 0) -> indefinitely (RememberFor = 0) and vice versa)
err = h.r.ConsentManager().ExtendConsentRequest(r.Context(), h.r.ScopeStrategy(), hr, p.RememberFor)
if err != nil {
h.r.Writer().WriteError(w, r, errorsx.WithStack(err))
return
}
}
p.Remember = false
}

Expand Down
3 changes: 3 additions & 0 deletions consent/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"context"
"time"

"github.com/ory/fosite"

"github.com/ory/hydra/client"
)

Expand All @@ -41,6 +43,7 @@ type Manager interface {
CreateConsentRequest(ctx context.Context, req *ConsentRequest) error
GetConsentRequest(ctx context.Context, challenge string) (*ConsentRequest, error)
HandleConsentRequest(ctx context.Context, challenge string, r *HandledConsentRequest) (*ConsentRequest, error)
ExtendConsentRequest(ctx context.Context, scopeStrategy fosite.ScopeStrategy, cr *ConsentRequest, extendBy int) error
RevokeSubjectConsentSession(ctx context.Context, user string) error
RevokeSubjectClientConsentSession(ctx context.Context, user, client string) error

Expand Down
68 changes: 68 additions & 0 deletions persistence/sql/persister_consent.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,74 @@ func (p *Persister) HandleConsentRequest(ctx context.Context, challenge string,
return p.GetConsentRequest(ctx, challenge)
}

func (p *Persister) ExtendConsentRequest(ctx context.Context, scopeStrategy fosite.ScopeStrategy, cr *consent.ConsentRequest, extendBy int) error {
return p.transaction(ctx, func(ctx context.Context, c *pop.Connection) error {
tn := consent.HandledConsentRequest{}.TableName()

var sessionHcr consent.HandledConsentRequest
if err := c.
Where(fmt.Sprintf("r.subject = ? AND r.client_id = ? AND r.login_session_id = ? AND r.skip=FALSE AND (%s.error='{}' AND %s.remember=TRUE)", tn, tn), cr.Subject, cr.ClientID, cr.LoginSessionID.String()).
Join("hydra_oauth2_consent_request AS r", fmt.Sprintf("%s.challenge = r.challenge", tn)).
Order(fmt.Sprintf("%s.requested_at DESC", tn)).
Limit(1).
First(&sessionHcr); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return errorsx.WithStack(consent.ErrNoPreviousConsentFound)
}
return sqlcon.HandleError(err)
}

var latestHcr consent.HandledConsentRequest
if err := c.
Where(fmt.Sprintf("r.subject = ? AND r.client_id = ? AND r.skip=FALSE AND (%s.error='{}' AND %s.remember=TRUE)", tn, tn), cr.Subject, cr.ClientID).
Join("hydra_oauth2_consent_request AS r", fmt.Sprintf("%s.challenge = r.challenge", tn)).
Order(fmt.Sprintf("%s.requested_at DESC", tn)).
Limit(1).
First(&latestHcr); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return errorsx.WithStack(consent.ErrNoPreviousConsentFound)
}
return sqlcon.HandleError(err)
}

if err := p.extendHandledConsentRequest(ctx, cr, scopeStrategy, sessionHcr, extendBy); err != nil {
return err
}

if latestHcr.ID != sessionHcr.ID {
if err := p.extendHandledConsentRequest(ctx, cr, scopeStrategy, latestHcr, extendBy); err != nil {
return err
}
}
return nil
})
}

func (p *Persister) extendHandledConsentRequest(ctx context.Context, cr *consent.ConsentRequest, scopeStrategy fosite.ScopeStrategy, hcr consent.HandledConsentRequest, extendBy int) error {
for _, scope := range cr.RequestedScope {
if !scopeStrategy(hcr.GrantedScope, scope) {
return nil
}
}

isConsentRequestExpired := hcr.RememberFor > 0 && hcr.RequestedAt.Add(time.Duration(hcr.RememberFor)*time.Second).Before(time.Now().UTC())
if isConsentRequestExpired {
return nil
}

remainingTime := hcr.RequestedAt.Unix() + int64(hcr.RememberFor) - time.Now().Unix()
if remainingTime > 0 {
hcr.RememberFor = hcr.RememberFor + extendBy - int(remainingTime)
} else {
hcr.RememberFor = hcr.RememberFor + extendBy
}

if err := sqlcon.HandleError(p.Connection(ctx).Update(&hcr)); err != nil {
return err
}
return nil
}

func (p *Persister) VerifyAndInvalidateConsentRequest(ctx context.Context, verifier string) (*consent.HandledConsentRequest, error) {
var r consent.HandledConsentRequest
return &r, p.transaction(ctx, func(ctx context.Context, c *pop.Connection) error {
Expand Down

0 comments on commit d703604

Please sign in to comment.