fix(storage): duo/u2f upsert failure on postgresql (#2658)

This replaces the standard duo_devices upsert with a PostgreSQL specific one and ensures the u2f_devices upsert uses the new unique key for the ON CONFLICT check.
pull/2626/head^2
James Elliott 2021-12-02 15:16:45 +11:00 committed by GitHub
parent bf9ab360bd
commit a79e4dc592
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 11 deletions

View File

@ -48,9 +48,10 @@ func SecondFactorU2FRegister(ctx *middlewares.AutheliaCtx) {
publicKey := elliptic.Marshal(elliptic.P256(), registration.PubKey.X, registration.PubKey.Y) publicKey := elliptic.Marshal(elliptic.P256(), registration.PubKey.X, registration.PubKey.Y)
err = ctx.Providers.StorageProvider.SaveU2FDevice(ctx, models.U2FDevice{ err = ctx.Providers.StorageProvider.SaveU2FDevice(ctx, models.U2FDevice{
Username: userSession.Username, Username: userSession.Username,
KeyHandle: registration.KeyHandle, Description: "Primary",
PublicKey: publicKey}, KeyHandle: registration.KeyHandle,
PublicKey: publicKey},
) )
if err != nil { if err != nil {

View File

@ -339,8 +339,8 @@ func (p *SQLProvider) UpdateTOTPConfigurationSecret(ctx context.Context, config
// SaveU2FDevice saves a registered U2F device. // SaveU2FDevice saves a registered U2F device.
func (p *SQLProvider) SaveU2FDevice(ctx context.Context, device models.U2FDevice) (err error) { func (p *SQLProvider) SaveU2FDevice(ctx context.Context, device models.U2FDevice) (err error) {
if _, err = p.db.ExecContext(ctx, p.sqlUpsertU2FDevice, device.Username, device.KeyHandle, device.PublicKey); err != nil { if _, err = p.db.ExecContext(ctx, p.sqlUpsertU2FDevice, device.Username, device.Description, device.KeyHandle, device.PublicKey); err != nil {
return fmt.Errorf("error upserting U2F device secret: %v", err) return fmt.Errorf("error upserting U2F device: %v", err)
} }
return nil return nil

View File

@ -27,6 +27,7 @@ func NewPostgreSQLProvider(config *schema.Configuration) (provider *PostgreSQLPr
// Specific alterations to this provider. // Specific alterations to this provider.
// PostgreSQL doesn't have a UPSERT statement but has an ON CONFLICT operation instead. // PostgreSQL doesn't have a UPSERT statement but has an ON CONFLICT operation instead.
provider.sqlUpsertU2FDevice = fmt.Sprintf(queryFmtPostgresUpsertU2FDevice, tableU2FDevices) provider.sqlUpsertU2FDevice = fmt.Sprintf(queryFmtPostgresUpsertU2FDevice, tableU2FDevices)
provider.sqlUpsertDuoDevice = fmt.Sprintf(queryFmtPostgresUpsertDuoDevice, tableDuoDevices)
provider.sqlUpsertTOTPConfig = fmt.Sprintf(queryFmtPostgresUpsertTOTPConfiguration, tableTOTPConfigurations) provider.sqlUpsertTOTPConfig = fmt.Sprintf(queryFmtPostgresUpsertTOTPConfiguration, tableTOTPConfigurations)
provider.sqlUpsertPreferred2FAMethod = fmt.Sprintf(queryFmtPostgresUpsertPreferred2FAMethod, tableUserPreferences) provider.sqlUpsertPreferred2FAMethod = fmt.Sprintf(queryFmtPostgresUpsertPreferred2FAMethod, tableUserPreferences)
provider.sqlUpsertEncryptionValue = fmt.Sprintf(queryFmtPostgresUpsertEncryptionValue, tableEncryption) provider.sqlUpsertEncryptionValue = fmt.Sprintf(queryFmtPostgresUpsertEncryptionValue, tableEncryption)

View File

@ -119,14 +119,14 @@ const (
WHERE username = ?;` WHERE username = ?;`
queryFmtUpsertU2FDevice = ` queryFmtUpsertU2FDevice = `
REPLACE INTO %s (username, key_handle, public_key) REPLACE INTO %s (username, description, key_handle, public_key)
VALUES (?, ?, ?);` VALUES (?, ?, ?, ?);`
queryFmtPostgresUpsertU2FDevice = ` queryFmtPostgresUpsertU2FDevice = `
INSERT INTO %s (username, key_handle, public_key) INSERT INTO %s (username, description, key_handle, public_key)
VALUES ($1, $2, $3) VALUES ($1, $2, $3, $4)
ON CONFLICT (username) ON CONFLICT (username, description)
DO UPDATE SET key_handle=$2, public_key=$3;` DO UPDATE SET key_handle=$3, public_key=$4;`
) )
const ( const (
@ -134,6 +134,12 @@ const (
REPLACE INTO %s (username, device, method) REPLACE INTO %s (username, device, method)
VALUES (?, ?, ?);` VALUES (?, ?, ?);`
queryFmtPostgresUpsertDuoDevice = `
INSERT INTO %s (username, device, method)
VALUES ($1, $2, $3)
ON CONFLICT (username)
DO UPDATE SET device=$2, method=$3;`
queryFmtDeleteDuoDevice = ` queryFmtDeleteDuoDevice = `
DELETE DELETE
FROM %s FROM %s