Manage session time fields centrally

This commit is contained in:
Nick Meves
2021-06-21 21:54:52 -07:00
parent 7e80e5596b
commit 7fa6d2d024
11 changed files with 91 additions and 64 deletions
+12 -18
View File
@@ -142,16 +142,13 @@ func (p *AzureProvider) Redeem(ctx context.Context, redirectURL, code string) (*
return nil, err
}
created := time.Now()
expires := time.Unix(jsonResponse.ExpiresOn, 0)
session := &sessions.SessionState{
AccessToken: jsonResponse.AccessToken,
IDToken: jsonResponse.IDToken,
CreatedAt: &created,
ExpiresOn: &expires,
RefreshToken: jsonResponse.RefreshToken,
}
session.CreatedAtNow()
session.SetExpiresOn(time.Unix(jsonResponse.ExpiresOn, 0))
email, err := p.verifyTokenAndExtractEmail(ctx, session.IDToken)
@@ -239,10 +236,9 @@ func (p *AzureProvider) verifyTokenAndExtractEmail(ctx context.Context, token st
return email, nil
}
// RefreshSessionIfNeeded checks if the session has expired and uses the
// RefreshToken to fetch a new ID token if required
func (p *AzureProvider) RefreshSessionIfNeeded(ctx context.Context, s *sessions.SessionState) (bool, error) {
if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" {
// RefreshSession uses the RefreshToken to fetch new Access and ID Tokens
func (p *AzureProvider) RefreshSession(ctx context.Context, s *sessions.SessionState) (bool, error) {
if s == nil || s.RefreshToken == "" {
return false, nil
}
@@ -257,7 +253,7 @@ func (p *AzureProvider) RefreshSessionIfNeeded(ctx context.Context, s *sessions.
return true, nil
}
func (p *AzureProvider) redeemRefreshToken(ctx context.Context, s *sessions.SessionState) (err error) {
func (p *AzureProvider) redeemRefreshToken(ctx context.Context, s *sessions.SessionState) error {
params := url.Values{}
params.Add("client_id", p.ClientID)
params.Add("client_secret", p.ClientSecret)
@@ -271,25 +267,23 @@ func (p *AzureProvider) redeemRefreshToken(ctx context.Context, s *sessions.Sess
IDToken string `json:"id_token"`
}
err = requests.New(p.RedeemURL.String()).
err := requests.New(p.RedeemURL.String()).
WithContext(ctx).
WithMethod("POST").
WithBody(bytes.NewBufferString(params.Encode())).
SetHeader("Content-Type", "application/x-www-form-urlencoded").
Do().
UnmarshalInto(&jsonResponse)
if err != nil {
return
return err
}
now := time.Now()
expires := time.Unix(jsonResponse.ExpiresOn, 0)
s.AccessToken = jsonResponse.AccessToken
s.IDToken = jsonResponse.IDToken
s.RefreshToken = jsonResponse.RefreshToken
s.CreatedAt = &now
s.ExpiresOn = &expires
s.CreatedAtNow()
s.SetExpiresOn(time.Unix(jsonResponse.ExpiresOn, 0))
email, err := p.verifyTokenAndExtractEmail(ctx, s.IDToken)
@@ -312,7 +306,7 @@ func (p *AzureProvider) redeemRefreshToken(ctx context.Context, s *sessions.Sess
}
}
return
return nil
}
func makeAzureHeader(accessToken string) http.Header {
+7 -5
View File
@@ -259,14 +259,16 @@ func (p *GitLabProvider) createSession(ctx context.Context, token *oauth2.Token)
}
}
created := time.Now()
return &sessions.SessionState{
ss := &sessions.SessionState{
AccessToken: token.AccessToken,
IDToken: getIDToken(token),
RefreshToken: token.RefreshToken,
CreatedAt: &created,
ExpiresOn: &idToken.Expiry,
}, nil
}
ss.CreatedAtNow()
ss.SetExpiresOn(idToken.Expiry)
return ss, nil
}
// ValidateSession checks that the session's IDToken is still valid
+12 -13
View File
@@ -163,23 +163,22 @@ func (p *GoogleProvider) Redeem(ctx context.Context, redirectURL, code string) (
return nil, err
}
created := time.Now()
expires := time.Now().Add(time.Duration(jsonResponse.ExpiresIn) * time.Second).Truncate(time.Second)
return &sessions.SessionState{
ss := &sessions.SessionState{
AccessToken: jsonResponse.AccessToken,
IDToken: jsonResponse.IDToken,
CreatedAt: &created,
ExpiresOn: &expires,
RefreshToken: jsonResponse.RefreshToken,
Email: c.Email,
User: c.Subject,
}, nil
}
ss.CreatedAtNow()
ss.ExpiresIn(time.Duration(jsonResponse.ExpiresIn) * time.Second)
return ss, nil
}
// EnrichSession checks the listed Google Groups configured and adds any
// that the user is a member of to session.Groups.
func (p *GoogleProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
func (p *GoogleProvider) EnrichSession(_ context.Context, s *sessions.SessionState) error {
// TODO (@NickMeves) - Move to pure EnrichSession logic and stop
// reusing legacy `groupValidator`.
//
@@ -272,7 +271,7 @@ func (p *GoogleProvider) RefreshSession(ctx context.Context, s *sessions.Session
return false, nil
}
newToken, newIDToken, duration, err := p.redeemRefreshToken(ctx, s.RefreshToken)
newToken, newIDToken, ttl, err := p.redeemRefreshToken(ctx, s.RefreshToken)
if err != nil {
return false, err
}
@@ -285,12 +284,12 @@ func (p *GoogleProvider) RefreshSession(ctx context.Context, s *sessions.Session
return false, fmt.Errorf("%s is no longer in the group(s)", s.Email)
}
origExpiration := s.ExpiresOn
expires := time.Now().Add(duration).Truncate(time.Second)
s.AccessToken = newToken
s.IDToken = newIDToken
s.ExpiresOn = &expires
logger.Printf("refreshed access token %s (expired on %s)", s, origExpiration)
s.CreatedAtNow()
s.ExpiresIn(ttl)
return true, nil
}
+8 -9
View File
@@ -159,7 +159,7 @@ func emailFromUserInfo(ctx context.Context, accessToken string, userInfoEndpoint
}
// Redeem exchanges the OAuth2 authentication token for an ID token
func (p *LoginGovProvider) Redeem(ctx context.Context, redirectURL, code string) (*sessions.SessionState, error) {
func (p *LoginGovProvider) Redeem(ctx context.Context, _, code string) (*sessions.SessionState, error) {
if code == "" {
return nil, ErrMissingCode
}
@@ -214,17 +214,16 @@ func (p *LoginGovProvider) Redeem(ctx context.Context, redirectURL, code string)
return nil, err
}
created := time.Now()
expires := time.Now().Add(time.Duration(jsonResponse.ExpiresIn) * time.Second).Truncate(time.Second)
// Store the data that we found in the session state
return &sessions.SessionState{
session := &sessions.SessionState{
AccessToken: jsonResponse.AccessToken,
IDToken: jsonResponse.IDToken,
CreatedAt: &created,
ExpiresOn: &expires,
Email: email,
}, nil
}
session.CreatedAtNow()
session.ExpiresIn(time.Duration(jsonResponse.ExpiresIn) * time.Second)
return session, nil
}
// GetLoginURL overrides GetLoginURL to add login.gov parameters
+5 -4
View File
@@ -226,7 +226,9 @@ func (p *OIDCProvider) CreateSessionFromToken(ctx context.Context, token string)
ss.AccessToken = token
ss.IDToken = token
ss.RefreshToken = ""
ss.ExpiresOn = &idToken.Expiry
ss.CreatedAtNow()
ss.SetExpiresOn(idToken.Expiry)
return ss, nil
}
@@ -256,9 +258,8 @@ func (p *OIDCProvider) createSession(ctx context.Context, token *oauth2.Token, r
ss.RefreshToken = token.RefreshToken
ss.IDToken = getIDToken(token)
created := time.Now()
ss.CreatedAt = &created
ss.ExpiresOn = &token.Expiry
ss.CreatedAtNow()
ss.SetExpiresOn(token.Expiry)
return ss, nil
}
+6 -3
View File
@@ -6,7 +6,6 @@ import (
"errors"
"fmt"
"net/url"
"time"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
@@ -85,9 +84,13 @@ func (p *ProviderData) Redeem(ctx context.Context, redirectURL, code string) (*s
if err != nil {
return nil, err
}
// TODO (@NickMeves): Uses OAuth `expires_in` to set an expiration
if token := values.Get("access_token"); token != "" {
created := time.Now()
return &sessions.SessionState{AccessToken: token, CreatedAt: &created}, nil
ss := &sessions.SessionState{
AccessToken: token,
}
ss.CreatedAtNow()
return ss, nil
}
return nil, fmt.Errorf("no access token found %s", result.Body())