mirror of
https://github.com/zitadel/zitadel.git
synced 2025-01-07 08:07:46 +00:00
fix: pass sessionID to OTP email link (#8745)
# Which Problems Are Solved OTP Email links currently could not use / include the sessionID they belong to. This prevents an easy use for redirecting and handling OTP via email through the session API. # How the Problems Are Solved Added the sessionID as placeholder for the OTP Email link template. # Additional Changes List all available placeholders in the url_templates of V2 endpoints. # Additional Context - discussed in a customer meeting
This commit is contained in:
parent
222915ca3d
commit
16171ce3b9
@ -61,7 +61,7 @@ func (c *Commands) OTPSMSSent(ctx context.Context, sessionID, resourceOwner stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) CreateOTPEmailChallengeURLTemplate(urlTmpl string) (SessionCommand, error) {
|
func (c *Commands) CreateOTPEmailChallengeURLTemplate(urlTmpl string) (SessionCommand, error) {
|
||||||
if err := domain.RenderOTPEmailURLTemplate(io.Discard, urlTmpl, "code", "userID", "loginName", "displayName", language.English); err != nil {
|
if err := domain.RenderOTPEmailURLTemplate(io.Discard, urlTmpl, "code", "userID", "loginName", "displayName", "sessionID", language.English); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return c.createOTPEmailChallenge(false, urlTmpl, nil), nil
|
return c.createOTPEmailChallenge(false, urlTmpl, nil), nil
|
||||||
|
@ -20,16 +20,18 @@ type OTPEmailURLData struct {
|
|||||||
LoginName string
|
LoginName string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
PreferredLanguage language.Tag
|
PreferredLanguage language.Tag
|
||||||
|
SessionID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderOTPEmailURLTemplate parses and renders tmpl.
|
// RenderOTPEmailURLTemplate parses and renders tmpl.
|
||||||
// code, userID, (preferred) loginName, displayName and preferredLanguage are passed into the [OTPEmailURLData].
|
// code, userID, (preferred) loginName, displayName and preferredLanguage are passed into the [OTPEmailURLData].
|
||||||
func RenderOTPEmailURLTemplate(w io.Writer, tmpl, code, userID, loginName, displayName string, preferredLanguage language.Tag) error {
|
func RenderOTPEmailURLTemplate(w io.Writer, tmpl, code, userID, loginName, displayName, sessionID string, preferredLanguage language.Tag) error {
|
||||||
return renderURLTemplate(w, tmpl, &OTPEmailURLData{
|
return renderURLTemplate(w, tmpl, &OTPEmailURLData{
|
||||||
Code: code,
|
Code: code,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
LoginName: loginName,
|
LoginName: loginName,
|
||||||
DisplayName: displayName,
|
DisplayName: displayName,
|
||||||
PreferredLanguage: preferredLanguage,
|
PreferredLanguage: preferredLanguage,
|
||||||
|
SessionID: sessionID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -442,7 +442,7 @@ func (u *userNotifier) reduceSessionOTPEmailChallenged(event eventstore.Event) (
|
|||||||
if e.URLTmpl != "" {
|
if e.URLTmpl != "" {
|
||||||
urlTmpl = e.URLTmpl
|
urlTmpl = e.URLTmpl
|
||||||
}
|
}
|
||||||
if err := domain.RenderOTPEmailURLTemplate(&buf, urlTmpl, code, user.ID, user.PreferredLoginName, user.DisplayName, user.PreferredLanguage); err != nil {
|
if err := domain.RenderOTPEmailURLTemplate(&buf, urlTmpl, code, user.ID, user.PreferredLoginName, user.DisplayName, e.Aggregate().ID, user.PreferredLanguage); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return buf.String(), nil
|
return buf.String(), nil
|
||||||
|
@ -42,13 +42,16 @@ message RequestChallenges {
|
|||||||
}
|
}
|
||||||
message OTPEmail {
|
message OTPEmail {
|
||||||
message SendCode {
|
message SendCode {
|
||||||
|
// Optionally set a url_template, which will be used in the mail sent by ZITADEL to guide the user to your verification page.
|
||||||
|
// If no template is set, the default ZITADEL url will be used.
|
||||||
|
//
|
||||||
|
// The following placeholders can be used: Code, UserID, LoginName, DisplayName, PreferredLanguage, SessionID
|
||||||
optional string url_template = 1 [
|
optional string url_template = 1 [
|
||||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
min_length: 1;
|
min_length: 1;
|
||||||
max_length: 200;
|
max_length: 200;
|
||||||
example: "\"https://example.com/otp/verify?userID={{.UserID}}&code={{.Code}}\"";
|
example: "\"https://example.com/otp/verify?userID={{.UserID}}&code={{.Code}}\"";
|
||||||
description: "\"Optionally set a url_template, which will be used in the mail sent by ZITADEL to guide the user to your verification page. If no template is set, the default ZITADEL url will be used.\""
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,16 @@ enum PasskeyAuthenticator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message SendPasskeyRegistrationLink {
|
message SendPasskeyRegistrationLink {
|
||||||
|
// Optionally set a url_template, which will be used in the mail sent by ZITADEL to guide the user to your passkey registration page.
|
||||||
|
// If no template is set, the default ZITADEL url will be used.
|
||||||
|
//
|
||||||
|
// The following placeholders can be used: UserID, OrgID, CodeID, Code
|
||||||
optional string url_template = 1 [
|
optional string url_template = 1 [
|
||||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
min_length: 1;
|
min_length: 1;
|
||||||
max_length: 200;
|
max_length: 200;
|
||||||
example: "\"https://example.com/passkey/register?userID={{.UserID}}&orgID={{.OrgID}}&codeID={{.CodeID}}&code={{.Code}}\"";
|
example: "\"https://example.com/passkey/register?userID={{.UserID}}&orgID={{.OrgID}}&codeID={{.CodeID}}&code={{.Code}}\"";
|
||||||
description: "\"Optionally set a url_template, which will be used in the mail sent by ZITADEL to guide the user to your passkey registration page. If no template is set, the default ZITADEL url will be used.\""
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -39,13 +39,16 @@ message HumanEmail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message SendEmailVerificationCode {
|
message SendEmailVerificationCode {
|
||||||
|
// Optionally set a url_template, which will be used in the verification mail sent by ZITADEL to guide the user to your verification page.
|
||||||
|
// If no template is set, the default ZITADEL url will be used.
|
||||||
|
//
|
||||||
|
// The following placeholders can be used: UserID, OrgID, Code
|
||||||
optional string url_template = 1 [
|
optional string url_template = 1 [
|
||||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
min_length: 1;
|
min_length: 1;
|
||||||
max_length: 200;
|
max_length: 200;
|
||||||
example: "\"https://example.com/email/verify?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}\"";
|
example: "\"https://example.com/email/verify?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}\"";
|
||||||
description: "\"Optionally set a url_template, which will be used in the verification mail sent by ZITADEL to guide the user to your verification page. If no template is set, the default ZITADEL url will be used.\""
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -37,13 +37,16 @@ message HashedPassword {
|
|||||||
|
|
||||||
message SendPasswordResetLink {
|
message SendPasswordResetLink {
|
||||||
NotificationType notification_type = 1;
|
NotificationType notification_type = 1;
|
||||||
|
// Optionally set a url_template, which will be used in the password reset mail sent by ZITADEL to guide the user to your password change page.
|
||||||
|
// If no template is set, the default ZITADEL url will be used.
|
||||||
|
//
|
||||||
|
// The following placeholders can be used: UserID, OrgID, Code
|
||||||
optional string url_template = 2 [
|
optional string url_template = 2 [
|
||||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
min_length: 1;
|
min_length: 1;
|
||||||
max_length: 200;
|
max_length: 200;
|
||||||
example: "\"https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}\"";
|
example: "\"https://example.com/password/changey?userID={{.UserID}}&code={{.Code}}&orgID={{.OrgID}}\"";
|
||||||
description: "\"Optionally set a url_template, which will be used in the password reset mail sent by ZITADEL to guide the user to your password change page. If no template is set, the default ZITADEL url will be used.\""
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -286,6 +286,8 @@ enum AuthFactorState {
|
|||||||
message SendInviteCode {
|
message SendInviteCode {
|
||||||
// Optionally set a url_template, which will be used in the invite mail sent by ZITADEL to guide the user to your invitation page.
|
// Optionally set a url_template, which will be used in the invite mail sent by ZITADEL to guide the user to your invitation page.
|
||||||
// If no template is set, the default ZITADEL url will be used.
|
// If no template is set, the default ZITADEL url will be used.
|
||||||
|
//
|
||||||
|
// The following placeholders can be used: UserID, OrgID, Code
|
||||||
optional string url_template = 1 [
|
optional string url_template = 1 [
|
||||||
(validate.rules).string = {min_len: 1, max_len: 200},
|
(validate.rules).string = {min_len: 1, max_len: 200},
|
||||||
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user