Move password encryption to argon2id
This commit is contained in:
parent
c1611114d0
commit
c269db5b02
5 changed files with 201 additions and 3 deletions
106
auth-new/totp.go
Normal file
106
auth-new/totp.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.mstar.dev/mstar/goutils/other"
|
||||
"git.mstar.dev/mstar/goutils/sliceutils"
|
||||
"github.com/pquerna/otp"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
"git.mstar.dev/mstar/linstrom/config"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||
)
|
||||
|
||||
const totpUnverifiedSuffix = "-NOT_VERIFIED"
|
||||
|
||||
func (a *Authenticator) PerformTotpLogin(
|
||||
username string,
|
||||
totpToken string,
|
||||
) (LoginNextState, string, error) {
|
||||
if ok, err := a.canUsernameLogin(username); !ok {
|
||||
return 0, "", other.Error("auth", "user may not login", err)
|
||||
}
|
||||
acc, err := dbgen.User.Where(dbgen.User.Username.Eq(username)).First()
|
||||
if err != nil {
|
||||
return LoginNextFailure, "", other.Error("auth", "failed to find account", err)
|
||||
}
|
||||
secrets := sliceutils.Map(
|
||||
sliceutils.Filter(acc.AuthMethods, func(t models.UserAuthMethod) bool {
|
||||
return t.AuthMethod == models.AuthMethodGAuth
|
||||
}),
|
||||
func(t models.UserAuthMethod) string {
|
||||
return string(t.Token)
|
||||
},
|
||||
)
|
||||
found := false
|
||||
for _, secret := range secrets {
|
||||
if totp.Validate(totpToken, secret) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return LoginNextFailure, "", other.Error(
|
||||
"auth",
|
||||
"no fitting credential found",
|
||||
ErrInvalidCombination,
|
||||
)
|
||||
}
|
||||
token := models.AccessToken{
|
||||
User: *acc,
|
||||
UserId: acc.ID,
|
||||
ExpiresAt: time.Now().Add(time.Hour * 24 * 365),
|
||||
}
|
||||
err = dbgen.AccessToken.
|
||||
// technically, the chance of a conflict is so incredibly low that it should never ever occur
|
||||
// since both the username and a randomly generated uuid would need to be created the same. Twice
|
||||
// But, just in case, do this
|
||||
Clauses(clause.OnConflict{DoNothing: true}).
|
||||
Omit(dbgen.AccessToken.Token).
|
||||
Create(&token)
|
||||
if err != nil {
|
||||
return LoginNextFailure, "", other.Error(
|
||||
"auth",
|
||||
"failed to create new access token",
|
||||
err,
|
||||
)
|
||||
}
|
||||
return LoginNextSucess, token.Token, nil
|
||||
}
|
||||
|
||||
func (a *Authenticator) StartTotpRegistration(
|
||||
username string,
|
||||
tokenName string,
|
||||
) (*otp.Key, error) {
|
||||
if ok, err := a.canUsernameLogin(username); !ok {
|
||||
return nil, other.Error("auth", "user may not login", err)
|
||||
}
|
||||
acc, err := dbgen.User.Where(dbgen.User.Username.Eq(username)).First()
|
||||
if err != nil {
|
||||
return nil, other.Error("auth", "failed to find account", err)
|
||||
}
|
||||
key, err := totp.Generate(totp.GenerateOpts{
|
||||
Issuer: config.GlobalConfig.General.GetFullDomain(),
|
||||
AccountName: username,
|
||||
SecretSize: 160,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
secret := key.Secret()
|
||||
authToken := models.UserAuthMethod{
|
||||
UserId: acc.ID,
|
||||
User: *acc,
|
||||
Token: []byte(secret),
|
||||
AuthMethod: models.AuthMethodGAuth,
|
||||
Name: tokenName + totpUnverifiedSuffix,
|
||||
}
|
||||
err = dbgen.UserAuthMethod.Create(&authToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue