feat: jwt as idp (#2363)

* feat: jwt idp

* feat: command side

* feat: add tests

* fill idp views with jwt idps and return apis

* add jwtEndpoint to jwt idp

* begin jwt request handling

* merge

* handle jwt idp

* cleanup

* fixes

* autoregister

* get token from specific header name

* error handling

* fix texts

* handle renderExternalNotFoundOption

Co-authored-by: fabi <fabienne.gerschwiler@gmail.com>
This commit is contained in:
Livio Amstutz
2021-09-14 15:15:01 +02:00
committed by GitHub
parent 4e1d42259c
commit b6b5b1b782
54 changed files with 2575 additions and 71 deletions

View File

@@ -401,6 +401,41 @@ service AdminService {
};
}
// Adds a new jwt identity provider configuration the IAM
rpc AddJWTIDP(AddJWTIDPRequest) returns (AddJWTIDPResponse) {
option (google.api.http) = {
post: "/idps/jwt";
body: "*";
};
option (zitadel.v1.auth_option) = {
permission: "iam.idp.write";
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "identity provider";
tags: "jwt";
responses: {
key: "200";
value: {
description: "idp created";
};
};
responses: {
key: "400";
value: {
description: "invalid argument";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
};
};
};
};
};
}
//Updates the specified idp
// all fields are updated. If no value is provided the field will be empty afterwards.
rpc UpdateIDP(UpdateIDPRequest) returns (UpdateIDPResponse) {
@@ -598,7 +633,53 @@ service AdminService {
};
};
}
//Updates the jwt configuration of the specified idp
// all fields are updated. If no value is provided the field will be empty afterwards.
rpc UpdateIDPJWTConfig(UpdateIDPJWTConfigRequest) returns (UpdateIDPJWTConfigResponse) {
option (google.api.http) = {
put: "/idps/{idp_id}/jwt_config";
body: "*";
};
option (zitadel.v1.auth_option) = {
permission: "iam.idp.write";
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "identity provider";
tags: "jwt";
responses: {
key: "200";
value: {
description: "jwt config updated";
};
};
responses: {
key: "400";
value: {
description: "invalid argument";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
};
};
};
};
responses: {
key: "409";
value: {
description: "precondition failed";
schema: {
json_schema: {
ref: "#/definitions/rpcStatus";
};
};
};
};
};
}
rpc GetDefaultFeatures(GetDefaultFeaturesRequest) returns (GetDefaultFeaturesResponse) {
option(google.api.http) = {
get: "/features"
@@ -2436,6 +2517,64 @@ message AddOIDCIDPResponse {
string idp_id = 2;
}
message AddJWTIDPRequest {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {
required: ["name", "issuer", "keys_endpoint"]
};
};
string name = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"google\"";
min_length: 1;
max_length: 200;
}
];
zitadel.idp.v1.IDPStylingType styling_type = 2 [
(validate.rules).enum = {defined_only: true},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "some identity providers specify the styling of the button to their login";
}
];
string jwt_endpoint = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://custom.com/auth/jwt\"";
description: "the endpoint where the jwt can be extracted";
}
];
string issuer = 4 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.custom.com\"";
description: "the issuer of the jwt (for validation)";
}
];
string keys_endpoint = 5 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.custom.com/keys\"";
description: "the endpoint to the key (JWK) which are used to sign the JWT with";
}
];
string header_name = 6 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"x-auth-token\"";
description: "the name of the header where the JWT is sent in, default is authorization";
max_length: 200;
}
];
bool auto_register = 7;
}
message AddJWTIDPResponse {
zitadel.v1.ObjectDetails details = 1;
string idp_id = 2;
}
message UpdateIDPRequest {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {
@@ -2590,6 +2729,62 @@ message UpdateIDPOIDCConfigResponse {
zitadel.v1.ObjectDetails details = 1;
}
message UpdateIDPJWTConfigRequest {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {
required: ["idp_id", "issuer", "keys_endpoint"]
};
};
string idp_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
min_length: 1;
max_length: 200;
}
];
string jwt_endpoint = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://custom.com/auth/jwt\"";
description: "the endpoint where the jwt can be extracted";
min_length: 1;
max_length: 200;
}
];
string issuer = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.custom.com\"";
description: "the issuer of the jwt (for validation)";
min_length: 1;
max_length: 200;
}
];
string keys_endpoint = 4 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.custom.com/keys\"";
description: "the endpoint to the key (JWK) which are used to sign the JWT with";
min_length: 1;
max_length: 200;
}
];
string header_name = 5 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"x-auth-token\"";
description: "the name of the header where the JWT is sent in, default is authorization";
max_length: 200;
}
];
}
message UpdateIDPJWTConfigResponse {
zitadel.v1.ObjectDetails details = 1;
}
message GetDefaultFeaturesRequest {}
message GetDefaultFeaturesResponse {
@@ -3637,4 +3832,4 @@ message FailedEvent {
example: "\"ID=EXAMP-ID3ER Message=Example message\"";
}
];
}
}

View File

@@ -37,6 +37,7 @@ message IDP {
];
oneof config {
OIDCConfig oidc_config = 7;
JWTConfig jwt_config = 9;
}
bool auto_register = 8;
}
@@ -115,6 +116,7 @@ enum IDPType {
IDP_TYPE_UNSPECIFIED = 0;
IDP_TYPE_OIDC = 1;
//PLANNED: IDP_TYPE_SAML
IDP_TYPE_JWT = 3;
}
// the owner of the identity provider.
@@ -162,6 +164,38 @@ enum OIDCMappingField {
OIDC_MAPPING_FIELD_EMAIL = 2;
}
message JWTConfig {
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\"";
description: "the endpoint where the jwt can be extracted";
}
];
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\"";
description: "the issuer of the jwt (for validation)";
}
];
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\"";
description: "the endpoint to the key (JWK) which are used to sign the JWT with";
}
];
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\"";
description: "the name of the header where the JWT is sent in, default is authorization";
}
];
}
message IDPIDQuery {
string id = 1 [
(validate.rules).string = {max_len: 200},

View File

@@ -2617,6 +2617,19 @@ service ManagementService {
};
}
// Add a new jwt identity provider configuration in the organisation
rpc AddOrgJWTIDP(AddOrgJWTIDPRequest) returns (AddOrgJWTIDPResponse) {
option (google.api.http) = {
post: "/idps/jwt"
body: "*"
};
option (zitadel.v1.auth_option) = {
permission: "org.idp.write"
feature: "login_policy.idp"
};
}
// Deactivate identity provider configuration
// Users will not be able to use this provider for login (e.g Google, Microsoft, AD, etc)
// Returns error if already deactivated
@@ -2684,6 +2697,19 @@ service ManagementService {
feature: "login_policy.idp"
};
}
// Change JWT identity provider configuration of the organisation
rpc UpdateOrgIDPJWTConfig(UpdateOrgIDPJWTConfigRequest) returns (UpdateOrgIDPJWTConfigResponse) {
option (google.api.http) = {
put: "/idps/{idp_id}/jwt_config"
body: "*"
};
option (zitadel.v1.auth_option) = {
permission: "org.idp.write"
feature: "login_policy.idp"
};
}
}
//This is an empty request
@@ -4892,6 +4918,62 @@ message AddOrgOIDCIDPResponse {
string idp_id = 2;
}
message AddOrgJWTIDPRequest {
string name = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"google\"";
}
];
zitadel.idp.v1.IDPStylingType styling_type = 2 [
(validate.rules).enum = {defined_only: true},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "some identity providers specify the styling of the button to their login";
}
];
string jwt_endpoint = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
description: "the endpoint where the jwt can be extracted";
min_length: 1;
max_length: 200;
}
];
string issuer = 4 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
description: "the issuer of the jwt (for validation)";
min_length: 1;
max_length: 200;
}
];
string keys_endpoint = 5 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/keys\"";
description: "the endpoint to the key (JWK) which are used to sign the JWT with";
min_length: 1;
max_length: 200;
}
];
string header_name = 6 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"x-auth-token\"";
description: "the name of the header where the JWT is sent in, default is authorization";
max_length: 200;
}
];
bool auto_register = 7;
}
message AddOrgJWTIDPResponse {
zitadel.v1.ObjectDetails details = 1;
string idp_id = 2;
}
message DeactivateOrgIDPRequest {
string idp_id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
}
@@ -4986,3 +5068,52 @@ message UpdateOrgIDPOIDCConfigRequest {
message UpdateOrgIDPOIDCConfigResponse {
zitadel.v1.ObjectDetails details = 1;
}
message UpdateOrgIDPJWTConfigRequest {
string idp_id = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
}
];
string jwt_endpoint = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
description: "the endpoint where the jwt can be extracted";
min_length: 1;
max_length: 200;
}
];
string issuer = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
description: "the issuer of the jwt (for validation)";
min_length: 1;
max_length: 200;
}
];
string keys_endpoint = 4 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/keys\"";
description: "the endpoint to the key (JWK) which are used to sign the JWT with";
min_length: 1;
max_length: 200;
}
];
string header_name = 5 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"x-auth-token\"";
description: "the name of the header where the JWT is sent in, default is authorization";
max_length: 200;
}
];
}
message UpdateOrgIDPJWTConfigResponse {
zitadel.v1.ObjectDetails details = 1;
}