mirror of
https://github.com/zitadel/zitadel
synced 2024-11-22 00:39:36 +00:00
fix: improvements for WebAuthN (#1105)
* add missing translations * add missing passwordless funcs in api * remove u2f with verification from setup in login
This commit is contained in:
parent
7463bf4fe0
commit
71df1bcd0e
@ -2,6 +2,7 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
|
||||
"github.com/caos/zitadel/pkg/grpc/auth"
|
||||
@ -175,6 +176,14 @@ func (s *Server) RemoveMyMfaU2F(ctx context.Context, id *auth.WebAuthNTokenID) (
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
|
||||
func (s *Server) GetMyPasswordless(ctx context.Context, _ *empty.Empty) (_ *auth.WebAuthNTokens, err error) {
|
||||
tokens, err := s.repo.GetMyPasswordless(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webAuthNTokensFromModel(tokens), err
|
||||
}
|
||||
|
||||
func (s *Server) AddMyPasswordless(ctx context.Context, _ *empty.Empty) (_ *auth.WebAuthNResponse, err error) {
|
||||
u2f, err := s.repo.AddMyPasswordless(ctx)
|
||||
return verifyWebAuthNFromModel(u2f), err
|
||||
|
@ -436,3 +436,19 @@ func verifyWebAuthNFromModel(u2f *usr_model.WebAuthNToken) *auth.WebAuthNRespons
|
||||
State: mfaStateFromModel(u2f.State),
|
||||
}
|
||||
}
|
||||
|
||||
func webAuthNTokensFromModel(tokens []*usr_model.WebAuthNToken) *auth.WebAuthNTokens {
|
||||
result := make([]*auth.WebAuthNToken, len(tokens))
|
||||
for i, token := range tokens {
|
||||
result[i] = webAuthNTokenFromModel(token)
|
||||
}
|
||||
return &auth.WebAuthNTokens{Tokens: result}
|
||||
}
|
||||
|
||||
func webAuthNTokenFromModel(token *usr_model.WebAuthNToken) *auth.WebAuthNToken {
|
||||
return &auth.WebAuthNToken{
|
||||
Id: token.WebAuthNTokenID,
|
||||
Name: token.WebAuthNTokenName,
|
||||
State: mfaStateFromModel(token.State),
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,11 @@ package management
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/pkg/grpc/management"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
)
|
||||
|
||||
func (s *Server) GetUserByID(ctx context.Context, id *management.UserID) (*management.UserView, error) {
|
||||
@ -231,6 +233,19 @@ func (s *Server) RemoveMfaU2F(ctx context.Context, webAuthNTokenID *management.W
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
|
||||
func (s *Server) GetPasswordless(ctx context.Context, userID *management.UserID) (_ *management.WebAuthNTokens, err error) {
|
||||
tokens, err := s.user.GetPasswordless(ctx, userID.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webAuthNTokensFromModel(tokens), err
|
||||
}
|
||||
|
||||
func (s *Server) RemovePasswordless(ctx context.Context, id *management.WebAuthNTokenID) (*empty.Empty, error) {
|
||||
err := s.user.RemovePasswordless(ctx, id.UserId, id.Id)
|
||||
return &empty.Empty{}, err
|
||||
}
|
||||
|
||||
func (s *Server) SearchUserMemberships(ctx context.Context, in *management.UserMembershipSearchRequest) (*management.UserMembershipSearchResponse, error) {
|
||||
request := userMembershipSearchRequestsToModel(in)
|
||||
request.AppendUserIDQuery(in.UserId)
|
||||
|
@ -629,3 +629,19 @@ func userChangesToMgtAPI(changes *usr_model.UserChanges) (_ []*management.Change
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func webAuthNTokensFromModel(tokens []*usr_model.WebAuthNToken) *management.WebAuthNTokens {
|
||||
result := make([]*management.WebAuthNToken, len(tokens))
|
||||
for i, token := range tokens {
|
||||
result[i] = webAuthNTokenFromModel(token)
|
||||
}
|
||||
return &management.WebAuthNTokens{Tokens: result}
|
||||
}
|
||||
|
||||
func webAuthNTokenFromModel(token *usr_model.WebAuthNToken) *management.WebAuthNToken {
|
||||
return &management.WebAuthNToken{
|
||||
Id: token.WebAuthNTokenID,
|
||||
Name: token.WebAuthNTokenName,
|
||||
State: mfaStateFromModel(token.State),
|
||||
}
|
||||
}
|
||||
|
@ -326,10 +326,18 @@ func (repo *UserRepo) RemoveMyMFAU2F(ctx context.Context, webAuthNTokenID string
|
||||
return repo.UserEvents.RemoveU2FToken(ctx, authz.GetCtxData(ctx).UserID, webAuthNTokenID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNToken, error) {
|
||||
return repo.UserEvents.GetPasswordless(ctx, userID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) AddPasswordless(ctx context.Context, userID string) (*model.WebAuthNToken, error) {
|
||||
return repo.UserEvents.AddPasswordless(ctx, userID, true)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) GetMyPasswordless(ctx context.Context) ([]*model.WebAuthNToken, error) {
|
||||
return repo.UserEvents.GetPasswordless(ctx, authz.GetCtxData(ctx).UserID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) AddMyPasswordless(ctx context.Context) (*model.WebAuthNToken, error) {
|
||||
return repo.UserEvents.AddPasswordless(ctx, authz.GetCtxData(ctx).UserID, false)
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ type UserRepository interface {
|
||||
VerifyMFAU2FSetup(ctx context.Context, userID, tokenName, userAgentID string, credentialData []byte) error
|
||||
RemoveMFAU2F(ctx context.Context, userID, webAuthNTokenID string) error
|
||||
|
||||
GetPasswordless(ctx context.Context, id string) ([]*model.WebAuthNToken, error)
|
||||
AddPasswordless(ctx context.Context, id string) (*model.WebAuthNToken, error)
|
||||
VerifyPasswordlessSetup(ctx context.Context, userID, tokenName, userAgentID string, credentialData []byte) error
|
||||
RemovePasswordless(ctx context.Context, userID, webAuthNTokenID string) error
|
||||
@ -80,6 +81,7 @@ type myUserRepo interface {
|
||||
VerifyMyMFAU2FSetup(ctx context.Context, tokenName string, data []byte) error
|
||||
RemoveMyMFAU2F(ctx context.Context, webAuthNTokenID string) error
|
||||
|
||||
GetMyPasswordless(ctx context.Context) ([]*model.WebAuthNToken, error)
|
||||
AddMyPasswordless(ctx context.Context) (*model.WebAuthNToken, error)
|
||||
VerifyMyPasswordlessSetup(ctx context.Context, tokenName string, data []byte) error
|
||||
RemoveMyPasswordless(ctx context.Context, webAuthNTokenID string) error
|
||||
|
@ -235,6 +235,14 @@ func (repo *UserRepo) RemoveU2F(ctx context.Context, userID, webAuthNTokenID str
|
||||
return repo.UserEvents.RemoveU2FToken(ctx, userID, webAuthNTokenID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) GetPasswordless(ctx context.Context, userID string) ([]*usr_model.WebAuthNToken, error) {
|
||||
return repo.UserEvents.GetPasswordless(ctx, userID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) RemovePasswordless(ctx context.Context, userID, webAuthNTokenID string) error {
|
||||
return repo.UserEvents.RemovePasswordlessToken(ctx, userID, webAuthNTokenID)
|
||||
}
|
||||
|
||||
func (repo *UserRepo) SetOneTimePassword(ctx context.Context, password *usr_model.Password) (*usr_model.Password, error) {
|
||||
policy, err := repo.View.PasswordComplexityPolicyByAggregateID(authz.GetCtxData(ctx).OrgID)
|
||||
if err != nil && caos_errs.IsNotFound(err) {
|
||||
|
@ -34,6 +34,9 @@ type UserRepository interface {
|
||||
RemoveOTP(ctx context.Context, userID string) error
|
||||
RemoveU2F(ctx context.Context, userID, webAuthNTokenID string) error
|
||||
|
||||
GetPasswordless(ctx context.Context, userID string) ([]*model.WebAuthNToken, error)
|
||||
RemovePasswordless(ctx context.Context, userID, webAuthNTokenID string) error
|
||||
|
||||
SearchExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error)
|
||||
RemoveExternalIDP(ctx context.Context, externalIDP *model.ExternalIDP) error
|
||||
|
||||
|
@ -446,9 +446,16 @@ EventTypes:
|
||||
login:
|
||||
added: Login Richtlinie hinzugefügt
|
||||
changed: Login Richtlinie geändert
|
||||
removed: Login Richtline gelöscht
|
||||
idpprovider:
|
||||
added: Idp Provider zu Login Richtlinie hinzugefügt
|
||||
removed: Idp Provider aus Login Richtlinie gelöscht
|
||||
secondfactor:
|
||||
added: Zweitfaktor zu Login Richtlinie hinzugefügt
|
||||
removed: Zweitfaktor aus Login Richtlinie gelöscht
|
||||
multifactor:
|
||||
added: Multifaktor zu Login Richtlinie hinzugefügt
|
||||
removed: Multifaktor aus Login Richtlinie gelöscht
|
||||
password:
|
||||
complexity:
|
||||
added: Passwort Komplexitäts Richtlinie hinzugefügt
|
||||
|
@ -446,9 +446,16 @@ EventTypes:
|
||||
login:
|
||||
added: Login Policy added
|
||||
changed: Login Policy changed
|
||||
removed: Login Policy removed
|
||||
idpprovider:
|
||||
added: Idp Provider added to Login Policy
|
||||
removed: Idp Provider removed from Login Policy
|
||||
secondfactor:
|
||||
added: Second factor added to Login Policy
|
||||
removed: Second factor removed from Login Policy
|
||||
multifactor:
|
||||
added: Multi factor added to Login Policy
|
||||
removed: Multi factor removed from Login Policy
|
||||
password:
|
||||
complexity:
|
||||
added: Password complexity policy added
|
||||
|
@ -136,16 +136,6 @@ func (u *UserView) MFATypesSetupPossible(level req_model.MFALevel, policy *iam_m
|
||||
}
|
||||
}
|
||||
//PLANNED: add sms
|
||||
fallthrough
|
||||
case req_model.MFALevelMultiFactor:
|
||||
if policy.HasMultiFactors() {
|
||||
for _, mfaType := range policy.MultiFactors {
|
||||
switch mfaType {
|
||||
case iam_model.MultiFactorTypeU2FWithPIN:
|
||||
types = append(types, req_model.MFATypeU2FUserVerification)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
@ -1410,6 +1410,14 @@ func (es *UserEventstore) VerifyMFAU2F(ctx context.Context, userID string, crede
|
||||
return finishErr
|
||||
}
|
||||
|
||||
func (es *UserEventstore) GetPasswordless(ctx context.Context, userID string) ([]*usr_model.WebAuthNToken, error) {
|
||||
user, err := es.HumanByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return user.PasswordlessTokens, nil
|
||||
}
|
||||
|
||||
func (es *UserEventstore) AddPasswordless(ctx context.Context, userID string, isLoginUI bool) (*usr_model.WebAuthNToken, error) {
|
||||
user, err := es.HumanByID(ctx, userID)
|
||||
if err != nil {
|
||||
|
@ -337,6 +337,15 @@ service AuthService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetMyPasswordless(google.protobuf.Empty) returns (WebAuthNTokens) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/me/passwordless"
|
||||
};
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "authenticated"
|
||||
};
|
||||
}
|
||||
|
||||
rpc AddMyPasswordless(google.protobuf.Empty) returns (WebAuthNResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/users/me/passwordless"
|
||||
@ -666,6 +675,16 @@ message MfaOtpResponse {
|
||||
MFAState state = 4;
|
||||
}
|
||||
|
||||
message WebAuthNTokens {
|
||||
repeated WebAuthNToken tokens = 1;
|
||||
}
|
||||
|
||||
message WebAuthNToken {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
MFAState state = 3;
|
||||
}
|
||||
|
||||
message WebAuthNResponse {
|
||||
string id = 1;
|
||||
bytes public_key = 2;
|
||||
|
@ -409,6 +409,26 @@ service ManagementService {
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetPasswordless(UserID) returns (WebAuthNTokens) {
|
||||
option (google.api.http) = {
|
||||
get: "/users/{id}/passwordless"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "user.read"
|
||||
};
|
||||
}
|
||||
|
||||
rpc RemovePasswordless(WebAuthNTokenID) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
delete: "/users/{user_id}/passwordless"
|
||||
};
|
||||
|
||||
option (caos.zitadel.utils.v1.auth_option) = {
|
||||
permission: "user.write"
|
||||
};
|
||||
}
|
||||
|
||||
// Sends an Notification (Email/SMS) with a password reset Link
|
||||
rpc SendSetPasswordNotification(SetPasswordNotificationRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {
|
||||
@ -1656,6 +1676,16 @@ message UserID {
|
||||
string id = 1 [(validate.rules).string.min_len = 1];
|
||||
}
|
||||
|
||||
message WebAuthNTokens {
|
||||
repeated WebAuthNToken tokens = 1;
|
||||
}
|
||||
|
||||
message WebAuthNToken {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
MFAState state = 3;
|
||||
}
|
||||
|
||||
message WebAuthNTokenID {
|
||||
string user_id = 1 [(validate.rules).string.min_len = 1];
|
||||
string id = 2 [(validate.rules).string.min_len = 1];
|
||||
@ -3097,6 +3127,7 @@ enum PasswordlessType {
|
||||
PASSWORDLESSTYPE_ALLOWED = 1;
|
||||
}
|
||||
|
||||
|
||||
message IdpProviderID {
|
||||
string idp_config_id = 1 [(validate.rules).string = {min_len: 1}];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user