feat: v2alpha user service idp endpoints (#5879)

* feat: v2alpha user service idp endpoints

* feat: v2alpha user service intent endpoints

* begin idp intents (callback)

* some cleanup

* runnable idp authentication

* cleanup

* proto cleanup

* retrieve idp info

* improve success and failure handling

* some unit tests

* grpc unit tests

* add permission check AddUserIDPLink

* feat: v2alpha intent writemodel refactoring

* feat: v2alpha intent writemodel refactoring

* feat: v2alpha intent writemodel refactoring

* provider from write model

* fix idp type model and add integration tests

* proto cleanup

* fix integration test

* add missing import

* add more integration tests

* auth url test

* feat: v2alpha intent writemodel refactoring

* remove unused functions

* check token on RetrieveIdentityProviderInformation

* feat: v2alpha intent writemodel refactoring

* fix TestServer_RetrieveIdentityProviderInformation

* fix test

* i18n and linting

* feat: v2alpha intent review changes

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
This commit is contained in:
Stefan Benz
2023-05-24 20:29:58 +02:00
committed by GitHub
parent 767b3d7e65
commit fa8f191812
35 changed files with 3560 additions and 19 deletions

View File

@@ -0,0 +1,51 @@
syntax = "proto3";
package zitadel.user.v2alpha;
option go_package = "github.com/zitadel/zitadel/pkg/grpc/user/v2alpha;user";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
message IDPInformation{
oneof access{
IDPOAuthAccessInformation oauth = 1;
}
bytes idp_information = 2;
}
message IDPOAuthAccessInformation{
string access_token = 1;
optional string id_token = 2;
}
message IDPLink {
string idp_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "ID of the identity provider"
min_length: 1;
max_length: 200;
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
}
];
string idp_external_id = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "ID of user of the identity provider"
min_length: 1;
max_length: 200;
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
}
];
string display_name = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Display name of user of the identity provider"
min_length: 1;
max_length: 200;
example: "\"Firstname Lastname\"";
}
];
}

View File

@@ -6,6 +6,7 @@ import "zitadel/object/v2alpha/object.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/user/v2alpha/auth.proto";
import "zitadel/user/v2alpha/email.proto";
import "zitadel/user/v2alpha/idp.proto";
import "zitadel/user/v2alpha/password.proto";
import "zitadel/user/v2alpha/user.proto";
import "google/api/annotations.proto";
@@ -158,7 +159,7 @@ service UserService {
rpc RegisterPasskey (RegisterPasskeyRequest) returns (RegisterPasskeyResponse) {
option (google.api.http) = {
post: "/users/{user_id}/passkeys"
post: "/v2alpha/users/{user_id}/passkeys"
body: "*"
};
@@ -180,7 +181,7 @@ service UserService {
}
rpc VerifyPasskeyRegistration (VerifyPasskeyRegistrationRequest) returns (VerifyPasskeyRegistrationResponse) {
option (google.api.http) = {
post: "/users/{user_id}/passkeys/{passkey_id}"
post: "/v2alpha/users/{user_id}/passkeys/{passkey_id}"
body: "*"
};
@@ -202,7 +203,7 @@ service UserService {
}
rpc CreatePasskeyRegistrationLink (CreatePasskeyRegistrationLinkRequest) returns (CreatePasskeyRegistrationLinkResponse) {
option (google.api.http) = {
post: "/users/{user_id}/passkeys/registration_link"
post: "/v2alpha/users/{user_id}/passkeys/registration_link"
body: "*"
};
@@ -222,6 +223,80 @@ service UserService {
};
};
}
// Start an IDP authentication (for external login, registration or linking)
rpc StartIdentityProviderFlow (StartIdentityProviderFlowRequest) returns (StartIdentityProviderFlowResponse) {
option (google.api.http) = {
post: "/v2alpha/users/idps/{idp_id}/start"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Start flow with an identity provider";
description: "Start a flow with an identity provider, for external login, registration or linking";
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
rpc RetrieveIdentityProviderInformation (RetrieveIdentityProviderInformationRequest) returns (RetrieveIdentityProviderInformationResponse) {
option (google.api.http) = {
post: "/v2alpha/users/intents/{intent_id}/information"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Retrieve the information returned by the identity provider";
description: "Retrieve the information returned by the identity provider for registration or updating an existing user with new information";
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
// Link an IDP to an existing user
rpc AddIDPLink (AddIDPLinkRequest) returns (AddIDPLinkResponse) {
option (google.api.http) = {
post: "/v2alpha/users/users/{user_id}/links"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
summary: "Add link to an identity provider to an user";
description: "Add link to an identity provider to an user";
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
}
message AddHumanUserRequest{
@@ -257,6 +332,7 @@ message AddHumanUserRequest{
Password password = 7;
HashedPassword hashed_password = 8;
}
repeated IDPLink idp_links = 9;
}
message AddHumanUserResponse {
@@ -430,3 +506,88 @@ message CreatePasskeyRegistrationLinkResponse{
}
];
}
message StartIdentityProviderFlowRequest{
string idp_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "ID for existing identity provider"
min_length: 1;
max_length: 200;
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
}
];
string success_url = 2 [
(validate.rules).string = {min_len: 1, max_len: 200, uri_ref: true},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "URL on which the user will be redirected after a successful login"
min_length: 1;
max_length: 200;
example: "\"https://custom.com/login/idp/success\"";
}
];
string failure_url = 3 [
(validate.rules).string = {min_len: 1, max_len: 200, uri_ref: true},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "URL on which the user will be redirected after a failed login"
min_length: 1;
max_length: 200;
example: "\"https://custom.com/login/idp/fail\"";
}
];
}
message StartIdentityProviderFlowResponse{
zitadel.object.v2alpha.Details details = 1;
oneof next_step {
string auth_url = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "URL to which the client should redirect"
example: "\"https://accounts.google.com/o/oauth2/v2/auth?client_id=clientID&callback=https%3A%2F%2Fzitadel.cloud%2Fidps%2Fcallback\"";
}
];
}
}
message RetrieveIdentityProviderInformationRequest{
string intent_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "ID of the intent, previously returned on the success response of the IDP callback"
min_length: 1;
max_length: 200;
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
}
];
string token = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "token of the intent, previously returned on the success response of the IDP callback"
min_length: 1;
max_length: 200;
example: "\"SJKL3ioIDpo342ioqw98fjp3sdf32wahb=\"";
}
];
}
message RetrieveIdentityProviderInformationResponse{
zitadel.object.v2alpha.Details details = 1;
IDPInformation idp_information = 2;
}
message AddIDPLinkRequest{
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\"";
}
];
IDPLink idp_link = 2;
}
message AddIDPLinkResponse {
zitadel.object.v2alpha.Details details = 1;
}