feat: idp v2 api GetIDPByID (#8425)

# Which Problems Are Solved

GetIDPByID as endpoint in the API v2 so that it can be available for the
new login.

# How the Problems Are Solved

Create GetIDPByID endpoint with IDP v2 API, throught the GetProviderByID
implementation from admin and management API.

# Additional Changes

- Remove the OwnerType attribute from the response, as the information
is available through the resourceOwner.
- correct refs to messages in proto which are used for doc generation
- renaming of elements for API v3

# Additional Context

Closes #8337

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz
2024-08-14 20:18:29 +02:00
committed by GitHub
parent 64a3bb3149
commit 3e3d46ac0d
18 changed files with 1348 additions and 22 deletions

View File

@@ -0,0 +1,391 @@
syntax = "proto3";
package zitadel.idp.v2;
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/object/v2/object.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "google/protobuf/duration.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/idp/v2;idp";
message IDP {
// Unique identifier for the identity provider.
string id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
}
];
zitadel.object.v2.Details details = 2;
// Current state of the identity provider.
IDPState state = 3;
string name = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"Google\"";
}
];
// Type of the identity provider, for example OIDC, JWT, LDAP and SAML.
IDPType type = 5;
// Configuration for the type of the identity provider.
IDPConfig config = 6;
}
enum IDPState {
IDP_STATE_UNSPECIFIED = 0;
IDP_STATE_ACTIVE = 1;
IDP_STATE_INACTIVE = 2;
IDP_STATE_REMOVED = 3;
IDP_STATE_MIGRATED = 4;
}
enum IDPType {
IDP_TYPE_UNSPECIFIED = 0;
IDP_TYPE_OIDC = 1;
IDP_TYPE_JWT = 2;
IDP_TYPE_LDAP = 3;
IDP_TYPE_OAUTH = 4;
IDP_TYPE_AZURE_AD = 5;
IDP_TYPE_GITHUB = 6;
IDP_TYPE_GITHUB_ES = 7;
IDP_TYPE_GITLAB = 8;
IDP_TYPE_GITLAB_SELF_HOSTED = 9;
IDP_TYPE_GOOGLE = 10;
IDP_TYPE_APPLE = 11;
IDP_TYPE_SAML = 12;
}
enum SAMLBinding {
SAML_BINDING_UNSPECIFIED = 0;
SAML_BINDING_POST = 1;
SAML_BINDING_REDIRECT = 2;
SAML_BINDING_ARTIFACT = 3;
}
enum SAMLNameIDFormat {
SAML_NAME_ID_FORMAT_UNSPECIFIED = 0;
SAML_NAME_ID_FORMAT_EMAIL_ADDRESS = 1;
SAML_NAME_ID_FORMAT_PERSISTENT = 2;
SAML_NAME_ID_FORMAT_TRANSIENT = 3;
}
message IDPConfig {
Options options = 1;
oneof config {
LDAPConfig ldap = 2;
GoogleConfig google = 3;
OAuthConfig oauth = 4;
GenericOIDCConfig oidc = 5;
JWTConfig jwt = 6;
GitHubConfig github = 7;
GitHubEnterpriseServerConfig github_es = 8;
GitLabConfig gitlab = 9;
GitLabSelfHostedConfig gitlab_self_hosted = 10;
AzureADConfig azure_ad = 11;
AppleConfig apple = 12;
SAMLConfig saml = 13;
}
}
message JWTConfig {
// The endpoint where the JWT can be extracted.
string jwt_endpoint = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
}
];
// The issuer of the JWT (for validation).
string issuer = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
}
];
// The endpoint to the key (JWK) which is used to sign the JWT with.
string keys_endpoint = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/keys\"";
}
];
// The name of the header where the JWT is sent in, default is authorization.
string header_name = 4 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"x-auth-token\"";
}
];
}
message OAuthConfig {
// Client id generated by the identity provider.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// The endpoint where ZITADEL send the user to authenticate.
string authorization_endpoint = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/o/oauth2/v2/auth\"";
}
];
// The endpoint where ZITADEL can get the token.
string token_endpoint = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://oauth2.googleapis.com/token\"";
}
];
// The endpoint where ZITADEL can get the user information.
string user_endpoint = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://openidconnect.googleapis.com/v1/userinfo\"";
}
];
// The scopes requested by ZITADEL during the request on the identity provider.
repeated string scopes = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
// Defines how the attribute is called where ZITADEL can get the id of the user.
string id_attribute = 6 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"user_id\"";
}
];
}
message GenericOIDCConfig {
// The OIDC issuer of the identity provider.
string issuer = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/\"";
}
];
// Client id generated by the identity provider.
string client_id = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// The scopes requested by ZITADEL during the request on the identity provider.
repeated string scopes = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
// If true, provider information get mapped from the id token, not from the userinfo endpoint.
bool is_id_token_mapping = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "true";
}
];
}
message GitHubConfig {
// The client ID of the GitHub App.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// The scopes requested by ZITADEL during the request to GitHub.
repeated string scopes = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
}
message GitHubEnterpriseServerConfig {
// The client ID of the GitHub App.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
string authorization_endpoint = 2;
string token_endpoint = 3;
string user_endpoint = 4;
// The scopes requested by ZITADEL during the request to GitHub.
repeated string scopes = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
}
message GoogleConfig {
// Client id of the Google application.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// The scopes requested by ZITADEL during the request to Google.
repeated string scopes = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
}
message GitLabConfig {
// Client id of the GitLab application.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// The scopes requested by ZITADEL during the request to GitLab.
repeated string scopes = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
}
message GitLabSelfHostedConfig {
string issuer = 1;
// Client id of the GitLab application.
string client_id = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// The scopes requested by ZITADEL during the request to GitLab.
repeated string scopes = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
}
message LDAPConfig {
repeated string servers = 1;
bool start_tls = 2;
string base_dn = 3;
string bind_dn = 4;
string user_base = 5;
repeated string user_object_classes = 6;
repeated string user_filters = 7;
google.protobuf.Duration timeout = 8;
LDAPAttributes attributes = 9;
}
message SAMLConfig {
// Metadata of the SAML identity provider.
bytes metadata_xml = 1;
// Binding which defines the type of communication with the identity provider.
SAMLBinding binding = 2;
// Boolean which defines if the authentication requests are signed.
bool with_signed_request = 3;
// `nameid-format` for the SAML Request.
SAMLNameIDFormat name_id_format = 4;
// Optional name of the attribute, which will be used to map the user
// in case the nameid-format returned is `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`.
optional string transient_mapping_attribute_name = 5;
}
message AzureADConfig {
// Client id of the Azure AD application
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// Defines what user accounts should be able to login (Personal, Organizational, All).
AzureADTenant tenant = 2;
// Azure AD doesn't send if the email has been verified. Enable this if the user email should always be added verified in ZITADEL (no verification emails will be sent).
bool email_verified = 3;
// The scopes requested by ZITADEL during the request to Azure AD.
repeated string scopes = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\", \"User.Read\"]";
}
];
}
message Options {
// Enable if users should be able to link an existing ZITADEL user with an external account.
bool is_linking_allowed = 1;
// Enable if users should be able to create a new account in ZITADEL when using an external account.
bool is_creation_allowed = 2;
// Enable if a new account in ZITADEL should be created automatically when login with an external account.
bool is_auto_creation = 3;
// Enable if a the ZITADEL account fields should be updated automatically on each login.
bool is_auto_update = 4;
// Enable if users should get prompted to link an existing ZITADEL user to an external account if the selected attribute matches.
AutoLinkingOption auto_linking = 5 ;
}
enum AutoLinkingOption {
// AUTO_LINKING_OPTION_UNSPECIFIED disables the auto linking prompt.
AUTO_LINKING_OPTION_UNSPECIFIED = 0;
// AUTO_LINKING_OPTION_USERNAME will use the username of the external user to check for a corresponding ZITADEL user.
AUTO_LINKING_OPTION_USERNAME = 1;
// AUTO_LINKING_OPTION_EMAIL will use the email of the external user to check for a corresponding ZITADEL user with the same verified email
// Note that in case multiple users match, no prompt will be shown.
AUTO_LINKING_OPTION_EMAIL = 2;
}
message LDAPAttributes {
string id_attribute = 1 [(validate.rules).string = {max_len: 200}];
string first_name_attribute = 2 [(validate.rules).string = {max_len: 200}];
string last_name_attribute = 3 [(validate.rules).string = {max_len: 200}];
string display_name_attribute = 4 [(validate.rules).string = {max_len: 200}];
string nick_name_attribute = 5 [(validate.rules).string = {max_len: 200}];
string preferred_username_attribute = 6 [(validate.rules).string = {max_len: 200}];
string email_attribute = 7 [(validate.rules).string = {max_len: 200}];
string email_verified_attribute = 8 [(validate.rules).string = {max_len: 200}];
string phone_attribute = 9 [(validate.rules).string = {max_len: 200}];
string phone_verified_attribute = 10 [(validate.rules).string = {max_len: 200}];
string preferred_language_attribute = 11 [(validate.rules).string = {max_len: 200}];
string avatar_url_attribute = 12 [(validate.rules).string = {max_len: 200}];
string profile_attribute = 13 [(validate.rules).string = {max_len: 200}];
}
enum AzureADTenantType {
AZURE_AD_TENANT_TYPE_COMMON = 0;
AZURE_AD_TENANT_TYPE_ORGANISATIONS = 1;
AZURE_AD_TENANT_TYPE_CONSUMERS = 2;
}
message AzureADTenant {
oneof type {
AzureADTenantType tenant_type = 1;
string tenant_id = 2;
}
}
message AppleConfig {
// Client id (App ID or Service ID) provided by Apple.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"com.client.id\"";
}
];
// Team ID provided by Apple.
string team_id = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ALT03JV3OS\"";
}
];
// ID of the private key generated by Apple.
string key_id = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"OGKDK25KD\"";
}
];
// The scopes requested by ZITADEL during the request to Apple.
repeated string scopes = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"name\", \"email\"]";
}
];
}

View File

@@ -0,0 +1,136 @@
syntax = "proto3";
package zitadel.idp.v2;
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "zitadel/object/v2/object.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "zitadel/idp/v2/idp.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/idp/v2;idp";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "Identity Provider Service";
version: "2.0";
description: "This API is intended to manage identity providers (IdPs) in a ZITADEL instance.";
contact:{
name: "ZITADEL"
url: "https://zitadel.com"
email: "hi@zitadel.com"
}
license: {
name: "Apache 2.0",
url: "https://github.com/zitadel/zitadel/blob/main/LICENSE";
};
};
schemes: HTTPS;
schemes: HTTP;
consumes: "application/json";
consumes: "application/grpc";
produces: "application/json";
produces: "application/grpc";
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "$CUSTOM-DOMAIN";
base_path: "/";
external_docs: {
description: "Detailed information about ZITADEL",
url: "https://zitadel.com/docs"
}
security_definitions: {
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
scopes: {
scope: {
key: "openid";
value: "openid";
}
scope: {
key: "urn:zitadel:iam:org:project:id:zitadel:aud";
value: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
}
}
security: {
security_requirement: {
key: "OAuth2";
value: {
scope: "openid";
scope: "urn:zitadel:iam:org:project:id:zitadel:aud";
}
}
}
responses: {
key: "403";
value: {
description: "Returned when the user does not have permission to access the resource.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
responses: {
key: "404";
value: {
description: "Returned when the resource does not exist.";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
}
}
}
}
};
service IdentityProviderService {
// Get identity provider (IdP) by ID
//
// Returns an identity provider (social/enterprise login) by its ID, which can be of the type Google, AzureAD, etc.
rpc GetIDPByID (GetIDPByIDRequest) returns (GetIDPByIDResponse) {
option (google.api.http) = {
get: "/v2/idps/{id}"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
auth_option: {
permission: "authenticated"
}
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
responses: {
key: "200"
value: {
description: "OK";
}
};
};
}
}
message GetIDPByIDRequest {
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
}
message GetIDPByIDResponse {
zitadel.idp.v2.IDP idp = 1;
}

View File

@@ -47,7 +47,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "${ZITADEL_DOMAIN}";
host: "$CUSTOM-DOMAIN";
base_path: "/resources/v3alpha/actions";
external_docs: {
@@ -60,8 +60,8 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "${ZITADEL_DOMAIN}/oauth/v2/authorize";
token_url: "${ZITADEL_DOMAIN}/oauth/v2/token";
authorization_url: "$CUSTOM-DOMAIN/oauth/v2/authorize";
token_url: "$CUSTOM-DOMAIN/oauth/v2/token";
scopes: {
scope: {
key: "openid";
@@ -135,7 +135,7 @@ service ZITADELActions {
description: "Target successfully created";
schema: {
json_schema: {
ref: "#/definitions/CreateTargetResponse";
ref: "#/definitions/v3alphaCreateTargetResponse";
}
}
};
@@ -278,7 +278,7 @@ service ZITADELActions {
description: "Execution successfully updated or left unchanged";
schema: {
json_schema: {
ref: "#/definitions/SetExecutionResponse";
ref: "#/definitions/v3alphaSetExecutionResponse";
}
}
};

View File

@@ -42,7 +42,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
consumes: "application/grpc-web+proto";
produces: "application/grpc-web+proto";
host: "${ZITADEL_DOMAIN}";
host: "$CUSTOM-DOMAIN";
base_path: "/resources/v3alpha/web_keys";
external_docs: {