diff options
| author | James Elliott <james-d-elliott@users.noreply.github.com> | 2022-10-20 13:16:36 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-20 13:16:36 +1100 |
| commit | 3aaca0604f2ed479d7f00fb5087ffed059f87a71 (patch) | |
| tree | dfa3a2622b3368fac30d5eee2956b4d5fcc5fa17 /internal/storage/sql_provider.go | |
| parent | b1a6dae99ac5b34f065391e266ac1cd87bac5b14 (diff) | |
feat(oidc): implicit consent (#4080)
This adds multiple consent modes to OpenID Connect clients. Specifically it allows configuration of a new consent mode called implicit which never asks for user consent.
Diffstat (limited to 'internal/storage/sql_provider.go')
| -rw-r--r-- | internal/storage/sql_provider.go | 84 |
1 files changed, 57 insertions, 27 deletions
diff --git a/internal/storage/sql_provider.go b/internal/storage/sql_provider.go index 6991e7021..7ee60ab5c 100644 --- a/internal/storage/sql_provider.go +++ b/internal/storage/sql_provider.go @@ -6,6 +6,7 @@ import ( "database/sql" "errors" "fmt" + "strings" "time" "github.com/google/uuid" @@ -73,6 +74,15 @@ func NewSQLProvider(config *schema.Configuration, name, driverName, dataSourceNa sqlSelectUserOpaqueIdentifiers: fmt.Sprintf(queryFmtSelectUserOpaqueIdentifiers, tableUserOpaqueIdentifier), sqlSelectUserOpaqueIdentifierBySignature: fmt.Sprintf(queryFmtSelectUserOpaqueIdentifierBySignature, tableUserOpaqueIdentifier), + sqlInsertOAuth2ConsentPreConfiguration: fmt.Sprintf(queryFmtInsertOAuth2ConsentPreConfiguration, tableOAuth2ConsentPreConfiguration), + sqlSelectOAuth2ConsentPreConfigurations: fmt.Sprintf(queryFmtSelectOAuth2ConsentPreConfigurations, tableOAuth2ConsentPreConfiguration), + + sqlInsertOAuth2ConsentSession: fmt.Sprintf(queryFmtInsertOAuth2ConsentSession, tableOAuth2ConsentSession), + sqlUpdateOAuth2ConsentSessionSubject: fmt.Sprintf(queryFmtUpdateOAuth2ConsentSessionSubject, tableOAuth2ConsentSession), + sqlUpdateOAuth2ConsentSessionResponse: fmt.Sprintf(queryFmtUpdateOAuth2ConsentSessionResponse, tableOAuth2ConsentSession), + sqlUpdateOAuth2ConsentSessionGranted: fmt.Sprintf(queryFmtUpdateOAuth2ConsentSessionGranted, tableOAuth2ConsentSession), + sqlSelectOAuth2ConsentSessionByChallengeID: fmt.Sprintf(queryFmtSelectOAuth2ConsentSessionByChallengeID, tableOAuth2ConsentSession), + sqlInsertOAuth2AuthorizeCodeSession: fmt.Sprintf(queryFmtInsertOAuth2Session, tableOAuth2AuthorizeCodeSession), sqlSelectOAuth2AuthorizeCodeSession: fmt.Sprintf(queryFmtSelectOAuth2Session, tableOAuth2AuthorizeCodeSession), sqlRevokeOAuth2AuthorizeCodeSession: fmt.Sprintf(queryFmtRevokeOAuth2Session, tableOAuth2AuthorizeCodeSession), @@ -108,13 +118,6 @@ func NewSQLProvider(config *schema.Configuration, name, driverName, dataSourceNa sqlDeactivateOAuth2OpenIDConnectSession: fmt.Sprintf(queryFmtDeactivateOAuth2Session, tableOAuth2OpenIDConnectSession), sqlDeactivateOAuth2OpenIDConnectSessionByRequestID: fmt.Sprintf(queryFmtDeactivateOAuth2SessionByRequestID, tableOAuth2OpenIDConnectSession), - sqlInsertOAuth2ConsentSession: fmt.Sprintf(queryFmtInsertOAuth2ConsentSession, tableOAuth2ConsentSession), - sqlUpdateOAuth2ConsentSessionSubject: fmt.Sprintf(queryFmtUpdateOAuth2ConsentSessionSubject, tableOAuth2ConsentSession), - sqlUpdateOAuth2ConsentSessionResponse: fmt.Sprintf(queryFmtUpdateOAuth2ConsentSessionResponse, tableOAuth2ConsentSession), - sqlUpdateOAuth2ConsentSessionGranted: fmt.Sprintf(queryFmtUpdateOAuth2ConsentSessionGranted, tableOAuth2ConsentSession), - sqlSelectOAuth2ConsentSessionByChallengeID: fmt.Sprintf(queryFmtSelectOAuth2ConsentSessionByChallengeID, tableOAuth2ConsentSession), - sqlSelectOAuth2ConsentSessionsPreConfigured: fmt.Sprintf(queryFmtSelectOAuth2ConsentSessionsPreConfigured, tableOAuth2ConsentSession), - sqlUpsertOAuth2BlacklistedJTI: fmt.Sprintf(queryFmtUpsertOAuth2BlacklistedJTI, tableOAuth2BlacklistedJTI), sqlSelectOAuth2BlacklistedJTI: fmt.Sprintf(queryFmtSelectOAuth2BlacklistedJTI, tableOAuth2BlacklistedJTI), @@ -202,6 +205,17 @@ type SQLProvider struct { sqlUpsertEncryptionValue string sqlSelectEncryptionValue string + // Table: oauth2_consent_preconfiguration. + sqlInsertOAuth2ConsentPreConfiguration string + sqlSelectOAuth2ConsentPreConfigurations string + + // Table: oauth2_consent_session. + sqlInsertOAuth2ConsentSession string + sqlUpdateOAuth2ConsentSessionSubject string + sqlUpdateOAuth2ConsentSessionResponse string + sqlUpdateOAuth2ConsentSessionGranted string + sqlSelectOAuth2ConsentSessionByChallengeID string + // Table: oauth2_authorization_code_session. sqlInsertOAuth2AuthorizeCodeSession string sqlSelectOAuth2AuthorizeCodeSession string @@ -242,14 +256,6 @@ type SQLProvider struct { sqlDeactivateOAuth2OpenIDConnectSession string sqlDeactivateOAuth2OpenIDConnectSessionByRequestID string - // Table: oauth2_consent_session. - sqlInsertOAuth2ConsentSession string - sqlUpdateOAuth2ConsentSessionSubject string - sqlUpdateOAuth2ConsentSessionResponse string - sqlUpdateOAuth2ConsentSessionGranted string - sqlSelectOAuth2ConsentSessionByChallengeID string - sqlSelectOAuth2ConsentSessionsPreConfigured string - sqlUpsertOAuth2BlacklistedJTI string sqlSelectOAuth2BlacklistedJTI string @@ -404,8 +410,8 @@ func (p *SQLProvider) LoadUserOpaqueIdentifierBySignature(ctx context.Context, s func (p *SQLProvider) SaveOAuth2ConsentSession(ctx context.Context, consent model.OAuth2ConsentSession) (err error) { if _, err = p.db.ExecContext(ctx, p.sqlInsertOAuth2ConsentSession, consent.ChallengeID, consent.ClientID, consent.Subject, consent.Authorized, consent.Granted, - consent.RequestedAt, consent.RespondedAt, consent.ExpiresAt, consent.Form, - consent.RequestedScopes, consent.GrantedScopes, consent.RequestedAudience, consent.GrantedAudience); err != nil { + consent.RequestedAt, consent.RespondedAt, consent.Form, + consent.RequestedScopes, consent.GrantedScopes, consent.RequestedAudience, consent.GrantedAudience, consent.PreConfiguration); err != nil { return fmt.Errorf("error inserting oauth2 consent session with challenge id '%s' for subject '%s': %w", consent.ChallengeID.String(), consent.Subject.UUID.String(), err) } @@ -423,7 +429,7 @@ func (p *SQLProvider) SaveOAuth2ConsentSessionSubject(ctx context.Context, conse // SaveOAuth2ConsentSessionResponse updates an OAuth2.0 consent session with the response. func (p *SQLProvider) SaveOAuth2ConsentSessionResponse(ctx context.Context, consent model.OAuth2ConsentSession, authorized bool) (err error) { - if _, err = p.db.ExecContext(ctx, p.sqlUpdateOAuth2ConsentSessionResponse, authorized, consent.ExpiresAt, consent.GrantedScopes, consent.GrantedAudience, consent.ID); err != nil { + if _, err = p.db.ExecContext(ctx, p.sqlUpdateOAuth2ConsentSessionResponse, authorized, consent.GrantedScopes, consent.GrantedAudience, consent.PreConfiguration, consent.ID); err != nil { return fmt.Errorf("error updating oauth2 consent session (authorized '%t') with id '%d' and challenge id '%s' for subject '%s': %w", authorized, consent.ID, consent.ChallengeID, consent.Subject.UUID, err) } @@ -450,19 +456,43 @@ func (p *SQLProvider) LoadOAuth2ConsentSessionByChallengeID(ctx context.Context, return consent, nil } -// LoadOAuth2ConsentSessionsPreConfigured returns an OAuth2.0 consents that are pre-configured given the consent signature. -func (p *SQLProvider) LoadOAuth2ConsentSessionsPreConfigured(ctx context.Context, clientID string, subject uuid.UUID) (rows *ConsentSessionRows, err error) { +// SaveOAuth2ConsentPreConfiguration inserts an OAuth2.0 consent pre-configuration. +func (p *SQLProvider) SaveOAuth2ConsentPreConfiguration(ctx context.Context, config model.OAuth2ConsentPreConfig) (insertedID int64, err error) { + switch p.name { + case providerPostgres: + if err = p.db.GetContext(ctx, &insertedID, p.sqlInsertOAuth2ConsentPreConfiguration, + config.ClientID, config.Subject, config.CreatedAt, config.ExpiresAt, + config.Revoked, config.Scopes, config.Audience); err != nil { + return -1, fmt.Errorf("error inserting oauth2 consent pre-configuration for subject '%s' with client id '%s' and scopes '%s': %w", config.Subject.String(), config.ClientID, strings.Join(config.Scopes, " "), err) + } + + return insertedID, nil + default: + var result sql.Result + + if result, err = p.db.ExecContext(ctx, p.sqlInsertOAuth2ConsentPreConfiguration, + config.ClientID, config.Subject, config.CreatedAt, config.ExpiresAt, + config.Revoked, config.Scopes, config.Audience); err != nil { + return -1, fmt.Errorf("error inserting oauth2 consent pre-configuration for subject '%s' with client id '%s' and scopes '%s': %w", config.Subject.String(), config.ClientID, strings.Join(config.Scopes, " "), err) + } + + return result.LastInsertId() + } +} + +// LoadOAuth2ConsentPreConfigurations returns an OAuth2.0 consents pre-configurations given the consent signature. +func (p *SQLProvider) LoadOAuth2ConsentPreConfigurations(ctx context.Context, clientID string, subject uuid.UUID) (rows *ConsentPreConfigRows, err error) { var r *sqlx.Rows - if r, err = p.db.QueryxContext(ctx, p.sqlSelectOAuth2ConsentSessionsPreConfigured, clientID, subject); err != nil { + if r, err = p.db.QueryxContext(ctx, p.sqlSelectOAuth2ConsentPreConfigurations, clientID, subject); err != nil { if errors.Is(err, sql.ErrNoRows) { - return &ConsentSessionRows{}, nil + return &ConsentPreConfigRows{}, nil } - return &ConsentSessionRows{}, fmt.Errorf("error selecting oauth2 consent session by signature with client id '%s' and subject '%s': %w", clientID, subject.String(), err) + return &ConsentPreConfigRows{}, fmt.Errorf("error selecting oauth2 consent pre-configurations by signature with client id '%s' and subject '%s': %w", clientID, subject.String(), err) } - return &ConsentSessionRows{rows: r}, nil + return &ConsentPreConfigRows{rows: r}, nil } // SaveOAuth2Session saves a OAuth2Session to the database. @@ -724,7 +754,7 @@ func (p *SQLProvider) FindIdentityVerification(ctx context.Context, jti string) } switch { - case verification.Consumed != nil: + case verification.Consumed.Valid: return false, fmt.Errorf("the token has already been consumed") case verification.ExpiresAt.Before(time.Now()): return false, fmt.Errorf("the token expired %s ago", time.Since(verification.ExpiresAt)) @@ -750,7 +780,7 @@ func (p *SQLProvider) SaveTOTPConfiguration(ctx context.Context, config model.TO } // UpdateTOTPConfigurationSignIn updates a registered Webauthn devices sign in information. -func (p *SQLProvider) UpdateTOTPConfigurationSignIn(ctx context.Context, id int, lastUsedAt *time.Time) (err error) { +func (p *SQLProvider) UpdateTOTPConfigurationSignIn(ctx context.Context, id int, lastUsedAt sql.NullTime) (err error) { if _, err = p.db.ExecContext(ctx, p.sqlUpdateTOTPConfigRecordSignIn, lastUsedAt, id); err != nil { return fmt.Errorf("error updating TOTP configuration id %d: %w", id, err) } @@ -841,7 +871,7 @@ func (p *SQLProvider) SaveWebauthnDevice(ctx context.Context, device model.Webau } // UpdateWebauthnDeviceSignIn updates a registered Webauthn devices sign in information. -func (p *SQLProvider) UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt *time.Time, signCount uint32, cloneWarning bool) (err error) { +func (p *SQLProvider) UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt sql.NullTime, signCount uint32, cloneWarning bool) (err error) { if _, err = p.db.ExecContext(ctx, p.sqlUpdateWebauthnDeviceRecordSignIn, rpid, lastUsedAt, signCount, cloneWarning, id); err != nil { return fmt.Errorf("error updating Webauthn signin metadata for id '%x': %w", id, err) } |
