feat(api): add password reset and change to user service (#6036)

* feat(api): add password reset and change to user service

* integration tests

* invalidate password check after password change

* handle notification type

* fix proto
This commit is contained in:
Livio Spring
2023-06-20 17:34:06 +02:00
committed by GitHub
parent 1017568cf1
commit 82e7333169
20 changed files with 1373 additions and 54 deletions

View File

@@ -8,13 +8,6 @@ import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
message SetUserPassword {
oneof type {
Password password = 1;
HashedPassword hashed_password = 2;
}
}
message Password {
string password = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
@@ -51,3 +44,24 @@ message HashedPassword {
];
bool change_required = 3;
}
message SendPasswordResetLink {
NotificationType notification_type = 1;
optional string url_template = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
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.\""
}
];
}
message ReturnPasswordResetCode {}
enum NotificationType {
NOTIFICATION_TYPE_Unspecified = 0;
NOTIFICATION_TYPE_Email = 1;
NOTIFICATION_TYPE_SMS = 2;
}

View File

@@ -390,6 +390,56 @@ service UserService {
};
};
}
// Request password reset
rpc PasswordReset (PasswordResetRequest) returns (PasswordResetResponse) {
option (google.api.http) = {
post: "/v2alpha/users/{user_id}/password_reset"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Request a code to reset a password";
description: "Request a code to reset a password";
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
// Change password
rpc SetPassword (SetPasswordRequest) returns (SetPasswordResponse) {
option (google.api.http) = {
post: "/v2alpha/users/{user_id}/password"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Request a code to reset a password";
description: "Request a code to reset a password";
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
}
message AddHumanUserRequest{
@@ -806,3 +856,66 @@ message AddIDPLinkRequest{
message AddIDPLinkResponse {
zitadel.object.v2alpha.Details details = 1;
}
message PasswordResetRequest{
string user_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"69629026806489455\"";
}
];
// if no medium is specified, an email is sent with the default url
oneof medium {
SendPasswordResetLink send_link = 2;
ReturnPasswordResetCode return_code = 3;
}
}
message PasswordResetResponse{
zitadel.object.v2alpha.Details details = 1;
// in case the medium was set to return_code, the code will be returned
optional string verification_code = 2;
}
message SetPasswordRequest{
string user_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"69629026806489455\"";
}
];
Password new_password = 2;
// if neither, the current password must be provided nor a verification code generated by the PasswordReset is provided,
// the user must be granted permission to set a password
oneof verification {
string current_password = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 200;
example: "\"Secr3tP4ssw0rd!\"";
}
];
string verification_code = 4 [
(validate.rules).string = {min_len: 1, max_len: 20},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
min_length: 1;
max_length: 20;
example: "\"SKJd342k\"";
description: "\"the verification code generated during password reset request\"";
}
];
}
}
message SetPasswordResponse{
zitadel.object.v2alpha.Details details = 1;
}