mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:07:30 +00:00
feat: new user auth api (#1168)
* fix: correct selectors for extended writemodel * fix: no previous checks in eventstore * start check previous * feat: auth user commands * feat: auth user commands * feat: auth user commands * feat: otp * feat: corrections from pr merge * feat: webauthn * feat: comment old webauthn * feat: refactor user, human, machine * feat: webauth command side * feat: command and query side in login * feat: fix user writemodel append events * fix: remove creation dates on command side * fix: remove previous sequence * previous sequence * fix: external idps * Update internal/api/grpc/management/user.go Co-authored-by: Livio Amstutz <livio.a@gmail.com> * Update internal/v2/command/user_human_email.go Co-authored-by: Livio Amstutz <livio.a@gmail.com> * fix: pr changes * fix: phone verification Co-authored-by: adlerhurst <silvan.reusser@gmail.com> Co-authored-by: Livio Amstutz <livio.a@gmail.com>
This commit is contained in:
@@ -11,6 +11,8 @@ import (
|
||||
type Human struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
Username string
|
||||
State UserState
|
||||
*Password
|
||||
*Profile
|
||||
*Email
|
||||
@@ -24,6 +26,14 @@ type Human struct {
|
||||
PasswordlessLogins []*WebAuthNLogin
|
||||
}
|
||||
|
||||
func (h Human) GetUsername() string {
|
||||
return h.Username
|
||||
}
|
||||
|
||||
func (h Human) GetState() UserState {
|
||||
return h.State
|
||||
}
|
||||
|
||||
type InitUserCode struct {
|
||||
es_models.ObjectRoot
|
||||
|
||||
@@ -91,3 +101,10 @@ func NewInitUserCode(generator crypto.Generator) (*InitUserCode, error) {
|
||||
Expiry: generator.Expiry(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GenerateLoginName(username, domain string, appendDomain bool) string {
|
||||
if !appendDomain {
|
||||
return username
|
||||
}
|
||||
return username + "@" + domain
|
||||
}
|
||||
|
@@ -2,7 +2,10 @@ package domain
|
||||
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/crypto"
|
||||
caos_errs "github.com/caos/zitadel/internal/errors"
|
||||
es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
"github.com/pquerna/otp"
|
||||
"github.com/pquerna/otp/totp"
|
||||
)
|
||||
|
||||
type OTP struct {
|
||||
@@ -14,16 +17,27 @@ type OTP struct {
|
||||
State MFAState
|
||||
}
|
||||
|
||||
type OTPState int32
|
||||
|
||||
const (
|
||||
OTPStateUnspecified OTPState = iota
|
||||
OTPStateActive
|
||||
OTPStateRemoved
|
||||
|
||||
otpStateCount
|
||||
)
|
||||
|
||||
func (s OTPState) Valid() bool {
|
||||
return s >= 0 && s < otpStateCount
|
||||
func NewOTPKey(issuer, accountName string, cryptoAlg crypto.EncryptionAlgorithm) (*otp.Key, *crypto.CryptoValue, error) {
|
||||
key, err := totp.Generate(totp.GenerateOpts{Issuer: issuer, AccountName: accountName})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
encryptedSecret, err := crypto.Encrypt([]byte(key.Secret()), cryptoAlg)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return key, encryptedSecret, nil
|
||||
}
|
||||
|
||||
func VerifyMFAOTP(code string, secret *crypto.CryptoValue, cryptoAlg crypto.EncryptionAlgorithm) error {
|
||||
decrypt, err := crypto.DecryptString(secret, cryptoAlg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valid := totp.Validate(code, decrypt)
|
||||
if !valid {
|
||||
return caos_errs.ThrowInvalidArgument(nil, "EVENT-8isk2", "Errors.User.MFA.OTP.InvalidCode")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -39,16 +39,19 @@ const (
|
||||
UserVerificationRequirementDiscouraged
|
||||
)
|
||||
|
||||
type WebAuthNState int32
|
||||
type AuthenticatorAttachment int32
|
||||
|
||||
const (
|
||||
WebAuthNStateUnspecified WebAuthNState = iota
|
||||
WebAuthNStateActive
|
||||
WebAuthNStateRemoved
|
||||
|
||||
webAuthNStateCount
|
||||
AuthenticatorAttachmentUnspecified AuthenticatorAttachment = iota
|
||||
AuthenticatorAttachmentPlattform
|
||||
AuthenticatorAttachmentCrossPlattform
|
||||
)
|
||||
|
||||
func (s WebAuthNState) Valid() bool {
|
||||
return s >= 0 && s < webAuthNStateCount
|
||||
func GetTokenToVerify(tokens []*WebAuthNToken) (int, *WebAuthNToken) {
|
||||
for i, u2f := range tokens {
|
||||
if u2f.State == MFAStateNotReady {
|
||||
return i, u2f
|
||||
}
|
||||
}
|
||||
return -1, nil
|
||||
}
|
||||
|
@@ -5,10 +5,20 @@ import "github.com/caos/zitadel/internal/eventstore/models"
|
||||
type Machine struct {
|
||||
models.ObjectRoot
|
||||
|
||||
Username string
|
||||
State UserState
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
func (m Machine) GetUsername() string {
|
||||
return m.Username
|
||||
}
|
||||
|
||||
func (m Machine) GetState() UserState {
|
||||
return m.State
|
||||
}
|
||||
|
||||
func (sa *Machine) IsValid() bool {
|
||||
return sa.Name != ""
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ const (
|
||||
MFAStateUnspecified MFAState = iota
|
||||
MFAStateNotReady
|
||||
MFAStateReady
|
||||
MFAStateRemoved
|
||||
|
||||
stateCount
|
||||
)
|
||||
|
@@ -12,6 +12,7 @@ type Org struct {
|
||||
State OrgState
|
||||
Name string
|
||||
|
||||
PrimaryDomain string
|
||||
Domains []*OrgDomain
|
||||
Members []*Member
|
||||
OrgIamPolicy *OrgIAMPolicy
|
||||
@@ -38,6 +39,7 @@ func (o *Org) nameForDomain(iamDomain string) string {
|
||||
type OrgState int32
|
||||
|
||||
const (
|
||||
OrgStateActive OrgState = iota
|
||||
OrgStateUnspecified OrgState = iota
|
||||
OrgStateActive
|
||||
OrgStateInactive
|
||||
)
|
||||
|
@@ -1,14 +1,8 @@
|
||||
package domain
|
||||
|
||||
import es_models "github.com/caos/zitadel/internal/eventstore/models"
|
||||
|
||||
type User struct {
|
||||
es_models.ObjectRoot
|
||||
State UserState
|
||||
UserName string
|
||||
|
||||
*Human
|
||||
*Machine
|
||||
type User interface {
|
||||
GetUsername() string
|
||||
GetState() UserState
|
||||
}
|
||||
|
||||
type UserState int32
|
||||
@@ -28,13 +22,3 @@ const (
|
||||
func (f UserState) Valid() bool {
|
||||
return f >= 0 && f < userStateCount
|
||||
}
|
||||
|
||||
func (u *User) IsValid() bool {
|
||||
if u.Human == nil && u.Machine == nil || u.UserName == "" {
|
||||
return false
|
||||
}
|
||||
if u.Human != nil {
|
||||
return u.Human.IsValid()
|
||||
}
|
||||
return u.Machine.IsValid()
|
||||
}
|
||||
|
Reference in New Issue
Block a user