Compare commits

...

2 commits

Author SHA1 Message Date
a6bcbaf5e9
Note about possible encryption of passkey secrets
Some checks are pending
/ test (push) Waiting to run
2025-03-31 23:23:35 +02:00
0fa8f4f7be
Encrypt totp secrets 2025-03-31 23:23:25 +02:00
3 changed files with 43 additions and 3 deletions

View file

@ -10,5 +10,18 @@ var (
ErrInvalidCombination = errors.New("invalid account and token combination")
ErrProcessTimeout = errors.New("authentication process timed out")
// A user may not login, for whatever reason
ErrCantLogin = errors.New("user can't login")
ErrCantLogin = errors.New("user can't login")
ErrDecryptionFailure = errors.New("failed to decrypt content")
)
type CombinedError struct {
Err1, Err2 error
}
func (c *CombinedError) Is(e error) bool {
return errors.Is(e, c.Err1) || errors.Is(e, c.Err2)
}
func (c *CombinedError) Error() string {
return c.Err1.Error() + " + " + c.Err2.Error()
}

View file

@ -14,6 +14,14 @@ import (
"git.mstar.dev/mstar/linstrom/storage-new/models"
)
// TODO: Check if passkey encryption is viable
// Check if encryption for passkey info data is viable to implement
// and if we should do it.
// Encrypting it would probably require making a custom wrapper struct,
// if even possible. Reason being that login completion still requires to update
// the data post-creation, including matching on unique and stable elements
// of said data
// Start the login process via passkey for a given username.
// Returns the credential options the passkey needs to sign
func (a *Authenticator) StartPasskeyLogin(

View file

@ -27,7 +27,7 @@ func (a *Authenticator) PerformTotpLogin(
if err != nil {
return LoginNextFailure, "", other.Error("auth", "failed to find account", err)
}
secrets := sliceutils.Map(
encryptedSecrets := sliceutils.Map(
sliceutils.Filter(acc.AuthMethods, func(t models.UserAuthMethod) bool {
return t.AuthMethod == models.AuthMethodGAuth
}),
@ -35,6 +35,18 @@ func (a *Authenticator) PerformTotpLogin(
return string(t.Token)
},
)
secrets := []string{}
for _, key := range encryptedSecrets {
decrypted, err := Decrypt([]byte(config.GlobalConfig.Storage.EncryptionKey), []byte(key))
if err != nil {
return 0, "", other.Error(
"auth",
"failed to decrypt secret",
&CombinedError{ErrDecryptionFailure, err},
)
}
secrets = append(secrets, string(decrypted))
}
found := false
for _, secret := range secrets {
if totp.Validate(totpToken, secret) {
@ -91,10 +103,17 @@ func (a *Authenticator) StartTotpRegistration(
return nil, err
}
secret := key.Secret()
encryptedSecret, err := Encrypt(
[]byte(config.GlobalConfig.Storage.EncryptionKey),
[]byte(secret),
)
if err != nil {
return nil, other.Error("auth", "failed to encrypt secret", err)
}
authToken := models.UserAuthMethod{
UserId: acc.ID,
User: *acc,
Token: []byte(secret),
Token: encryptedSecret,
AuthMethod: models.AuthMethodGAuth,
Name: tokenName + totpUnverifiedSuffix,
}