diff --git a/internal/models/types.go b/internal/models/types.go index a0c6e7e8..9e752b73 100644 --- a/internal/models/types.go +++ b/internal/models/types.go @@ -51,6 +51,8 @@ func (ip *IP) Scan(src interface{}) (err error) { switch v := src.(type) { case string: value = v + case []byte: + value = string(v) default: return fmt.Errorf("invalid type %T for IP %v", src, src) } @@ -86,6 +88,8 @@ func (ip *NullIP) Scan(src interface{}) (err error) { switch v := src.(type) { case string: value = v + case []byte: + value = string(v) default: return fmt.Errorf("invalid type %T for NullIP %v", src, src) } diff --git a/internal/storage/sql_provider.go b/internal/storage/sql_provider.go index 4d4b71ad..785ae619 100644 --- a/internal/storage/sql_provider.go +++ b/internal/storage/sql_provider.go @@ -33,9 +33,9 @@ func NewSQLProvider(config *schema.Configuration, name, driverName, dataSourceNa sqlInsertAuthenticationAttempt: fmt.Sprintf(queryFmtInsertAuthenticationLogEntry, tableAuthenticationLogs), sqlSelectAuthenticationAttemptsByUsername: fmt.Sprintf(queryFmtSelect1FAAuthenticationLogEntryByUsername, tableAuthenticationLogs), - sqlInsertIdentityVerification: fmt.Sprintf(queryFmtInsertIdentityVerification, tableIdentityVerification), - sqlConsumeIdentityVerification: fmt.Sprintf(queryFmtConsumeIdentityVerification, tableIdentityVerification), - sqlSelectExistsIdentityVerification: fmt.Sprintf(queryFmtSelectExistsIdentityVerification, tableIdentityVerification), + sqlInsertIdentityVerification: fmt.Sprintf(queryFmtInsertIdentityVerification, tableIdentityVerification), + sqlConsumeIdentityVerification: fmt.Sprintf(queryFmtConsumeIdentityVerification, tableIdentityVerification), + sqlSelectIdentityVerification: fmt.Sprintf(queryFmtSelectIdentityVerification, tableIdentityVerification), sqlUpsertTOTPConfig: fmt.Sprintf(queryFmtUpsertTOTPConfiguration, tableTOTPConfigurations), sqlDeleteTOTPConfig: fmt.Sprintf(queryFmtDeleteTOTPConfiguration, tableTOTPConfigurations), @@ -90,9 +90,9 @@ type SQLProvider struct { sqlSelectAuthenticationAttemptsByUsername string // Table: identity_verification. - sqlInsertIdentityVerification string - sqlConsumeIdentityVerification string - sqlSelectExistsIdentityVerification string + sqlInsertIdentityVerification string + sqlConsumeIdentityVerification string + sqlSelectIdentityVerification string // Table: totp_configurations. sqlUpsertTOTPConfig string @@ -245,11 +245,21 @@ func (p *SQLProvider) ConsumeIdentityVerification(ctx context.Context, jti strin // FindIdentityVerification checks if an identity verification record is in the database and active. func (p *SQLProvider) FindIdentityVerification(ctx context.Context, jti string) (found bool, err error) { - if err = p.db.GetContext(ctx, &found, p.sqlSelectExistsIdentityVerification, jti); err != nil { + verification := models.IdentityVerification{} + if err = p.db.GetContext(ctx, &verification, p.sqlSelectIdentityVerification, jti); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return false, nil + } + return false, fmt.Errorf("error selecting identity verification exists: %w", err) } - return found, nil + switch { + case verification.Consumed != nil, verification.ExpiresAt.Before(time.Now()): + return false, nil + default: + return true, nil + } } // SaveTOTPConfiguration save a TOTP configuration of a given user in the database. diff --git a/internal/storage/sql_provider_backend_postgres.go b/internal/storage/sql_provider_backend_postgres.go index e70718dd..e371569b 100644 --- a/internal/storage/sql_provider_backend_postgres.go +++ b/internal/storage/sql_provider_backend_postgres.go @@ -36,7 +36,7 @@ func NewPostgreSQLProvider(config *schema.Configuration) (provider *PostgreSQLPr provider.sqlFmtRenameTable = provider.db.Rebind(provider.sqlFmtRenameTable) provider.sqlSelectPreferred2FAMethod = provider.db.Rebind(provider.sqlSelectPreferred2FAMethod) provider.sqlSelectUserInfo = provider.db.Rebind(provider.sqlSelectUserInfo) - provider.sqlSelectExistsIdentityVerification = provider.db.Rebind(provider.sqlSelectExistsIdentityVerification) + provider.sqlSelectIdentityVerification = provider.db.Rebind(provider.sqlSelectIdentityVerification) provider.sqlInsertIdentityVerification = provider.db.Rebind(provider.sqlInsertIdentityVerification) provider.sqlConsumeIdentityVerification = provider.db.Rebind(provider.sqlConsumeIdentityVerification) provider.sqlSelectTOTPConfig = provider.db.Rebind(provider.sqlSelectTOTPConfig) diff --git a/internal/storage/sql_provider_queries.go b/internal/storage/sql_provider_queries.go index 1cb9de96..8da7c132 100644 --- a/internal/storage/sql_provider_queries.go +++ b/internal/storage/sql_provider_queries.go @@ -56,12 +56,10 @@ const ( ) const ( - queryFmtSelectExistsIdentityVerification = ` - SELECT EXISTS ( - SELECT id - FROM %s - WHERE jti = ? AND exp > CURRENT_TIMESTAMP AND consumed IS NULL - );` + queryFmtSelectIdentityVerification = ` + SELECT id, jti, iat, issued_ip, exp, username, action, consumed, consumed_ip + FROM %s + WHERE jti = ?;` queryFmtInsertIdentityVerification = ` INSERT INTO %s (jti, iat, issued_ip, exp, username, action)