mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-06 13:57:41 +00:00
feat: choose preferred WebAuthN platform for passwordless registration (#2469)
* feat: request preferred platform type for passwordless registration when using link * add text in console
This commit is contained in:
parent
415d0c7ab2
commit
52c1494fe9
@ -333,6 +333,7 @@ export function mapRequestValues(map: Partial<Map>, req: Req): Req {
|
||||
|
||||
const r31 = new PasswordlessRegistrationDoneScreenText();
|
||||
r31.setDescription(map.passwordlessRegistrationDoneText?.description ?? '');
|
||||
r31.setDescriptionClose(map.passwordlessRegistrationDoneText?.descriptionClose ?? '');
|
||||
r31.setNextButtonText(map.passwordlessRegistrationDoneText?.nextButtonText ?? '');
|
||||
r31.setTitle(map.passwordlessRegistrationDoneText?.title ?? '');
|
||||
r31.setNextButtonText(map.passwordlessRegistrationDoneText?.cancelButtonText ?? '');
|
||||
|
@ -438,6 +438,7 @@ title: zitadel/text.proto
|
||||
| description | string | - | string.max_len: 500<br /> |
|
||||
| next_button_text | string | - | string.max_len: 100<br /> |
|
||||
| cancel_button_text | string | - | string.max_len: 100<br /> |
|
||||
| description_close | string | - | string.max_len: 100<br /> |
|
||||
|
||||
|
||||
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/api/grpc/object"
|
||||
user_grpc "github.com/caos/zitadel/internal/api/grpc/user"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
auth_pb "github.com/caos/zitadel/pkg/grpc/auth"
|
||||
user_pb "github.com/caos/zitadel/pkg/grpc/user"
|
||||
)
|
||||
@ -24,7 +25,7 @@ func (s *Server) ListMyPasswordless(ctx context.Context, _ *auth_pb.ListMyPasswo
|
||||
|
||||
func (s *Server) AddMyPasswordless(ctx context.Context, _ *auth_pb.AddMyPasswordlessRequest) (*auth_pb.AddMyPasswordlessResponse, error) {
|
||||
ctxData := authz.GetCtxData(ctx)
|
||||
token, err := s.command.HumanAddPasswordlessSetup(ctx, ctxData.UserID, ctxData.ResourceOwner, false)
|
||||
token, err := s.command.HumanAddPasswordlessSetup(ctx, ctxData.UserID, ctxData.ResourceOwner, false, domain.AuthenticatorAttachmentUnspecified)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -302,6 +302,7 @@ func PasswordlessRegistrationDoneScreenTextToPb(text domain.PasswordlessRegistra
|
||||
return &text_pb.PasswordlessRegistrationDoneScreenText{
|
||||
Title: text.Title,
|
||||
Description: text.Description,
|
||||
DescriptionClose: text.DescriptionClose,
|
||||
NextButtonText: text.NextButtonText,
|
||||
CancelButtonText: text.CancelButtonText,
|
||||
}
|
||||
@ -754,9 +755,10 @@ func PasswordlessRegistrationDoneScreenTextPbToDomain(text *text_pb.Passwordless
|
||||
return domain.PasswordlessRegistrationDoneScreenText{}
|
||||
}
|
||||
return domain.PasswordlessRegistrationDoneScreenText{
|
||||
Title: text.Title,
|
||||
Description: text.Description,
|
||||
NextButtonText: text.NextButtonText,
|
||||
Title: text.Title,
|
||||
Description: text.Description,
|
||||
DescriptionClose: text.DescriptionClose,
|
||||
NextButtonText: text.NextButtonText,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,9 @@ type AuthRequestRepository interface {
|
||||
VerifyMFAOTP(ctx context.Context, authRequestID, userID, resourceOwner, code, userAgentID string, info *domain.BrowserInfo) error
|
||||
BeginMFAU2FLogin(ctx context.Context, userID, resourceOwner, authRequestID, userAgentID string) (*domain.WebAuthNLogin, error)
|
||||
VerifyMFAU2F(ctx context.Context, userID, resourceOwner, authRequestID, userAgentID string, credentialData []byte, info *domain.BrowserInfo) error
|
||||
BeginPasswordlessSetup(ctx context.Context, userID, resourceOwner string) (login *domain.WebAuthNToken, err error)
|
||||
BeginPasswordlessSetup(ctx context.Context, userID, resourceOwner string, preferredPlatformType domain.AuthenticatorAttachment) (login *domain.WebAuthNToken, err error)
|
||||
VerifyPasswordlessSetup(ctx context.Context, userID, resourceOwner, userAgentID, tokenName string, credentialData []byte) (err error)
|
||||
BeginPasswordlessInitCodeSetup(ctx context.Context, userID, resourceOwner, codeID, verificationCode string) (login *domain.WebAuthNToken, err error)
|
||||
BeginPasswordlessInitCodeSetup(ctx context.Context, userID, resourceOwner, codeID, verificationCode string, preferredPlatformType domain.AuthenticatorAttachment) (login *domain.WebAuthNToken, err error)
|
||||
VerifyPasswordlessInitCodeSetup(ctx context.Context, userID, resourceOwner, userAgentID, tokenName, codeID, verificationCode string, credentialData []byte) (err error)
|
||||
BeginPasswordlessLogin(ctx context.Context, userID, resourceOwner, authRequestID, userAgentID string) (*domain.WebAuthNLogin, error)
|
||||
VerifyPasswordless(ctx context.Context, userID, resourceOwner, authRequestID, userAgentID string, credentialData []byte, info *domain.BrowserInfo) error
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/auth/repository/eventsourcing/view"
|
||||
"github.com/caos/zitadel/internal/auth_request/model"
|
||||
@ -327,10 +328,10 @@ func (repo *AuthRequestRepo) VerifyMFAU2F(ctx context.Context, userID, resourceO
|
||||
return repo.Command.HumanFinishU2FLogin(ctx, userID, resourceOwner, credentialData, request, true)
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) BeginPasswordlessSetup(ctx context.Context, userID, resourceOwner string) (login *domain.WebAuthNToken, err error) {
|
||||
func (repo *AuthRequestRepo) BeginPasswordlessSetup(ctx context.Context, userID, resourceOwner string, authenticatorPlatform domain.AuthenticatorAttachment) (login *domain.WebAuthNToken, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
return repo.Command.HumanAddPasswordlessSetup(ctx, userID, resourceOwner, true)
|
||||
return repo.Command.HumanAddPasswordlessSetup(ctx, userID, resourceOwner, true, authenticatorPlatform)
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) VerifyPasswordlessSetup(ctx context.Context, userID, resourceOwner, userAgentID, tokenName string, credentialData []byte) (err error) {
|
||||
@ -340,10 +341,10 @@ func (repo *AuthRequestRepo) VerifyPasswordlessSetup(ctx context.Context, userID
|
||||
return err
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) BeginPasswordlessInitCodeSetup(ctx context.Context, userID, resourceOwner, codeID, verificationCode string) (login *domain.WebAuthNToken, err error) {
|
||||
func (repo *AuthRequestRepo) BeginPasswordlessInitCodeSetup(ctx context.Context, userID, resourceOwner, codeID, verificationCode string, preferredPlatformType domain.AuthenticatorAttachment) (login *domain.WebAuthNToken, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
return repo.Command.HumanAddPasswordlessSetupInitCode(ctx, userID, resourceOwner, codeID, verificationCode)
|
||||
return repo.Command.HumanAddPasswordlessSetupInitCode(ctx, userID, resourceOwner, codeID, verificationCode, preferredPlatformType)
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) VerifyPasswordlessInitCodeSetup(ctx context.Context, userID, resourceOwner, userAgentID, tokenName, codeID, verificationCode string, credentialData []byte) (err error) {
|
||||
|
@ -661,6 +661,10 @@ func (c *Commands) createPasswordlessRegistrationDoneEvents(ctx context.Context,
|
||||
if event != nil {
|
||||
events = append(events, event)
|
||||
}
|
||||
event = c.createCustomLoginTextEvent(ctx, agg, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, existingText.PasswordlessRegistrationDoneDescriptionClose, text.PasswordlessRegistrationDone.DescriptionClose, text.Language, defaultText)
|
||||
if event != nil {
|
||||
events = append(events, event)
|
||||
}
|
||||
event = c.createCustomLoginTextEvent(ctx, agg, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, existingText.PasswordlessRegistrationDoneNextButtonText, text.PasswordlessRegistrationDone.NextButtonText, text.Language, defaultText)
|
||||
if event != nil {
|
||||
events = append(events, event)
|
||||
|
@ -182,6 +182,7 @@ type CustomLoginTextReadModel struct {
|
||||
|
||||
PasswordlessRegistrationDoneTitle string
|
||||
PasswordlessRegistrationDoneDescription string
|
||||
PasswordlessRegistrationDoneDescriptionClose string
|
||||
PasswordlessRegistrationDoneNextButtonText string
|
||||
PasswordlessRegistrationDoneCancelButtonText string
|
||||
|
||||
@ -1703,6 +1704,10 @@ func (wm *CustomLoginTextReadModel) handlePasswordlessRegistrationDoneScreenSetE
|
||||
wm.PasswordlessRegistrationDoneDescription = e.Text
|
||||
return
|
||||
}
|
||||
if e.Key == domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose {
|
||||
wm.PasswordlessRegistrationDoneDescriptionClose = e.Text
|
||||
return
|
||||
}
|
||||
if e.Key == domain.LoginKeyPasswordlessRegistrationDoneNextButtonText {
|
||||
wm.PasswordlessRegistrationDoneNextButtonText = e.Text
|
||||
return
|
||||
@ -1722,6 +1727,10 @@ func (wm *CustomLoginTextReadModel) handlePasswordlessRegistrationDoneScreenRemo
|
||||
wm.PasswordlessRegistrationDoneDescription = ""
|
||||
return
|
||||
}
|
||||
if e.Key == domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose {
|
||||
wm.PasswordlessRegistrationDoneDescriptionClose = ""
|
||||
return
|
||||
}
|
||||
if e.Key == domain.LoginKeyPasswordlessRegistrationDoneNextButtonText {
|
||||
wm.PasswordlessRegistrationDoneNextButtonText = ""
|
||||
return
|
||||
|
@ -684,6 +684,11 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, "Description", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextSetEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, "DescriptionClose", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextSetEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, "NextButtonText", language.English,
|
||||
@ -1320,6 +1325,7 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
PasswordlessRegistrationDone: domain.PasswordlessRegistrationDoneScreenText{
|
||||
Title: "Title",
|
||||
Description: "Description",
|
||||
DescriptionClose: "DescriptionClose",
|
||||
NextButtonText: "NextButtonText",
|
||||
CancelButtonText: "CancelButtonText",
|
||||
},
|
||||
@ -2081,6 +2087,11 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, "Description", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextSetEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, "DescriptionClose", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextSetEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, "NextButtonText", language.English,
|
||||
@ -3174,6 +3185,11 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, language.English,
|
||||
@ -3641,41 +3657,41 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
config: &domain.CustomLoginText{
|
||||
Language: language.English,
|
||||
SelectAccount: domain.SelectAccountScreenText{},
|
||||
Login: domain.LoginScreenText{},
|
||||
Password: domain.PasswordScreenText{},
|
||||
UsernameChange: domain.UsernameChangeScreenText{},
|
||||
UsernameChangeDone: domain.UsernameChangeDoneScreenText{},
|
||||
InitPassword: domain.InitPasswordScreenText{},
|
||||
InitPasswordDone: domain.InitPasswordDoneScreenText{},
|
||||
EmailVerification: domain.EmailVerificationScreenText{},
|
||||
EmailVerificationDone: domain.EmailVerificationDoneScreenText{},
|
||||
InitUser: domain.InitializeUserScreenText{},
|
||||
InitUserDone: domain.InitializeUserDoneScreenText{},
|
||||
InitMFAPrompt: domain.InitMFAPromptScreenText{},
|
||||
InitMFAOTP: domain.InitMFAOTPScreenText{},
|
||||
InitMFAU2F: domain.InitMFAU2FScreenText{},
|
||||
InitMFADone: domain.InitMFADoneScreenText{},
|
||||
MFAProvider: domain.MFAProvidersText{},
|
||||
VerifyMFAOTP: domain.VerifyMFAOTPScreenText{},
|
||||
VerifyMFAU2F: domain.VerifyMFAU2FScreenText{},
|
||||
Passwordless: domain.PasswordlessScreenText{},
|
||||
PasswordlessPrompt: domain.PasswordlessPromptScreenText{},
|
||||
PasswordlessRegistration: domain.PasswordlessRegistrationScreenText{},
|
||||
PasswordlessRegistrationDone: domain.PasswordlessRegistrationDoneScreenText{},
|
||||
PasswordChange: domain.PasswordChangeScreenText{},
|
||||
PasswordChangeDone: domain.PasswordChangeDoneScreenText{},
|
||||
PasswordResetDone: domain.PasswordResetDoneScreenText{},
|
||||
RegisterOption: domain.RegistrationOptionScreenText{},
|
||||
RegistrationUser: domain.RegistrationUserScreenText{},
|
||||
Language: language.English,
|
||||
SelectAccount: domain.SelectAccountScreenText{},
|
||||
Login: domain.LoginScreenText{},
|
||||
Password: domain.PasswordScreenText{},
|
||||
UsernameChange: domain.UsernameChangeScreenText{},
|
||||
UsernameChangeDone: domain.UsernameChangeDoneScreenText{},
|
||||
InitPassword: domain.InitPasswordScreenText{},
|
||||
InitPasswordDone: domain.InitPasswordDoneScreenText{},
|
||||
EmailVerification: domain.EmailVerificationScreenText{},
|
||||
EmailVerificationDone: domain.EmailVerificationDoneScreenText{},
|
||||
InitUser: domain.InitializeUserScreenText{},
|
||||
InitUserDone: domain.InitializeUserDoneScreenText{},
|
||||
InitMFAPrompt: domain.InitMFAPromptScreenText{},
|
||||
InitMFAOTP: domain.InitMFAOTPScreenText{},
|
||||
InitMFAU2F: domain.InitMFAU2FScreenText{},
|
||||
InitMFADone: domain.InitMFADoneScreenText{},
|
||||
MFAProvider: domain.MFAProvidersText{},
|
||||
VerifyMFAOTP: domain.VerifyMFAOTPScreenText{},
|
||||
VerifyMFAU2F: domain.VerifyMFAU2FScreenText{},
|
||||
Passwordless: domain.PasswordlessScreenText{},
|
||||
PasswordlessPrompt: domain.PasswordlessPromptScreenText{},
|
||||
PasswordlessRegistration: domain.PasswordlessRegistrationScreenText{},
|
||||
PasswordlessRegistrationDone: domain.PasswordlessRegistrationDoneScreenText{},
|
||||
PasswordChange: domain.PasswordChangeScreenText{},
|
||||
PasswordChangeDone: domain.PasswordChangeDoneScreenText{},
|
||||
PasswordResetDone: domain.PasswordResetDoneScreenText{},
|
||||
RegisterOption: domain.RegistrationOptionScreenText{},
|
||||
RegistrationUser: domain.RegistrationUserScreenText{},
|
||||
ExternalRegistrationUserOverview: domain.ExternalRegistrationUserOverviewScreenText{},
|
||||
RegistrationOrg: domain.RegistrationOrgScreenText{},
|
||||
LinkingUsersDone: domain.LinkingUserDoneScreenText{},
|
||||
ExternalNotFoundOption: domain.ExternalUserNotFoundScreenText{},
|
||||
LoginSuccess: domain.SuccessLoginScreenText{},
|
||||
LogoutDone: domain.LogoutDoneScreenText{},
|
||||
Footer: domain.FooterText{},
|
||||
RegistrationOrg: domain.RegistrationOrgScreenText{},
|
||||
LinkingUsersDone: domain.LinkingUserDoneScreenText{},
|
||||
ExternalNotFoundOption: domain.ExternalUserNotFoundScreenText{},
|
||||
LoginSuccess: domain.SuccessLoginScreenText{},
|
||||
LogoutDone: domain.LogoutDoneScreenText{},
|
||||
Footer: domain.FooterText{},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -4320,6 +4336,11 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, "Description", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextSetEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, "DescriptionClose", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextSetEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, "NextButtonText", language.English,
|
||||
@ -5411,6 +5432,11 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextRemovedEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, language.English,
|
||||
@ -6504,6 +6530,11 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, "Description", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextSetEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, "DescriptionClose", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
iam.NewCustomTextSetEvent(context.Background(),
|
||||
&iam.NewAggregate().Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, "NextButtonText", language.English,
|
||||
@ -7141,6 +7172,7 @@ func TestCommandSide_SetCustomIAMLoginText(t *testing.T) {
|
||||
PasswordlessRegistrationDone: domain.PasswordlessRegistrationDoneScreenText{
|
||||
Title: "Title",
|
||||
Description: "Description",
|
||||
DescriptionClose: "DescriptionClose",
|
||||
NextButtonText: "NextButtonText",
|
||||
CancelButtonText: "CancelButtonText",
|
||||
},
|
||||
|
@ -701,6 +701,11 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, "Description", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, "DescriptionClose", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, "NextButtonText", language.English,
|
||||
@ -1339,6 +1344,7 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
PasswordlessRegistrationDone: domain.PasswordlessRegistrationDoneScreenText{
|
||||
Title: "Title",
|
||||
Description: "Description",
|
||||
DescriptionClose: "DescriptionClose",
|
||||
NextButtonText: "NextButtonText",
|
||||
CancelButtonText: "CancelButtonText",
|
||||
},
|
||||
@ -2100,6 +2106,11 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, "Description", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, "DescriptionClose", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, "NextButtonText", language.English,
|
||||
@ -3193,6 +3204,11 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextRemovedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextRemovedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, language.English,
|
||||
@ -3661,41 +3677,41 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
ctx: context.Background(),
|
||||
resourceOwner: "org1",
|
||||
config: &domain.CustomLoginText{
|
||||
Language: language.English,
|
||||
SelectAccount: domain.SelectAccountScreenText{},
|
||||
Login: domain.LoginScreenText{},
|
||||
Password: domain.PasswordScreenText{},
|
||||
UsernameChange: domain.UsernameChangeScreenText{},
|
||||
UsernameChangeDone: domain.UsernameChangeDoneScreenText{},
|
||||
InitPassword: domain.InitPasswordScreenText{},
|
||||
InitPasswordDone: domain.InitPasswordDoneScreenText{},
|
||||
EmailVerification: domain.EmailVerificationScreenText{},
|
||||
EmailVerificationDone: domain.EmailVerificationDoneScreenText{},
|
||||
InitUser: domain.InitializeUserScreenText{},
|
||||
InitUserDone: domain.InitializeUserDoneScreenText{},
|
||||
InitMFAPrompt: domain.InitMFAPromptScreenText{},
|
||||
InitMFAOTP: domain.InitMFAOTPScreenText{},
|
||||
InitMFAU2F: domain.InitMFAU2FScreenText{},
|
||||
InitMFADone: domain.InitMFADoneScreenText{},
|
||||
MFAProvider: domain.MFAProvidersText{},
|
||||
VerifyMFAOTP: domain.VerifyMFAOTPScreenText{},
|
||||
VerifyMFAU2F: domain.VerifyMFAU2FScreenText{},
|
||||
Passwordless: domain.PasswordlessScreenText{},
|
||||
PasswordlessPrompt: domain.PasswordlessPromptScreenText{},
|
||||
PasswordlessRegistration: domain.PasswordlessRegistrationScreenText{},
|
||||
PasswordlessRegistrationDone: domain.PasswordlessRegistrationDoneScreenText{},
|
||||
PasswordChange: domain.PasswordChangeScreenText{},
|
||||
PasswordChangeDone: domain.PasswordChangeDoneScreenText{},
|
||||
PasswordResetDone: domain.PasswordResetDoneScreenText{},
|
||||
RegisterOption: domain.RegistrationOptionScreenText{},
|
||||
Language: language.English,
|
||||
SelectAccount: domain.SelectAccountScreenText{},
|
||||
Login: domain.LoginScreenText{},
|
||||
Password: domain.PasswordScreenText{},
|
||||
UsernameChange: domain.UsernameChangeScreenText{},
|
||||
UsernameChangeDone: domain.UsernameChangeDoneScreenText{},
|
||||
InitPassword: domain.InitPasswordScreenText{},
|
||||
InitPasswordDone: domain.InitPasswordDoneScreenText{},
|
||||
EmailVerification: domain.EmailVerificationScreenText{},
|
||||
EmailVerificationDone: domain.EmailVerificationDoneScreenText{},
|
||||
InitUser: domain.InitializeUserScreenText{},
|
||||
InitUserDone: domain.InitializeUserDoneScreenText{},
|
||||
InitMFAPrompt: domain.InitMFAPromptScreenText{},
|
||||
InitMFAOTP: domain.InitMFAOTPScreenText{},
|
||||
InitMFAU2F: domain.InitMFAU2FScreenText{},
|
||||
InitMFADone: domain.InitMFADoneScreenText{},
|
||||
MFAProvider: domain.MFAProvidersText{},
|
||||
VerifyMFAOTP: domain.VerifyMFAOTPScreenText{},
|
||||
VerifyMFAU2F: domain.VerifyMFAU2FScreenText{},
|
||||
Passwordless: domain.PasswordlessScreenText{},
|
||||
PasswordlessPrompt: domain.PasswordlessPromptScreenText{},
|
||||
PasswordlessRegistration: domain.PasswordlessRegistrationScreenText{},
|
||||
PasswordlessRegistrationDone: domain.PasswordlessRegistrationDoneScreenText{},
|
||||
PasswordChange: domain.PasswordChangeScreenText{},
|
||||
PasswordChangeDone: domain.PasswordChangeDoneScreenText{},
|
||||
PasswordResetDone: domain.PasswordResetDoneScreenText{},
|
||||
RegisterOption: domain.RegistrationOptionScreenText{},
|
||||
ExternalRegistrationUserOverview: domain.ExternalRegistrationUserOverviewScreenText{},
|
||||
RegistrationUser: domain.RegistrationUserScreenText{},
|
||||
RegistrationOrg: domain.RegistrationOrgScreenText{},
|
||||
LinkingUsersDone: domain.LinkingUserDoneScreenText{},
|
||||
ExternalNotFoundOption: domain.ExternalUserNotFoundScreenText{},
|
||||
LoginSuccess: domain.SuccessLoginScreenText{},
|
||||
LogoutDone: domain.LogoutDoneScreenText{},
|
||||
Footer: domain.FooterText{},
|
||||
RegistrationUser: domain.RegistrationUserScreenText{},
|
||||
RegistrationOrg: domain.RegistrationOrgScreenText{},
|
||||
LinkingUsersDone: domain.LinkingUserDoneScreenText{},
|
||||
ExternalNotFoundOption: domain.ExternalUserNotFoundScreenText{},
|
||||
LoginSuccess: domain.SuccessLoginScreenText{},
|
||||
LogoutDone: domain.LogoutDoneScreenText{},
|
||||
Footer: domain.FooterText{},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
@ -4340,6 +4356,11 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, "Description", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, "DescriptionClose", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, "NextButtonText", language.English,
|
||||
@ -5430,6 +5451,11 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextRemovedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextRemovedEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, language.English,
|
||||
@ -6523,6 +6549,11 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescription, "Description", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose, "DescriptionClose", language.English,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewCustomTextSetEvent(context.Background(),
|
||||
&org.NewAggregate("org1", "org1").Aggregate, domain.LoginCustomText, domain.LoginKeyPasswordlessRegistrationDoneNextButtonText, "NextButtonText", language.English,
|
||||
@ -7161,6 +7192,7 @@ func TestCommandSide_SetCustomOrgLoginText(t *testing.T) {
|
||||
PasswordlessRegistrationDone: domain.PasswordlessRegistrationDoneScreenText{
|
||||
Title: "Title",
|
||||
Description: "Description",
|
||||
DescriptionClose: "DescriptionClose",
|
||||
NextButtonText: "NextButtonText",
|
||||
CancelButtonText: "CancelButtonText",
|
||||
},
|
||||
|
@ -82,7 +82,7 @@ func (c *Commands) HumanAddU2FSetup(ctx context.Context, userID, resourceowner s
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addWebAuthN, userAgg, webAuthN, err := c.addHumanWebAuthN(ctx, userID, resourceowner, isLoginUI, u2fTokens)
|
||||
addWebAuthN, userAgg, webAuthN, err := c.addHumanWebAuthN(ctx, userID, resourceowner, isLoginUI, u2fTokens, domain.AuthenticatorAttachmentUnspecified)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -103,12 +103,12 @@ func (c *Commands) HumanAddU2FSetup(ctx context.Context, userID, resourceowner s
|
||||
return createdWebAuthN, nil
|
||||
}
|
||||
|
||||
func (c *Commands) HumanAddPasswordlessSetup(ctx context.Context, userID, resourceowner string, isLoginUI bool) (*domain.WebAuthNToken, error) {
|
||||
func (c *Commands) HumanAddPasswordlessSetup(ctx context.Context, userID, resourceowner string, isLoginUI bool, authenticatorPlatform domain.AuthenticatorAttachment) (*domain.WebAuthNToken, error) {
|
||||
passwordlessTokens, err := c.getHumanPasswordlessTokens(ctx, userID, resourceowner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addWebAuthN, userAgg, webAuthN, err := c.addHumanWebAuthN(ctx, userID, resourceowner, isLoginUI, passwordlessTokens)
|
||||
addWebAuthN, userAgg, webAuthN, err := c.addHumanWebAuthN(ctx, userID, resourceowner, isLoginUI, passwordlessTokens, authenticatorPlatform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -129,15 +129,15 @@ func (c *Commands) HumanAddPasswordlessSetup(ctx context.Context, userID, resour
|
||||
return createdWebAuthN, nil
|
||||
}
|
||||
|
||||
func (c *Commands) HumanAddPasswordlessSetupInitCode(ctx context.Context, userID, resourceowner, codeID, verificationCode string) (*domain.WebAuthNToken, error) {
|
||||
func (c *Commands) HumanAddPasswordlessSetupInitCode(ctx context.Context, userID, resourceowner, codeID, verificationCode string, preferredPlatformType domain.AuthenticatorAttachment) (*domain.WebAuthNToken, error) {
|
||||
err := c.humanVerifyPasswordlessInitCode(ctx, userID, resourceowner, codeID, verificationCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.HumanAddPasswordlessSetup(ctx, userID, resourceowner, true)
|
||||
return c.HumanAddPasswordlessSetup(ctx, userID, resourceowner, true, preferredPlatformType)
|
||||
}
|
||||
|
||||
func (c *Commands) addHumanWebAuthN(ctx context.Context, userID, resourceowner string, isLoginUI bool, tokens []*domain.WebAuthNToken) (*HumanWebAuthNWriteModel, *eventstore.Aggregate, *domain.WebAuthNToken, error) {
|
||||
func (c *Commands) addHumanWebAuthN(ctx context.Context, userID, resourceowner string, isLoginUI bool, tokens []*domain.WebAuthNToken, authenticatorPlatform domain.AuthenticatorAttachment) (*HumanWebAuthNWriteModel, *eventstore.Aggregate, *domain.WebAuthNToken, error) {
|
||||
if userID == "" {
|
||||
return nil, nil, nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-3M0od", "Errors.IDMissing")
|
||||
}
|
||||
@ -157,7 +157,7 @@ func (c *Commands) addHumanWebAuthN(ctx context.Context, userID, resourceowner s
|
||||
if accountName == "" {
|
||||
accountName = user.EmailAddress
|
||||
}
|
||||
webAuthN, err := c.webauthn.BeginRegistration(user, accountName, domain.AuthenticatorAttachmentUnspecified, domain.UserVerificationRequirementDiscouraged, isLoginUI, tokens...)
|
||||
webAuthN, err := c.webauthn.BeginRegistration(user, accountName, authenticatorPlatform, domain.UserVerificationRequirementDiscouraged, isLoginUI, tokens...)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@ -498,6 +498,9 @@ func (c *Commands) HumanAddPasswordlessInitCode(ctx context.Context, userID, res
|
||||
|
||||
func (c *Commands) HumanSendPasswordlessInitCode(ctx context.Context, userID, resourceOwner string) (*domain.PasswordlessInitCode, error) {
|
||||
codeEvent, initCode, code, err := c.humanAddPasswordlessInitCode(ctx, userID, resourceOwner, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.PushEvents(ctx, codeEvent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -178,6 +178,7 @@ const (
|
||||
LoginKeyPasswordlessRegistrationDone = "PasswordlessRegistrationDone."
|
||||
LoginKeyPasswordlessRegistrationDoneTitle = LoginKeyPasswordlessRegistrationDone + "Title"
|
||||
LoginKeyPasswordlessRegistrationDoneDescription = LoginKeyPasswordlessRegistrationDone + "Description"
|
||||
LoginKeyPasswordlessRegistrationDoneDescriptionClose = LoginKeyPasswordlessRegistrationDone + "DescriptionClose"
|
||||
LoginKeyPasswordlessRegistrationDoneNextButtonText = LoginKeyPasswordlessRegistrationDone + "NextButtonText"
|
||||
LoginKeyPasswordlessRegistrationDoneCancelButtonText = LoginKeyPasswordlessRegistrationDone + "CancelButtonText"
|
||||
|
||||
@ -659,6 +660,7 @@ type PasswordlessRegistrationScreenText struct {
|
||||
type PasswordlessRegistrationDoneScreenText struct {
|
||||
Title string
|
||||
Description string
|
||||
DescriptionClose string
|
||||
NextButtonText string
|
||||
CancelButtonText string
|
||||
}
|
||||
|
@ -697,6 +697,9 @@ func passwordlessRegistrationDoneKeyToDomain(text *CustomTextView, result *domai
|
||||
if text.Key == domain.LoginKeyPasswordlessRegistrationDoneDescription {
|
||||
result.PasswordlessRegistrationDone.Description = text.Text
|
||||
}
|
||||
if text.Key == domain.LoginKeyPasswordlessRegistrationDoneDescriptionClose {
|
||||
result.PasswordlessRegistrationDone.DescriptionClose = text.Text
|
||||
}
|
||||
if text.Key == domain.LoginKeyPasswordlessRegistrationDoneNextButtonText {
|
||||
result.PasswordlessRegistrationDone.NextButtonText = text.Text
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ func (l *Login) handlePasswordlessPrompt(w http.ResponseWriter, r *http.Request)
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
l.renderPasswordlessRegistration(w, r, authReq, "", "", "", "", nil)
|
||||
l.renderPasswordlessRegistration(w, r, authReq, "", "", "", "", 0, nil)
|
||||
}
|
||||
|
||||
func (l *Login) renderPasswordlessPrompt(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, err error) {
|
||||
|
@ -4,46 +4,78 @@ import (
|
||||
"encoding/base64"
|
||||
"net/http"
|
||||
|
||||
"github.com/caos/logging"
|
||||
|
||||
http_mw "github.com/caos/zitadel/internal/api/http/middleware"
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
)
|
||||
|
||||
const (
|
||||
tmplPasswordlessRegistration = "passwordlessregistration"
|
||||
tmplPasswordlessRegistrationDone = "passwordlessregistrationdone"
|
||||
queryPasswordlessRegistrationCode = "code"
|
||||
queryPasswordlessRegistrationCodeID = "codeID"
|
||||
queryPasswordlessRegistrationUserID = "userID"
|
||||
queryPasswordlessRegistrationOrgID = "orgID"
|
||||
tmplPasswordlessRegistration = "passwordlessregistration"
|
||||
tmplPasswordlessRegistrationDone = "passwordlessregistrationdone"
|
||||
)
|
||||
|
||||
type passwordlessRegistrationData struct {
|
||||
webAuthNData
|
||||
Code string
|
||||
CodeID string
|
||||
UserID string
|
||||
OrgID string
|
||||
Disabled bool
|
||||
Code string
|
||||
CodeID string
|
||||
UserID string
|
||||
OrgID string
|
||||
RequestPlatformType authPlatform
|
||||
Disabled bool
|
||||
}
|
||||
|
||||
type passwordlessRegistrationDoneDate struct {
|
||||
userData
|
||||
HideNextButton bool
|
||||
}
|
||||
|
||||
type passwordlessRegistrationFormData struct {
|
||||
webAuthNFormData
|
||||
Code string `schema:"code"`
|
||||
CodeID string `schema:"codeID"`
|
||||
UserID string `schema:"userID"`
|
||||
OrgID string `schema:"orgID"`
|
||||
passwordlessRegistrationQueries
|
||||
TokenName string `schema:"name"`
|
||||
}
|
||||
|
||||
func (l *Login) handlePasswordlessRegistration(w http.ResponseWriter, r *http.Request) {
|
||||
userID := r.FormValue(queryPasswordlessRegistrationUserID)
|
||||
orgID := r.FormValue(queryPasswordlessRegistrationOrgID)
|
||||
codeID := r.FormValue(queryPasswordlessRegistrationCodeID)
|
||||
code := r.FormValue(queryPasswordlessRegistrationCode)
|
||||
l.renderPasswordlessRegistration(w, r, nil, userID, orgID, codeID, code, nil)
|
||||
type passwordlessRegistrationQueries struct {
|
||||
Code string `schema:"code"`
|
||||
CodeID string `schema:"codeID"`
|
||||
UserID string `schema:"userID"`
|
||||
OrgID string `schema:"orgID"`
|
||||
RequestPlatformType authPlatform `schema:"requestPlatformType"`
|
||||
}
|
||||
|
||||
func (l *Login) renderPasswordlessRegistration(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, userID, orgID, codeID, code string, err error) {
|
||||
type authPlatform domain.AuthenticatorAttachment
|
||||
|
||||
func (a authPlatform) MarshalText() (text []byte, err error) {
|
||||
switch domain.AuthenticatorAttachment(a) {
|
||||
case domain.AuthenticatorAttachmentPlattform:
|
||||
return []byte("platform"), nil
|
||||
case domain.AuthenticatorAttachmentCrossPlattform:
|
||||
return []byte("crossPlatform"), nil
|
||||
default:
|
||||
return []byte("unspecified"), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a *authPlatform) UnmarshalText(text []byte) (err error) {
|
||||
switch string(text) {
|
||||
case "platform",
|
||||
"1":
|
||||
*a = authPlatform(domain.AuthenticatorAttachmentPlattform)
|
||||
case "crossPlatform",
|
||||
"2":
|
||||
*a = authPlatform(domain.AuthenticatorAttachmentCrossPlattform)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Login) handlePasswordlessRegistration(w http.ResponseWriter, r *http.Request) {
|
||||
queries := new(passwordlessRegistrationQueries)
|
||||
err := l.parser.Parse(r, queries)
|
||||
l.renderPasswordlessRegistration(w, r, nil, queries.UserID, queries.OrgID, queries.CodeID, queries.Code, queries.RequestPlatformType, err)
|
||||
}
|
||||
|
||||
func (l *Login) renderPasswordlessRegistration(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, userID, orgID, codeID, code string, requestedPlatformType authPlatform, err error) {
|
||||
var errID, errMessage, credentialData string
|
||||
var disabled bool
|
||||
if authReq != nil {
|
||||
@ -53,9 +85,9 @@ func (l *Login) renderPasswordlessRegistration(w http.ResponseWriter, r *http.Re
|
||||
var webAuthNToken *domain.WebAuthNToken
|
||||
if err == nil {
|
||||
if authReq != nil {
|
||||
webAuthNToken, err = l.authRepo.BeginPasswordlessSetup(setContext(r.Context(), authReq.UserOrgID), userID, authReq.UserOrgID)
|
||||
webAuthNToken, err = l.authRepo.BeginPasswordlessSetup(setContext(r.Context(), authReq.UserOrgID), userID, authReq.UserOrgID, domain.AuthenticatorAttachment(requestedPlatformType))
|
||||
} else {
|
||||
webAuthNToken, err = l.authRepo.BeginPasswordlessInitCodeSetup(setContext(r.Context(), orgID), userID, orgID, codeID, code)
|
||||
webAuthNToken, err = l.authRepo.BeginPasswordlessInitCodeSetup(setContext(r.Context(), orgID), userID, orgID, codeID, code, domain.AuthenticatorAttachment(requestedPlatformType))
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
@ -74,21 +106,21 @@ func (l *Login) renderPasswordlessRegistration(w http.ResponseWriter, r *http.Re
|
||||
codeID,
|
||||
userID,
|
||||
orgID,
|
||||
requestedPlatformType,
|
||||
disabled,
|
||||
}
|
||||
translator := l.getTranslator(authReq)
|
||||
if authReq == nil {
|
||||
policy, err := l.authRepo.GetLabelPolicy(r.Context(), orgID)
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
logging.Log("LOGIN-afgr2").OnError(err).Warn("could not get label policy")
|
||||
data.LabelPolicy = policy
|
||||
texts, err := l.authRepo.GetLoginText(r.Context(), orgID)
|
||||
if err != nil {
|
||||
|
||||
translator, err = l.renderer.NewTranslator()
|
||||
if err == nil {
|
||||
texts, err := l.authRepo.GetLoginText(r.Context(), orgID)
|
||||
logging.Log("LOGIN-HJK4t").OnError(err).Warn("could not get custom texts")
|
||||
l.addLoginTranslations(translator, texts)
|
||||
}
|
||||
translator, _ = l.renderer.NewTranslator()
|
||||
l.addLoginTranslations(translator, texts)
|
||||
}
|
||||
l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplPasswordlessRegistration], data, nil)
|
||||
}
|
||||
@ -100,13 +132,13 @@ func (l *Login) handlePasswordlessRegistrationCheck(w http.ResponseWriter, r *ht
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
l.checkPasswordlessRegistration(w, r, authReq, formData, nil)
|
||||
l.checkPasswordlessRegistration(w, r, authReq, formData)
|
||||
}
|
||||
|
||||
func (l *Login) checkPasswordlessRegistration(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, formData *passwordlessRegistrationFormData, err error) {
|
||||
func (l *Login) checkPasswordlessRegistration(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, formData *passwordlessRegistrationFormData) {
|
||||
credData, err := base64.URLEncoding.DecodeString(formData.CredentialData)
|
||||
if err != nil {
|
||||
l.renderPasswordlessRegistration(w, r, authReq, formData.UserID, formData.OrgID, formData.CodeID, formData.Code, err)
|
||||
l.renderPasswordlessRegistration(w, r, authReq, formData.UserID, formData.OrgID, formData.CodeID, formData.Code, formData.RequestPlatformType, err)
|
||||
return
|
||||
}
|
||||
userAgentID, _ := http_mw.UserAgentIDFromCtx(r.Context())
|
||||
@ -116,7 +148,7 @@ func (l *Login) checkPasswordlessRegistration(w http.ResponseWriter, r *http.Req
|
||||
err = l.authRepo.VerifyPasswordlessInitCodeSetup(setContext(r.Context(), formData.OrgID), formData.UserID, formData.OrgID, userAgentID, formData.TokenName, formData.CodeID, formData.Code, credData)
|
||||
}
|
||||
if err != nil {
|
||||
l.renderPasswordlessRegistration(w, r, authReq, formData.UserID, formData.OrgID, formData.CodeID, formData.Code, err)
|
||||
l.renderPasswordlessRegistration(w, r, authReq, formData.UserID, formData.OrgID, formData.CodeID, formData.Code, formData.RequestPlatformType, err)
|
||||
return
|
||||
}
|
||||
l.renderPasswordlessRegistrationDone(w, r, authReq, nil)
|
||||
@ -127,6 +159,9 @@ func (l *Login) renderPasswordlessRegistrationDone(w http.ResponseWriter, r *htt
|
||||
if err != nil {
|
||||
errID, errMessage = l.getErrorMessage(r, err)
|
||||
}
|
||||
data := l.getUserData(r, authReq, "Passwordless Registration Done", errID, errMessage)
|
||||
data := passwordlessRegistrationDoneDate{
|
||||
userData: l.getUserData(r, authReq, "Passwordless Registration Done", errID, errMessage),
|
||||
HideNextButton: authReq == nil,
|
||||
}
|
||||
l.renderer.RenderTemplate(w, r, l.getTranslator(authReq), l.renderer.Templates[tmplPasswordlessRegistrationDone], data, nil)
|
||||
}
|
||||
|
@ -153,6 +153,7 @@ PasswordlessRegistration:
|
||||
PasswordlessRegistrationDone:
|
||||
Title: Passwortloser Login erstellt
|
||||
Description: Token für passwortlosen Login erfolgreich hinzugefügt.
|
||||
DescriptionClose: Du kannst das Fenster nun schliessen.
|
||||
NextButtonText: weiter
|
||||
CancelButtonText: abbrechen
|
||||
|
||||
|
@ -153,6 +153,7 @@ PasswordlessRegistration:
|
||||
PasswordlessRegistrationDone:
|
||||
Title: Passwordless set up
|
||||
Description: Token for passwordless successfully added.
|
||||
DescriptionClose: You can now close this window.
|
||||
NextButtonText: next
|
||||
CancelButtonText: cancel
|
||||
|
||||
|
@ -6,4 +6,8 @@
|
||||
margin-right: .5rem;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#wa-error {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -537,6 +537,10 @@ a.block {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
#wa-error {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.lgn-qrcode {
|
||||
display: block;
|
||||
margin: auto;
|
||||
@ -1426,6 +1430,10 @@ a.block {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
#wa-error {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.lgn-qrcode {
|
||||
display: block;
|
||||
margin: auto;
|
||||
|
File diff suppressed because one or more lines are too long
@ -17,6 +17,7 @@
|
||||
<input type="hidden" name="orgID" value="{{ .OrgID }}" />
|
||||
<input type="hidden" name="codeID" value="{{ .CodeID }}" />
|
||||
<input type="hidden" name="code" value="{{ .Code }}" />
|
||||
<input type="hidden" name="requestPlatformType" value="{{ .RequestPlatformType }}" />
|
||||
<input type="hidden" name="credentialCreationData" value="{{ .CredentialCreationData }}" />
|
||||
<input type="hidden" name="credentialData" />
|
||||
|
||||
|
@ -6,6 +6,9 @@
|
||||
{{ template "user-profile" . }}
|
||||
|
||||
<p>{{t "PasswordlessRegistrationDone.Description"}}</p>
|
||||
{{if .HideNextButton }}
|
||||
<p>{{t "PasswordlessRegistrationDone.DescriptionClose"}}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<form action="{{ loginUrl }}" method="POST">
|
||||
@ -15,13 +18,11 @@
|
||||
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
|
||||
|
||||
<div class="lgn-actions">
|
||||
<a class="lgn-stroked-button lgn-primary" href="{{ loginUrl }}">
|
||||
{{t "PasswordlessRegistrationDone.CancelButtonText"}}
|
||||
</a>
|
||||
<span class="fill-space"></span>
|
||||
{{if not .HideNextButton }}
|
||||
<button class="lgn-raised-button lgn-primary" type="submit">{{t "PasswordlessRegistrationDone.NextButtonText"}}</button>
|
||||
{{end}}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
{{template "main-bottom" .}}
|
||||
{{template "main-bottom" .}}
|
||||
|
@ -411,4 +411,5 @@ message PasswordlessRegistrationDoneScreenText {
|
||||
string description = 2 [(validate.rules).string = {max_len: 500}];
|
||||
string next_button_text = 3 [(validate.rules).string = {max_len: 100}];
|
||||
string cancel_button_text = 4 [(validate.rules).string = {max_len: 100}];
|
||||
}
|
||||
string description_close = 5 [(validate.rules).string = {max_len: 100}];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user