From 77777730676b2ad8ac302bc1c5ba6f491f4351f7 Mon Sep 17 00:00:00 2001 From: Maksim Nabokikh Date: Wed, 11 Mar 2026 07:21:14 +0100 Subject: [PATCH] feat(connector): connectors for grants (#4619) Signed-off-by: maksim.nabokikh --- api/v2/api.pb.go | 701 ++++++++++++++------------ api/v2/api.proto | 11 + cmd/dex/config.go | 24 +- cmd/dex/config_test.go | 7 + cmd/dex/serve.go | 5 + examples/config-dev.yaml | 14 +- server/api.go | 36 +- server/api_test.go | 99 ++++ server/handlers.go | 87 +++- server/handlers_test.go | 157 ++++++ server/oauth2.go | 10 + server/refreshhandlers.go | 4 + server/server.go | 9 + storage/conformance/conformance.go | 11 +- storage/ent/client/connector.go | 2 + storage/ent/client/types.go | 9 +- storage/ent/db/connector.go | 18 +- storage/ent/db/connector/connector.go | 3 + storage/ent/db/connector/where.go | 10 + storage/ent/db/connector_create.go | 10 + storage/ent/db/connector_update.go | 59 +++ storage/ent/db/migrate/schema.go | 1 + storage/ent/db/mutation.go | 119 ++++- storage/ent/schema/connector.go | 2 + storage/kubernetes/types.go | 12 +- storage/sql/crud.go | 35 +- storage/sql/migrate.go | 7 + storage/storage.go | 4 + 28 files changed, 1087 insertions(+), 379 deletions(-) diff --git a/api/v2/api.pb.go b/api/v2/api.pb.go index 6e8a134e..ee7e90ce 100644 --- a/api/v2/api.pb.go +++ b/api/v2/api.pb.go @@ -1129,6 +1129,7 @@ type Connector struct { Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` Config []byte `protobuf:"bytes,4,opt,name=config,proto3" json:"config,omitempty"` + GrantTypes []string `protobuf:"bytes,5,rep,name=grant_types,json=grantTypes,proto3" json:"grant_types,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1191,6 +1192,13 @@ func (x *Connector) GetConfig() []byte { return nil } +func (x *Connector) GetGrantTypes() []string { + if x != nil { + return x.GrantTypes + } + return nil +} + // CreateConnectorReq is a request to make a connector. type CreateConnectorReq struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1281,21 +1289,71 @@ func (x *CreateConnectorResp) GetAlreadyExists() bool { return false } +// GrantTypes wraps a list of grant types to distinguish between +// "not specified" (no update) and "empty list" (unrestricted). +type GrantTypes struct { + state protoimpl.MessageState `protogen:"open.v1"` + GrantTypes []string `protobuf:"bytes,1,rep,name=grant_types,json=grantTypes,proto3" json:"grant_types,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GrantTypes) Reset() { + *x = GrantTypes{} + mi := &file_api_v2_api_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GrantTypes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GrantTypes) ProtoMessage() {} + +func (x *GrantTypes) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_api_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GrantTypes.ProtoReflect.Descriptor instead. +func (*GrantTypes) Descriptor() ([]byte, []int) { + return file_api_v2_api_proto_rawDescGZIP(), []int{24} +} + +func (x *GrantTypes) GetGrantTypes() []string { + if x != nil { + return x.GrantTypes + } + return nil +} + // UpdateConnectorReq is a request to modify an existing connector. type UpdateConnectorReq struct { state protoimpl.MessageState `protogen:"open.v1"` // The id used to lookup the connector. This field cannot be modified - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - NewType string `protobuf:"bytes,2,opt,name=new_type,json=newType,proto3" json:"new_type,omitempty"` - NewName string `protobuf:"bytes,3,opt,name=new_name,json=newName,proto3" json:"new_name,omitempty"` - NewConfig []byte `protobuf:"bytes,4,opt,name=new_config,json=newConfig,proto3" json:"new_config,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + NewType string `protobuf:"bytes,2,opt,name=new_type,json=newType,proto3" json:"new_type,omitempty"` + NewName string `protobuf:"bytes,3,opt,name=new_name,json=newName,proto3" json:"new_name,omitempty"` + NewConfig []byte `protobuf:"bytes,4,opt,name=new_config,json=newConfig,proto3" json:"new_config,omitempty"` + // If set, updates the connector's allowed grant types. + // An empty grant_types list means unrestricted (all grant types allowed). + // If not set (null), grant types are not modified. + NewGrantTypes *GrantTypes `protobuf:"bytes,5,opt,name=new_grant_types,json=newGrantTypes,proto3" json:"new_grant_types,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *UpdateConnectorReq) Reset() { *x = UpdateConnectorReq{} - mi := &file_api_v2_api_proto_msgTypes[24] + mi := &file_api_v2_api_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1307,7 +1365,7 @@ func (x *UpdateConnectorReq) String() string { func (*UpdateConnectorReq) ProtoMessage() {} func (x *UpdateConnectorReq) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[24] + mi := &file_api_v2_api_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1320,7 +1378,7 @@ func (x *UpdateConnectorReq) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateConnectorReq.ProtoReflect.Descriptor instead. func (*UpdateConnectorReq) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{24} + return file_api_v2_api_proto_rawDescGZIP(), []int{25} } func (x *UpdateConnectorReq) GetId() string { @@ -1351,6 +1409,13 @@ func (x *UpdateConnectorReq) GetNewConfig() []byte { return nil } +func (x *UpdateConnectorReq) GetNewGrantTypes() *GrantTypes { + if x != nil { + return x.NewGrantTypes + } + return nil +} + // UpdateConnectorResp returns the response from modifying an existing connector. type UpdateConnectorResp struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1361,7 +1426,7 @@ type UpdateConnectorResp struct { func (x *UpdateConnectorResp) Reset() { *x = UpdateConnectorResp{} - mi := &file_api_v2_api_proto_msgTypes[25] + mi := &file_api_v2_api_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1373,7 +1438,7 @@ func (x *UpdateConnectorResp) String() string { func (*UpdateConnectorResp) ProtoMessage() {} func (x *UpdateConnectorResp) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[25] + mi := &file_api_v2_api_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1386,7 +1451,7 @@ func (x *UpdateConnectorResp) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateConnectorResp.ProtoReflect.Descriptor instead. func (*UpdateConnectorResp) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{25} + return file_api_v2_api_proto_rawDescGZIP(), []int{26} } func (x *UpdateConnectorResp) GetNotFound() bool { @@ -1406,7 +1471,7 @@ type DeleteConnectorReq struct { func (x *DeleteConnectorReq) Reset() { *x = DeleteConnectorReq{} - mi := &file_api_v2_api_proto_msgTypes[26] + mi := &file_api_v2_api_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1418,7 +1483,7 @@ func (x *DeleteConnectorReq) String() string { func (*DeleteConnectorReq) ProtoMessage() {} func (x *DeleteConnectorReq) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[26] + mi := &file_api_v2_api_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1431,7 +1496,7 @@ func (x *DeleteConnectorReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteConnectorReq.ProtoReflect.Descriptor instead. func (*DeleteConnectorReq) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{26} + return file_api_v2_api_proto_rawDescGZIP(), []int{27} } func (x *DeleteConnectorReq) GetId() string { @@ -1451,7 +1516,7 @@ type DeleteConnectorResp struct { func (x *DeleteConnectorResp) Reset() { *x = DeleteConnectorResp{} - mi := &file_api_v2_api_proto_msgTypes[27] + mi := &file_api_v2_api_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1463,7 +1528,7 @@ func (x *DeleteConnectorResp) String() string { func (*DeleteConnectorResp) ProtoMessage() {} func (x *DeleteConnectorResp) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[27] + mi := &file_api_v2_api_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1476,7 +1541,7 @@ func (x *DeleteConnectorResp) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteConnectorResp.ProtoReflect.Descriptor instead. func (*DeleteConnectorResp) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{27} + return file_api_v2_api_proto_rawDescGZIP(), []int{28} } func (x *DeleteConnectorResp) GetNotFound() bool { @@ -1495,7 +1560,7 @@ type ListConnectorReq struct { func (x *ListConnectorReq) Reset() { *x = ListConnectorReq{} - mi := &file_api_v2_api_proto_msgTypes[28] + mi := &file_api_v2_api_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1507,7 +1572,7 @@ func (x *ListConnectorReq) String() string { func (*ListConnectorReq) ProtoMessage() {} func (x *ListConnectorReq) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[28] + mi := &file_api_v2_api_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1520,7 +1585,7 @@ func (x *ListConnectorReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ListConnectorReq.ProtoReflect.Descriptor instead. func (*ListConnectorReq) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{28} + return file_api_v2_api_proto_rawDescGZIP(), []int{29} } // ListConnectorResp returns a list of connectors. @@ -1533,7 +1598,7 @@ type ListConnectorResp struct { func (x *ListConnectorResp) Reset() { *x = ListConnectorResp{} - mi := &file_api_v2_api_proto_msgTypes[29] + mi := &file_api_v2_api_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1545,7 +1610,7 @@ func (x *ListConnectorResp) String() string { func (*ListConnectorResp) ProtoMessage() {} func (x *ListConnectorResp) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[29] + mi := &file_api_v2_api_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1558,7 +1623,7 @@ func (x *ListConnectorResp) ProtoReflect() protoreflect.Message { // Deprecated: Use ListConnectorResp.ProtoReflect.Descriptor instead. func (*ListConnectorResp) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{29} + return file_api_v2_api_proto_rawDescGZIP(), []int{30} } func (x *ListConnectorResp) GetConnectors() []*Connector { @@ -1577,7 +1642,7 @@ type VersionReq struct { func (x *VersionReq) Reset() { *x = VersionReq{} - mi := &file_api_v2_api_proto_msgTypes[30] + mi := &file_api_v2_api_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1589,7 +1654,7 @@ func (x *VersionReq) String() string { func (*VersionReq) ProtoMessage() {} func (x *VersionReq) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[30] + mi := &file_api_v2_api_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1602,7 +1667,7 @@ func (x *VersionReq) ProtoReflect() protoreflect.Message { // Deprecated: Use VersionReq.ProtoReflect.Descriptor instead. func (*VersionReq) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{30} + return file_api_v2_api_proto_rawDescGZIP(), []int{31} } // VersionResp holds the version info of components. @@ -1619,7 +1684,7 @@ type VersionResp struct { func (x *VersionResp) Reset() { *x = VersionResp{} - mi := &file_api_v2_api_proto_msgTypes[31] + mi := &file_api_v2_api_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1631,7 +1696,7 @@ func (x *VersionResp) String() string { func (*VersionResp) ProtoMessage() {} func (x *VersionResp) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[31] + mi := &file_api_v2_api_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1644,7 +1709,7 @@ func (x *VersionResp) ProtoReflect() protoreflect.Message { // Deprecated: Use VersionResp.ProtoReflect.Descriptor instead. func (*VersionResp) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{31} + return file_api_v2_api_proto_rawDescGZIP(), []int{32} } func (x *VersionResp) GetServer() string { @@ -1670,7 +1735,7 @@ type DiscoveryReq struct { func (x *DiscoveryReq) Reset() { *x = DiscoveryReq{} - mi := &file_api_v2_api_proto_msgTypes[32] + mi := &file_api_v2_api_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1682,7 +1747,7 @@ func (x *DiscoveryReq) String() string { func (*DiscoveryReq) ProtoMessage() {} func (x *DiscoveryReq) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[32] + mi := &file_api_v2_api_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1695,7 +1760,7 @@ func (x *DiscoveryReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DiscoveryReq.ProtoReflect.Descriptor instead. func (*DiscoveryReq) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{32} + return file_api_v2_api_proto_rawDescGZIP(), []int{33} } // DiscoverResp holds the version oidc disovery info. @@ -1722,7 +1787,7 @@ type DiscoveryResp struct { func (x *DiscoveryResp) Reset() { *x = DiscoveryResp{} - mi := &file_api_v2_api_proto_msgTypes[33] + mi := &file_api_v2_api_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1734,7 +1799,7 @@ func (x *DiscoveryResp) String() string { func (*DiscoveryResp) ProtoMessage() {} func (x *DiscoveryResp) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[33] + mi := &file_api_v2_api_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1747,7 +1812,7 @@ func (x *DiscoveryResp) ProtoReflect() protoreflect.Message { // Deprecated: Use DiscoveryResp.ProtoReflect.Descriptor instead. func (*DiscoveryResp) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{33} + return file_api_v2_api_proto_rawDescGZIP(), []int{34} } func (x *DiscoveryResp) GetIssuer() string { @@ -1869,7 +1934,7 @@ type RefreshTokenRef struct { func (x *RefreshTokenRef) Reset() { *x = RefreshTokenRef{} - mi := &file_api_v2_api_proto_msgTypes[34] + mi := &file_api_v2_api_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1881,7 +1946,7 @@ func (x *RefreshTokenRef) String() string { func (*RefreshTokenRef) ProtoMessage() {} func (x *RefreshTokenRef) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[34] + mi := &file_api_v2_api_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1894,7 +1959,7 @@ func (x *RefreshTokenRef) ProtoReflect() protoreflect.Message { // Deprecated: Use RefreshTokenRef.ProtoReflect.Descriptor instead. func (*RefreshTokenRef) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{34} + return file_api_v2_api_proto_rawDescGZIP(), []int{35} } func (x *RefreshTokenRef) GetId() string { @@ -1936,7 +2001,7 @@ type ListRefreshReq struct { func (x *ListRefreshReq) Reset() { *x = ListRefreshReq{} - mi := &file_api_v2_api_proto_msgTypes[35] + mi := &file_api_v2_api_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1948,7 +2013,7 @@ func (x *ListRefreshReq) String() string { func (*ListRefreshReq) ProtoMessage() {} func (x *ListRefreshReq) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[35] + mi := &file_api_v2_api_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1961,7 +2026,7 @@ func (x *ListRefreshReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRefreshReq.ProtoReflect.Descriptor instead. func (*ListRefreshReq) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{35} + return file_api_v2_api_proto_rawDescGZIP(), []int{36} } func (x *ListRefreshReq) GetUserId() string { @@ -1981,7 +2046,7 @@ type ListRefreshResp struct { func (x *ListRefreshResp) Reset() { *x = ListRefreshResp{} - mi := &file_api_v2_api_proto_msgTypes[36] + mi := &file_api_v2_api_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1993,7 +2058,7 @@ func (x *ListRefreshResp) String() string { func (*ListRefreshResp) ProtoMessage() {} func (x *ListRefreshResp) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[36] + mi := &file_api_v2_api_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2006,7 +2071,7 @@ func (x *ListRefreshResp) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRefreshResp.ProtoReflect.Descriptor instead. func (*ListRefreshResp) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{36} + return file_api_v2_api_proto_rawDescGZIP(), []int{37} } func (x *ListRefreshResp) GetRefreshTokens() []*RefreshTokenRef { @@ -2028,7 +2093,7 @@ type RevokeRefreshReq struct { func (x *RevokeRefreshReq) Reset() { *x = RevokeRefreshReq{} - mi := &file_api_v2_api_proto_msgTypes[37] + mi := &file_api_v2_api_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2040,7 +2105,7 @@ func (x *RevokeRefreshReq) String() string { func (*RevokeRefreshReq) ProtoMessage() {} func (x *RevokeRefreshReq) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[37] + mi := &file_api_v2_api_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2053,7 +2118,7 @@ func (x *RevokeRefreshReq) ProtoReflect() protoreflect.Message { // Deprecated: Use RevokeRefreshReq.ProtoReflect.Descriptor instead. func (*RevokeRefreshReq) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{37} + return file_api_v2_api_proto_rawDescGZIP(), []int{38} } func (x *RevokeRefreshReq) GetUserId() string { @@ -2081,7 +2146,7 @@ type RevokeRefreshResp struct { func (x *RevokeRefreshResp) Reset() { *x = RevokeRefreshResp{} - mi := &file_api_v2_api_proto_msgTypes[38] + mi := &file_api_v2_api_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2093,7 +2158,7 @@ func (x *RevokeRefreshResp) String() string { func (*RevokeRefreshResp) ProtoMessage() {} func (x *RevokeRefreshResp) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[38] + mi := &file_api_v2_api_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2106,7 +2171,7 @@ func (x *RevokeRefreshResp) ProtoReflect() protoreflect.Message { // Deprecated: Use RevokeRefreshResp.ProtoReflect.Descriptor instead. func (*RevokeRefreshResp) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{38} + return file_api_v2_api_proto_rawDescGZIP(), []int{39} } func (x *RevokeRefreshResp) GetNotFound() bool { @@ -2126,7 +2191,7 @@ type VerifyPasswordReq struct { func (x *VerifyPasswordReq) Reset() { *x = VerifyPasswordReq{} - mi := &file_api_v2_api_proto_msgTypes[39] + mi := &file_api_v2_api_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2138,7 +2203,7 @@ func (x *VerifyPasswordReq) String() string { func (*VerifyPasswordReq) ProtoMessage() {} func (x *VerifyPasswordReq) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[39] + mi := &file_api_v2_api_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2151,7 +2216,7 @@ func (x *VerifyPasswordReq) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyPasswordReq.ProtoReflect.Descriptor instead. func (*VerifyPasswordReq) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{39} + return file_api_v2_api_proto_rawDescGZIP(), []int{40} } func (x *VerifyPasswordReq) GetEmail() string { @@ -2178,7 +2243,7 @@ type VerifyPasswordResp struct { func (x *VerifyPasswordResp) Reset() { *x = VerifyPasswordResp{} - mi := &file_api_v2_api_proto_msgTypes[40] + mi := &file_api_v2_api_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2190,7 +2255,7 @@ func (x *VerifyPasswordResp) String() string { func (*VerifyPasswordResp) ProtoMessage() {} func (x *VerifyPasswordResp) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_api_proto_msgTypes[40] + mi := &file_api_v2_api_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2203,7 +2268,7 @@ func (x *VerifyPasswordResp) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyPasswordResp.ProtoReflect.Descriptor instead. func (*VerifyPasswordResp) Descriptor() ([]byte, []int) { - return file_api_v2_api_proto_rawDescGZIP(), []int{40} + return file_api_v2_api_proto_rawDescGZIP(), []int{41} } func (x *VerifyPasswordResp) GetVerified() bool { @@ -2321,209 +2386,217 @@ var file_api_v2_api_proto_rawDesc = string([]byte{ 0x73, 0x70, 0x12, 0x2b, 0x0a, 0x09, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x09, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x22, - 0x5b, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x0e, 0x0a, 0x02, + 0x7c, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x42, 0x0a, 0x12, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, - 0x65, 0x71, 0x12, 0x2c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x22, 0x3c, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x72, 0x65, 0x61, - 0x64, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0d, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, 0x79, - 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, - 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, - 0x6e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x32, 0x0a, 0x13, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x24, 0x0a, - 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x22, 0x32, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1f, 0x0a, 0x0b, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x42, 0x0a, + 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x52, 0x65, 0x71, 0x12, 0x2c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x22, 0x3c, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x72, 0x65, + 0x61, 0x64, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0d, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22, + 0x2d, 0x0a, 0x0a, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xb2, + 0x01, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, + 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x09, 0x6e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x0a, 0x0f, 0x6e, 0x65, + 0x77, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x73, 0x52, 0x0d, 0x6e, 0x65, 0x77, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x73, 0x22, 0x32, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, - 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x12, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x22, 0x43, 0x0a, 0x11, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x2e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, - 0x22, 0x0c, 0x0a, 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x22, 0x37, - 0x0a, 0x0b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x03, 0x61, 0x70, 0x69, 0x22, 0x0e, 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x22, 0xb0, 0x06, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, - 0x75, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, - 0x72, 0x12, 0x35, 0x0a, 0x16, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x15, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, - 0x19, 0x0a, 0x08, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6a, 0x77, 0x6b, 0x73, 0x55, 0x72, 0x69, 0x12, 0x2b, 0x0a, 0x11, 0x75, 0x73, - 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x75, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x45, - 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x42, 0x0a, 0x1d, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x16, 0x69, - 0x6e, 0x74, 0x72, 0x6f, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x69, 0x6e, 0x74, - 0x72, 0x6f, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x13, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x53, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, - 0x12, 0x36, 0x0a, 0x17, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x15, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x53, - 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x4f, 0x0a, 0x25, 0x69, 0x64, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x20, 0x69, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x20, 0x63, 0x6f, 0x64, - 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0c, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x1d, 0x63, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, - 0x67, 0x65, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, - 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x5f, 0x73, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x63, - 0x6f, 0x70, 0x65, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x50, 0x0a, - 0x25, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, - 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x5f, 0x73, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x21, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, - 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x69, 0x6d, - 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x22, 0x7a, 0x0a, 0x0f, 0x52, 0x65, - 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, - 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x73, - 0x74, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, - 0x73, 0x74, 0x55, 0x73, 0x65, 0x64, 0x22, 0x29, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, - 0x64, 0x22, 0x4e, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x12, 0x3b, 0x0a, 0x0e, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, - 0x65, 0x66, 0x52, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x73, 0x22, 0x48, 0x0a, 0x10, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, - 0x73, 0x68, 0x52, 0x65, 0x71, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, - 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x30, 0x0a, 0x11, 0x52, - 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x45, 0x0a, - 0x11, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, - 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x22, 0x4d, 0x0a, 0x12, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x61, - 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x65, - 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x76, 0x65, - 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x5f, 0x66, 0x6f, - 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x74, 0x46, 0x6f, - 0x75, 0x6e, 0x64, 0x32, 0x8b, 0x09, 0x0a, 0x03, 0x44, 0x65, 0x78, 0x12, 0x34, 0x0a, 0x09, 0x47, - 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, - 0x00, 0x12, 0x3d, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, - 0x12, 0x3d, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, - 0x3d, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, - 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x38, - 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x12, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, - 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, - 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x43, 0x0a, - 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, - 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x24, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x32, 0x0a, + 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x5f, 0x66, 0x6f, 0x75, 0x6e, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, + 0x64, 0x22, 0x12, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x71, 0x22, 0x43, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2e, 0x0a, 0x0a, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x0a, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x0c, 0x0a, 0x0a, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x22, 0x37, 0x0a, 0x0b, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, + 0x10, 0x0a, 0x03, 0x61, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x61, 0x70, + 0x69, 0x22, 0x0e, 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, 0x65, + 0x71, 0x22, 0xb0, 0x06, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x16, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6a, 0x77, 0x6b, + 0x73, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6a, 0x77, 0x6b, + 0x73, 0x55, 0x72, 0x69, 0x12, 0x2b, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, + 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x10, 0x75, 0x73, 0x65, 0x72, 0x69, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x42, 0x0a, 0x1d, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x16, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x73, 0x70, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x12, 0x38, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x16, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x12, 0x4f, 0x0a, 0x25, 0x69, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x20, 0x69, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, + 0x67, 0x41, 0x6c, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, + 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x5f, 0x73, 0x75, + 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x1d, 0x63, + 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, + 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x53, 0x75, + 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x50, 0x0a, 0x25, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x21, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, + 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6c, 0x61, + 0x69, 0x6d, 0x73, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x18, 0x0f, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, + 0x72, 0x74, 0x65, 0x64, 0x22, 0x7a, 0x0a, 0x0f, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x66, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x73, 0x65, 0x64, + 0x22, 0x29, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, + 0x65, 0x71, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x4e, 0x0a, 0x0f, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3b, + 0x0a, 0x0e, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x66, + 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x66, 0x52, 0x0d, 0x72, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0x48, 0x0a, 0x10, 0x52, + 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x12, + 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x30, 0x0a, 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, + 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, + 0x74, 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, + 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x45, 0x0a, 0x11, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, + 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, + 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x4d, + 0x0a, 0x12, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x6e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x32, 0x8b, 0x09, + 0x0a, 0x03, 0x44, 0x65, 0x78, 0x12, 0x34, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x12, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0c, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0c, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0c, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, + 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x15, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, - 0x46, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, - 0x41, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x73, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x22, 0x00, 0x12, 0x31, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x1a, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x12, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3a, - 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x13, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, - 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x66, - 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0d, 0x52, 0x65, - 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x15, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, - 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x65, 0x72, - 0x69, 0x66, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, - 0x00, 0x42, 0x36, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x6f, 0x73, 0x2e, - 0x64, 0x65, 0x78, 0x2e, 0x61, 0x70, 0x69, 0x5a, 0x20, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, 0x78, 0x69, 0x64, 0x70, 0x2f, 0x64, 0x65, 0x78, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, + 0x71, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, + 0x00, 0x12, 0x3e, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x73, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, + 0x00, 0x12, 0x46, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x0f, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x17, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, + 0x00, 0x12, 0x46, 0x0a, 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0e, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x15, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x0a, + 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0f, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x10, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, + 0x37, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x12, + 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x52, + 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0d, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, + 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, + 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x36, 0x0a, 0x12, 0x63, + 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x6f, 0x73, 0x2e, 0x64, 0x65, 0x78, 0x2e, 0x61, 0x70, + 0x69, 0x5a, 0x20, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, + 0x78, 0x69, 0x64, 0x70, 0x2f, 0x64, 0x65, 0x78, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, + 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -2538,7 +2611,7 @@ func file_api_v2_api_proto_rawDescGZIP() []byte { return file_api_v2_api_proto_rawDescData } -var file_api_v2_api_proto_msgTypes = make([]protoimpl.MessageInfo, 41) +var file_api_v2_api_proto_msgTypes = make([]protoimpl.MessageInfo, 42) var file_api_v2_api_proto_goTypes = []any{ (*Client)(nil), // 0: api.Client (*ClientInfo)(nil), // 1: api.ClientInfo @@ -2564,23 +2637,24 @@ var file_api_v2_api_proto_goTypes = []any{ (*Connector)(nil), // 21: api.Connector (*CreateConnectorReq)(nil), // 22: api.CreateConnectorReq (*CreateConnectorResp)(nil), // 23: api.CreateConnectorResp - (*UpdateConnectorReq)(nil), // 24: api.UpdateConnectorReq - (*UpdateConnectorResp)(nil), // 25: api.UpdateConnectorResp - (*DeleteConnectorReq)(nil), // 26: api.DeleteConnectorReq - (*DeleteConnectorResp)(nil), // 27: api.DeleteConnectorResp - (*ListConnectorReq)(nil), // 28: api.ListConnectorReq - (*ListConnectorResp)(nil), // 29: api.ListConnectorResp - (*VersionReq)(nil), // 30: api.VersionReq - (*VersionResp)(nil), // 31: api.VersionResp - (*DiscoveryReq)(nil), // 32: api.DiscoveryReq - (*DiscoveryResp)(nil), // 33: api.DiscoveryResp - (*RefreshTokenRef)(nil), // 34: api.RefreshTokenRef - (*ListRefreshReq)(nil), // 35: api.ListRefreshReq - (*ListRefreshResp)(nil), // 36: api.ListRefreshResp - (*RevokeRefreshReq)(nil), // 37: api.RevokeRefreshReq - (*RevokeRefreshResp)(nil), // 38: api.RevokeRefreshResp - (*VerifyPasswordReq)(nil), // 39: api.VerifyPasswordReq - (*VerifyPasswordResp)(nil), // 40: api.VerifyPasswordResp + (*GrantTypes)(nil), // 24: api.GrantTypes + (*UpdateConnectorReq)(nil), // 25: api.UpdateConnectorReq + (*UpdateConnectorResp)(nil), // 26: api.UpdateConnectorResp + (*DeleteConnectorReq)(nil), // 27: api.DeleteConnectorReq + (*DeleteConnectorResp)(nil), // 28: api.DeleteConnectorResp + (*ListConnectorReq)(nil), // 29: api.ListConnectorReq + (*ListConnectorResp)(nil), // 30: api.ListConnectorResp + (*VersionReq)(nil), // 31: api.VersionReq + (*VersionResp)(nil), // 32: api.VersionResp + (*DiscoveryReq)(nil), // 33: api.DiscoveryReq + (*DiscoveryResp)(nil), // 34: api.DiscoveryResp + (*RefreshTokenRef)(nil), // 35: api.RefreshTokenRef + (*ListRefreshReq)(nil), // 36: api.ListRefreshReq + (*ListRefreshResp)(nil), // 37: api.ListRefreshResp + (*RevokeRefreshReq)(nil), // 38: api.RevokeRefreshReq + (*RevokeRefreshResp)(nil), // 39: api.RevokeRefreshResp + (*VerifyPasswordReq)(nil), // 40: api.VerifyPasswordReq + (*VerifyPasswordResp)(nil), // 41: api.VerifyPasswordResp } var file_api_v2_api_proto_depIdxs = []int32{ 0, // 0: api.GetClientResp.client:type_name -> api.Client @@ -2590,49 +2664,50 @@ var file_api_v2_api_proto_depIdxs = []int32{ 12, // 4: api.CreatePasswordReq.password:type_name -> api.Password 12, // 5: api.ListPasswordResp.passwords:type_name -> api.Password 21, // 6: api.CreateConnectorReq.connector:type_name -> api.Connector - 21, // 7: api.ListConnectorResp.connectors:type_name -> api.Connector - 34, // 8: api.ListRefreshResp.refresh_tokens:type_name -> api.RefreshTokenRef - 2, // 9: api.Dex.GetClient:input_type -> api.GetClientReq - 4, // 10: api.Dex.CreateClient:input_type -> api.CreateClientReq - 8, // 11: api.Dex.UpdateClient:input_type -> api.UpdateClientReq - 6, // 12: api.Dex.DeleteClient:input_type -> api.DeleteClientReq - 10, // 13: api.Dex.ListClients:input_type -> api.ListClientReq - 13, // 14: api.Dex.CreatePassword:input_type -> api.CreatePasswordReq - 15, // 15: api.Dex.UpdatePassword:input_type -> api.UpdatePasswordReq - 17, // 16: api.Dex.DeletePassword:input_type -> api.DeletePasswordReq - 19, // 17: api.Dex.ListPasswords:input_type -> api.ListPasswordReq - 22, // 18: api.Dex.CreateConnector:input_type -> api.CreateConnectorReq - 24, // 19: api.Dex.UpdateConnector:input_type -> api.UpdateConnectorReq - 26, // 20: api.Dex.DeleteConnector:input_type -> api.DeleteConnectorReq - 28, // 21: api.Dex.ListConnectors:input_type -> api.ListConnectorReq - 30, // 22: api.Dex.GetVersion:input_type -> api.VersionReq - 32, // 23: api.Dex.GetDiscovery:input_type -> api.DiscoveryReq - 35, // 24: api.Dex.ListRefresh:input_type -> api.ListRefreshReq - 37, // 25: api.Dex.RevokeRefresh:input_type -> api.RevokeRefreshReq - 39, // 26: api.Dex.VerifyPassword:input_type -> api.VerifyPasswordReq - 3, // 27: api.Dex.GetClient:output_type -> api.GetClientResp - 5, // 28: api.Dex.CreateClient:output_type -> api.CreateClientResp - 9, // 29: api.Dex.UpdateClient:output_type -> api.UpdateClientResp - 7, // 30: api.Dex.DeleteClient:output_type -> api.DeleteClientResp - 11, // 31: api.Dex.ListClients:output_type -> api.ListClientResp - 14, // 32: api.Dex.CreatePassword:output_type -> api.CreatePasswordResp - 16, // 33: api.Dex.UpdatePassword:output_type -> api.UpdatePasswordResp - 18, // 34: api.Dex.DeletePassword:output_type -> api.DeletePasswordResp - 20, // 35: api.Dex.ListPasswords:output_type -> api.ListPasswordResp - 23, // 36: api.Dex.CreateConnector:output_type -> api.CreateConnectorResp - 25, // 37: api.Dex.UpdateConnector:output_type -> api.UpdateConnectorResp - 27, // 38: api.Dex.DeleteConnector:output_type -> api.DeleteConnectorResp - 29, // 39: api.Dex.ListConnectors:output_type -> api.ListConnectorResp - 31, // 40: api.Dex.GetVersion:output_type -> api.VersionResp - 33, // 41: api.Dex.GetDiscovery:output_type -> api.DiscoveryResp - 36, // 42: api.Dex.ListRefresh:output_type -> api.ListRefreshResp - 38, // 43: api.Dex.RevokeRefresh:output_type -> api.RevokeRefreshResp - 40, // 44: api.Dex.VerifyPassword:output_type -> api.VerifyPasswordResp - 27, // [27:45] is the sub-list for method output_type - 9, // [9:27] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 24, // 7: api.UpdateConnectorReq.new_grant_types:type_name -> api.GrantTypes + 21, // 8: api.ListConnectorResp.connectors:type_name -> api.Connector + 35, // 9: api.ListRefreshResp.refresh_tokens:type_name -> api.RefreshTokenRef + 2, // 10: api.Dex.GetClient:input_type -> api.GetClientReq + 4, // 11: api.Dex.CreateClient:input_type -> api.CreateClientReq + 8, // 12: api.Dex.UpdateClient:input_type -> api.UpdateClientReq + 6, // 13: api.Dex.DeleteClient:input_type -> api.DeleteClientReq + 10, // 14: api.Dex.ListClients:input_type -> api.ListClientReq + 13, // 15: api.Dex.CreatePassword:input_type -> api.CreatePasswordReq + 15, // 16: api.Dex.UpdatePassword:input_type -> api.UpdatePasswordReq + 17, // 17: api.Dex.DeletePassword:input_type -> api.DeletePasswordReq + 19, // 18: api.Dex.ListPasswords:input_type -> api.ListPasswordReq + 22, // 19: api.Dex.CreateConnector:input_type -> api.CreateConnectorReq + 25, // 20: api.Dex.UpdateConnector:input_type -> api.UpdateConnectorReq + 27, // 21: api.Dex.DeleteConnector:input_type -> api.DeleteConnectorReq + 29, // 22: api.Dex.ListConnectors:input_type -> api.ListConnectorReq + 31, // 23: api.Dex.GetVersion:input_type -> api.VersionReq + 33, // 24: api.Dex.GetDiscovery:input_type -> api.DiscoveryReq + 36, // 25: api.Dex.ListRefresh:input_type -> api.ListRefreshReq + 38, // 26: api.Dex.RevokeRefresh:input_type -> api.RevokeRefreshReq + 40, // 27: api.Dex.VerifyPassword:input_type -> api.VerifyPasswordReq + 3, // 28: api.Dex.GetClient:output_type -> api.GetClientResp + 5, // 29: api.Dex.CreateClient:output_type -> api.CreateClientResp + 9, // 30: api.Dex.UpdateClient:output_type -> api.UpdateClientResp + 7, // 31: api.Dex.DeleteClient:output_type -> api.DeleteClientResp + 11, // 32: api.Dex.ListClients:output_type -> api.ListClientResp + 14, // 33: api.Dex.CreatePassword:output_type -> api.CreatePasswordResp + 16, // 34: api.Dex.UpdatePassword:output_type -> api.UpdatePasswordResp + 18, // 35: api.Dex.DeletePassword:output_type -> api.DeletePasswordResp + 20, // 36: api.Dex.ListPasswords:output_type -> api.ListPasswordResp + 23, // 37: api.Dex.CreateConnector:output_type -> api.CreateConnectorResp + 26, // 38: api.Dex.UpdateConnector:output_type -> api.UpdateConnectorResp + 28, // 39: api.Dex.DeleteConnector:output_type -> api.DeleteConnectorResp + 30, // 40: api.Dex.ListConnectors:output_type -> api.ListConnectorResp + 32, // 41: api.Dex.GetVersion:output_type -> api.VersionResp + 34, // 42: api.Dex.GetDiscovery:output_type -> api.DiscoveryResp + 37, // 43: api.Dex.ListRefresh:output_type -> api.ListRefreshResp + 39, // 44: api.Dex.RevokeRefresh:output_type -> api.RevokeRefreshResp + 41, // 45: api.Dex.VerifyPassword:output_type -> api.VerifyPasswordResp + 28, // [28:46] is the sub-list for method output_type + 10, // [10:28] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_api_v2_api_proto_init() } @@ -2646,7 +2721,7 @@ func file_api_v2_api_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v2_api_proto_rawDesc), len(file_api_v2_api_proto_rawDesc)), NumEnums: 0, - NumMessages: 41, + NumMessages: 42, NumExtensions: 0, NumServices: 1, }, diff --git a/api/v2/api.proto b/api/v2/api.proto index fc14913b..51d6d292 100644 --- a/api/v2/api.proto +++ b/api/v2/api.proto @@ -140,6 +140,7 @@ message Connector { string type = 2; string name = 3; bytes config = 4; + repeated string grant_types = 5; } // CreateConnectorReq is a request to make a connector. @@ -152,6 +153,12 @@ message CreateConnectorResp { bool already_exists = 1; } +// GrantTypes wraps a list of grant types to distinguish between +// "not specified" (no update) and "empty list" (unrestricted). +message GrantTypes { + repeated string grant_types = 1; +} + // UpdateConnectorReq is a request to modify an existing connector. message UpdateConnectorReq { // The id used to lookup the connector. This field cannot be modified @@ -159,6 +166,10 @@ message UpdateConnectorReq { string new_type = 2; string new_name = 3; bytes new_config = 4; + // If set, updates the connector's allowed grant types. + // An empty grant_types list means unrestricted (all grant types allowed). + // If not set (null), grant types are not modified. + GrantTypes new_grant_types = 5; } // UpdateConnectorResp returns the response from modifying an existing connector. diff --git a/cmd/dex/config.go b/cmd/dex/config.go index 8f78eea2..a05c3efd 100644 --- a/cmd/dex/config.go +++ b/cmd/dex/config.go @@ -459,7 +459,8 @@ type Connector struct { Name string `json:"name"` ID string `json:"id"` - Config server.ConnectorConfig `json:"config"` + Config server.ConnectorConfig `json:"config"` + GrantTypes []string `json:"grantTypes"` } // UnmarshalJSON allows Connector to implement the unmarshaler interface to @@ -470,7 +471,8 @@ func (c *Connector) UnmarshalJSON(b []byte) error { Name string `json:"name"` ID string `json:"id"` - Config json.RawMessage `json:"config"` + Config json.RawMessage `json:"config"` + GrantTypes []string `json:"grantTypes"` } if err := configUnmarshaller(b, &conn); err != nil { return fmt.Errorf("parse connector: %v", err) @@ -508,10 +510,11 @@ func (c *Connector) UnmarshalJSON(b []byte) error { } *c = Connector{ - Type: conn.Type, - Name: conn.Name, - ID: conn.ID, - Config: connConfig, + Type: conn.Type, + Name: conn.Name, + ID: conn.ID, + Config: connConfig, + GrantTypes: conn.GrantTypes, } return nil } @@ -524,10 +527,11 @@ func ToStorageConnector(c Connector) (storage.Connector, error) { } return storage.Connector{ - ID: c.ID, - Type: c.Type, - Name: c.Name, - Config: data, + ID: c.ID, + Type: c.Type, + Name: c.Name, + Config: data, + GrantTypes: c.GrantTypes, }, nil } diff --git a/cmd/dex/config_test.go b/cmd/dex/config_test.go index 1edca7cf..26385f56 100644 --- a/cmd/dex/config_test.go +++ b/cmd/dex/config_test.go @@ -107,6 +107,9 @@ connectors: - type: mockCallback id: mock name: Example + grantTypes: + - authorization_code + - "urn:ietf:params:oauth:grant-type:token-exchange" - type: oidc id: google name: Google @@ -202,6 +205,10 @@ additionalFeatures: [ ID: "mock", Name: "Example", Config: &mock.CallbackConfig{}, + GrantTypes: []string{ + "authorization_code", + "urn:ietf:params:oauth:grant-type:token-exchange", + }, }, { Type: "oidc", diff --git a/cmd/dex/serve.go b/cmd/dex/serve.go index 545419dc..cb675869 100644 --- a/cmd/dex/serve.go +++ b/cmd/dex/serve.go @@ -255,6 +255,11 @@ func runServe(options serveOptions) error { if c.Config == nil { return fmt.Errorf("invalid config: no config field for connector %q", c.ID) } + for _, gt := range c.GrantTypes { + if !server.ConnectorGrantTypes[gt] { + return fmt.Errorf("invalid config: unknown grant type %q for connector %q", gt, c.ID) + } + } logger.Info("config connector", "connector_id", c.ID) // convert to a storage connector object diff --git a/examples/config-dev.yaml b/examples/config-dev.yaml index 9c25b735..840905de 100644 --- a/examples/config-dev.yaml +++ b/examples/config-dev.yaml @@ -100,7 +100,7 @@ telemetry: # format: "text" # can also be "json" # Default values shown below -#oauth2: +# oauth2: # grantTypes determines the allowed set of authorization flows. # grantTypes: # - "authorization_code" @@ -151,6 +151,18 @@ connectors: - type: mockCallback id: mock name: Example + # grantTypes restricts which grant types can use this connector. + # If not specified, all grant types are allowed. + # Supported values: + # - "authorization_code" + # - "implicit" + # - "refresh_token" + # - "password" + # - "urn:ietf:params:oauth:grant-type:device_code" + # - "urn:ietf:params:oauth:grant-type:token-exchange" +# grantTypes: +# - "authorization_code" +# - "refresh_token" # - type: google # id: google # name: Google diff --git a/server/api.go b/server/api.go index 202fef36..8ade8a05 100644 --- a/server/api.go +++ b/server/api.go @@ -455,12 +455,19 @@ func (d dexAPI) CreateConnector(ctx context.Context, req *api.CreateConnectorReq return nil, errors.New("invalid config supplied") } + for _, gt := range req.Connector.GrantTypes { + if !ConnectorGrantTypes[gt] { + return nil, fmt.Errorf("unknown grant type %q", gt) + } + } + c := storage.Connector{ ID: req.Connector.Id, Name: req.Connector.Name, Type: req.Connector.Type, ResourceVersion: "1", Config: req.Connector.Config, + GrantTypes: req.Connector.GrantTypes, } if err := d.s.CreateConnector(ctx, c); err != nil { if err == storage.ErrAlreadyExists { @@ -487,14 +494,26 @@ func (d dexAPI) UpdateConnector(ctx context.Context, req *api.UpdateConnectorReq return nil, errors.New("no email supplied") } - if len(req.NewConfig) == 0 && req.NewName == "" && req.NewType == "" { + hasUpdate := len(req.NewConfig) != 0 || + req.NewName != "" || + req.NewType != "" || + req.NewGrantTypes != nil + if !hasUpdate { return nil, errors.New("nothing to update") } - if !json.Valid(req.NewConfig) { + if len(req.NewConfig) != 0 && !json.Valid(req.NewConfig) { return nil, errors.New("invalid config supplied") } + if req.NewGrantTypes != nil { + for _, gt := range req.NewGrantTypes.GrantTypes { + if !ConnectorGrantTypes[gt] { + return nil, fmt.Errorf("unknown grant type %q", gt) + } + } + } + updater := func(old storage.Connector) (storage.Connector, error) { if req.NewType != "" { old.Type = req.NewType @@ -508,6 +527,10 @@ func (d dexAPI) UpdateConnector(ctx context.Context, req *api.UpdateConnectorReq old.Config = req.NewConfig } + if req.NewGrantTypes != nil { + old.GrantTypes = req.NewGrantTypes.GrantTypes + } + if rev, err := strconv.Atoi(defaultTo(old.ResourceVersion, "0")); err == nil { old.ResourceVersion = strconv.Itoa(rev + 1) } @@ -561,10 +584,11 @@ func (d dexAPI) ListConnectors(ctx context.Context, req *api.ListConnectorReq) ( connectors := make([]*api.Connector, 0, len(connectorList)) for _, connector := range connectorList { c := api.Connector{ - Id: connector.ID, - Name: connector.Name, - Type: connector.Type, - Config: connector.Config, + Id: connector.ID, + Name: connector.Name, + Type: connector.Type, + Config: connector.Config, + GrantTypes: connector.GrantTypes, } connectors = append(connectors, &c) } diff --git a/server/api_test.go b/server/api_test.go index 5ddbcc4a..09cfa678 100644 --- a/server/api_test.go +++ b/server/api_test.go @@ -606,6 +606,105 @@ func TestUpdateConnector(t *testing.T) { } } +func TestUpdateConnectorGrantTypes(t *testing.T) { + t.Setenv("DEX_API_CONNECTORS_CRUD", "true") + + logger := newLogger(t) + s := memory.New(logger) + + client := newAPI(t, s, logger) + defer client.Close() + + ctx := t.Context() + + connectorID := "connector-gt" + + // Create a connector without grant types + createReq := api.CreateConnectorReq{ + Connector: &api.Connector{ + Id: connectorID, + Name: "TestConnector", + Type: "TestType", + Config: []byte(`{"key": "value"}`), + }, + } + _, err := client.CreateConnector(ctx, &createReq) + if err != nil { + t.Fatalf("failed to create connector: %v", err) + } + + // Set grant types + _, err = client.UpdateConnector(ctx, &api.UpdateConnectorReq{ + Id: connectorID, + NewGrantTypes: &api.GrantTypes{GrantTypes: []string{"authorization_code", "refresh_token"}}, + }) + if err != nil { + t.Fatalf("failed to update connector grant types: %v", err) + } + + resp, err := client.ListConnectors(ctx, &api.ListConnectorReq{}) + if err != nil { + t.Fatalf("failed to list connectors: %v", err) + } + for _, c := range resp.Connectors { + if c.Id == connectorID { + if !slices.Equal(c.GrantTypes, []string{"authorization_code", "refresh_token"}) { + t.Fatalf("expected grant types [authorization_code refresh_token], got %v", c.GrantTypes) + } + } + } + + // Clear grant types by passing empty GrantTypes message + _, err = client.UpdateConnector(ctx, &api.UpdateConnectorReq{ + Id: connectorID, + NewGrantTypes: &api.GrantTypes{}, + }) + if err != nil { + t.Fatalf("failed to clear connector grant types: %v", err) + } + + resp, err = client.ListConnectors(ctx, &api.ListConnectorReq{}) + if err != nil { + t.Fatalf("failed to list connectors: %v", err) + } + for _, c := range resp.Connectors { + if c.Id == connectorID { + if len(c.GrantTypes) != 0 { + t.Fatalf("expected empty grant types after clear, got %v", c.GrantTypes) + } + } + } + + // Reject invalid grant type on update + _, err = client.UpdateConnector(ctx, &api.UpdateConnectorReq{ + Id: connectorID, + NewGrantTypes: &api.GrantTypes{GrantTypes: []string{"bogus"}}, + }) + if err == nil { + t.Fatal("expected error for invalid grant type, got nil") + } + if !strings.Contains(err.Error(), `unknown grant type "bogus"`) { + t.Fatalf("unexpected error: %v", err) + } + + // Reject invalid grant type on create + _, err = client.CreateConnector(ctx, &api.CreateConnectorReq{ + Connector: &api.Connector{ + Id: "bad-gt", + Name: "Bad", + Type: "TestType", + Config: []byte(`{}`), + GrantTypes: []string{"invalid_type"}, + }, + }) + if err == nil { + t.Fatal("expected error for invalid grant type on create, got nil") + } + if !strings.Contains(err.Error(), `unknown grant type "invalid_type"`) { + t.Fatalf("unexpected error: %v", err) + } +} + func TestDeleteConnector(t *testing.T) { t.Setenv("DEX_API_CONNECTORS_CRUD", "true") diff --git a/server/handlers.go b/server/handlers.go index 10c6688d..6a40bf96 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -142,6 +142,21 @@ func (s *Server) constructDiscovery(ctx context.Context) discovery { return d } +// grantTypeFromAuthRequest determines the grant type from the authorization request parameters. +func (s *Server) grantTypeFromAuthRequest(r *http.Request) string { + redirectURI := r.Form.Get("redirect_uri") + if redirectURI == deviceCallbackURI || strings.HasSuffix(redirectURI, deviceCallbackURI) { + return grantTypeDeviceCode + } + responseType := r.Form.Get("response_type") + for _, rt := range strings.Fields(responseType) { + if rt == "token" || rt == "id_token" { + return grantTypeImplicit + } + } + return grantTypeAuthorizationCode +} + // handleAuthorization handles the OAuth2 auth endpoint. func (s *Server) handleAuthorization(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -154,13 +169,27 @@ func (s *Server) handleAuthorization(w http.ResponseWriter, r *http.Request) { } connectorID := r.Form.Get("connector_id") - connectors, err := s.storage.ListConnectors(ctx) + allConnectors, err := s.storage.ListConnectors(ctx) if err != nil { s.logger.ErrorContext(r.Context(), "failed to get list of connectors", "err", err) s.renderError(r, w, http.StatusInternalServerError, "Failed to retrieve connector list.") return } + // Determine the grant type from the authorization request to filter connectors. + grantType := s.grantTypeFromAuthRequest(r) + connectors := make([]storage.Connector, 0, len(allConnectors)) + for _, c := range allConnectors { + if GrantTypeAllowed(c.GrantTypes, grantType) { + connectors = append(connectors, c) + } + } + + if len(connectors) == 0 { + s.renderError(r, w, http.StatusBadRequest, "No connectors available for the requested grant type.") + return + } + // We don't need connector_id any more r.Form.Del("connector_id") @@ -187,15 +216,15 @@ func (s *Server) handleAuthorization(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, connURL.String(), http.StatusFound) } - connectorInfos := make([]connectorInfo, len(connectors)) - for index, conn := range connectors { + connectorInfos := make([]connectorInfo, 0, len(connectors)) + for _, conn := range connectors { connURL.Path = s.absPath("/auth", url.PathEscape(conn.ID)) - connectorInfos[index] = connectorInfo{ + connectorInfos = append(connectorInfos, connectorInfo{ ID: conn.ID, Name: conn.Name, Type: conn.Type, URL: template.URL(connURL.String()), - } + }) } if err := s.templates.login(r, w, connectorInfos); err != nil { @@ -235,6 +264,15 @@ func (s *Server) handleConnectorLogin(w http.ResponseWriter, r *http.Request) { return } + // Check if the connector allows the requested grant type. + grantType := s.grantTypeFromAuthRequest(r) + if !GrantTypeAllowed(conn.GrantTypes, grantType) { + s.logger.ErrorContext(r.Context(), "connector does not allow requested grant type", + "connector_id", connID, "grant_type", grantType) + s.renderError(r, w, http.StatusBadRequest, "Requested connector does not support this grant type.") + return + } + // Set the connector being used for the login. if authReq.ConnectorID != "" && authReq.ConnectorID != connID { s.logger.ErrorContext(r.Context(), "mismatched connector ID in auth request", @@ -995,9 +1033,16 @@ func (s *Server) exchangeAuthCode(ctx context.Context, w http.ResponseWriter, au } reqRefresh := func() bool { - // Ensure the connector supports refresh tokens. + // Determine whether to issue a refresh token. A refresh token is only + // issued when all of the following are true: + // 1. The connector implements RefreshConnector. + // 2. The connector's grantTypes config allows refresh_token. + // 3. The client requested the offline_access scope. // - // Connectors like `saml` do not implement RefreshConnector. + // When any condition is not met, the refresh token is silently omitted + // rather than returning an error. This matches the OAuth2 spec: the + // server is never required to issue a refresh token (RFC 6749 §1.5). + // https://datatracker.ietf.org/doc/html/rfc6749#section-1.5 conn, err := s.getConnector(ctx, authCode.ConnectorID) if err != nil { s.logger.ErrorContext(ctx, "connector not found", "connector_id", authCode.ConnectorID, "err", err) @@ -1010,6 +1055,10 @@ func (s *Server) exchangeAuthCode(ctx context.Context, w http.ResponseWriter, au return false } + if !GrantTypeAllowed(conn.GrantTypes, grantTypeRefreshToken) { + return false + } + for _, scope := range authCode.Scopes { if scope == scopeOfflineAccess { return true @@ -1215,6 +1264,11 @@ func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, cli s.tokenErrHelper(w, errInvalidRequest, "Requested connector does not exist.", http.StatusBadRequest) return } + if !GrantTypeAllowed(conn.GrantTypes, grantTypePassword) { + s.logger.ErrorContext(r.Context(), "connector does not allow password grant", "connector_id", connID) + s.tokenErrHelper(w, errInvalidRequest, "Requested connector does not support password grant.", http.StatusBadRequest) + return + } passwordConnector, ok := conn.Connector.(connector.PasswordConnector) if !ok { @@ -1261,11 +1315,15 @@ func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, cli } reqRefresh := func() bool { - // Ensure the connector supports refresh tokens. - // - // Connectors like `saml` do not implement RefreshConnector. - _, ok := conn.Connector.(connector.RefreshConnector) - if !ok { + // Same logic as in exchangeAuthCode: silently omit refresh token + // when the connector doesn't support it or grantTypes forbids it. + // See RFC 6749 §1.5 — refresh tokens are never mandatory. + // https://datatracker.ietf.org/doc/html/rfc6749#section-1.5 + if _, ok := conn.Connector.(connector.RefreshConnector); !ok { + return false + } + + if !GrantTypeAllowed(conn.GrantTypes, grantTypeRefreshToken) { return false } @@ -1422,6 +1480,11 @@ func (s *Server) handleTokenExchange(w http.ResponseWriter, r *http.Request, cli s.tokenErrHelper(w, errInvalidRequest, "Requested connector does not exist.", http.StatusBadRequest) return } + if !GrantTypeAllowed(conn.GrantTypes, grantTypeTokenExchange) { + s.logger.ErrorContext(r.Context(), "connector does not allow token exchange", "connector_id", connID) + s.tokenErrHelper(w, errInvalidRequest, "Requested connector does not support token exchange.", http.StatusBadRequest) + return + } teConn, ok := conn.Connector.(connector.TokenIdentityConnector) if !ok { s.logger.ErrorContext(r.Context(), "connector doesn't implement token exchange", "connector_id", connID) diff --git a/server/handlers_test.go b/server/handlers_test.go index 14bb3da9..43343aee 100644 --- a/server/handlers_test.go +++ b/server/handlers_test.go @@ -1060,6 +1060,163 @@ func TestHandleTokenExchange(t *testing.T) { } } +func TestHandleTokenExchangeConnectorGrantTypeRestriction(t *testing.T) { + ctx := t.Context() + httpServer, s := newTestServer(t, func(c *Config) { + c.Storage.CreateClient(ctx, storage.Client{ + ID: "client_1", + Secret: "secret_1", + }) + }) + defer httpServer.Close() + + // Restrict mock connector to authorization_code only + err := s.storage.UpdateConnector(ctx, "mock", func(c storage.Connector) (storage.Connector, error) { + c.GrantTypes = []string{grantTypeAuthorizationCode} + return c, nil + }) + require.NoError(t, err) + // Clear cached connector to pick up new grant types + s.mu.Lock() + delete(s.connectors, "mock") + s.mu.Unlock() + + vals := make(url.Values) + vals.Set("grant_type", grantTypeTokenExchange) + vals.Set("connector_id", "mock") + vals.Set("scope", "openid") + vals.Set("requested_token_type", tokenTypeAccess) + vals.Set("subject_token_type", tokenTypeID) + vals.Set("subject_token", "foobar") + vals.Set("client_id", "client_1") + vals.Set("client_secret", "secret_1") + + rr := httptest.NewRecorder() + req := httptest.NewRequest(http.MethodPost, httpServer.URL+"/token", strings.NewReader(vals.Encode())) + req.Header.Set("content-type", "application/x-www-form-urlencoded") + + s.handleToken(rr, req) + + require.Equal(t, http.StatusBadRequest, rr.Code, rr.Body.String()) +} + +func TestHandleAuthorizationConnectorGrantTypeFiltering(t *testing.T) { + tests := []struct { + name string + // grantTypes per connector ID; nil means unrestricted + connectorGrantTypes map[string][]string + responseType string + wantCode int + // wantRedirectContains is checked when wantCode == 302 + wantRedirectContains string + // wantBodyContains is checked when wantCode != 302 + wantBodyContains string + }{ + { + name: "one connector filtered, redirect to remaining", + connectorGrantTypes: map[string][]string{ + "mock": {grantTypeDeviceCode}, + "mock2": nil, + }, + responseType: "code", + wantCode: http.StatusFound, + wantRedirectContains: "/auth/mock2", + }, + { + name: "all connectors filtered", + connectorGrantTypes: map[string][]string{ + "mock": {grantTypeDeviceCode}, + "mock2": {grantTypeDeviceCode}, + }, + responseType: "code", + wantCode: http.StatusBadRequest, + wantBodyContains: "No connectors available", + }, + { + name: "no restrictions, both available", + connectorGrantTypes: map[string][]string{ + "mock": nil, + "mock2": nil, + }, + responseType: "code", + wantCode: http.StatusOK, + }, + { + name: "implicit flow filters auth_code-only connector", + connectorGrantTypes: map[string][]string{ + "mock": {grantTypeAuthorizationCode}, + "mock2": nil, + }, + responseType: "token", + wantCode: http.StatusFound, + wantRedirectContains: "/auth/mock2", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + ctx := t.Context() + httpServer, s := newTestServerMultipleConnectors(t, nil) + defer httpServer.Close() + + for id, gts := range tc.connectorGrantTypes { + err := s.storage.UpdateConnector(ctx, id, func(c storage.Connector) (storage.Connector, error) { + c.GrantTypes = gts + return c, nil + }) + require.NoError(t, err) + s.mu.Lock() + delete(s.connectors, id) + s.mu.Unlock() + } + + rr := httptest.NewRecorder() + reqURL := fmt.Sprintf("%s/auth?response_type=%s&client_id=test&redirect_uri=http://example.com/callback&scope=openid", httpServer.URL, tc.responseType) + req := httptest.NewRequest(http.MethodGet, reqURL, nil) + s.handleAuthorization(rr, req) + + require.Equal(t, tc.wantCode, rr.Code) + if tc.wantRedirectContains != "" { + require.Contains(t, rr.Header().Get("Location"), tc.wantRedirectContains) + } + if tc.wantBodyContains != "" { + require.Contains(t, rr.Body.String(), tc.wantBodyContains) + } + }) + } +} + +func TestHandleConnectorLoginGrantTypeRejection(t *testing.T) { + ctx := t.Context() + httpServer, s := newTestServer(t, func(c *Config) { + c.Storage.CreateClient(ctx, storage.Client{ + ID: "test-client", + Secret: "secret", + RedirectURIs: []string{"http://example.com/callback"}, + }) + }) + defer httpServer.Close() + + // Restrict mock connector to device_code only + err := s.storage.UpdateConnector(ctx, "mock", func(c storage.Connector) (storage.Connector, error) { + c.GrantTypes = []string{grantTypeDeviceCode} + return c, nil + }) + require.NoError(t, err) + s.mu.Lock() + delete(s.connectors, "mock") + s.mu.Unlock() + + // Try to use mock connector for auth code flow via the full server router + rr := httptest.NewRecorder() + reqURL := httpServer.URL + "/auth/mock?response_type=code&client_id=test-client&redirect_uri=http://example.com/callback&scope=openid" + req := httptest.NewRequest(http.MethodGet, reqURL, nil) + s.ServeHTTP(rr, req) + + require.Equal(t, http.StatusBadRequest, rr.Code) + require.Contains(t, rr.Body.String(), "does not support this grant type") +} + func setNonEmpty(vals url.Values, key, value string) { if value != "" { vals.Set(key, value) diff --git a/server/oauth2.go b/server/oauth2.go index 8fe75475..91879761 100644 --- a/server/oauth2.go +++ b/server/oauth2.go @@ -146,6 +146,16 @@ const ( grantTypeClientCredentials = "client_credentials" ) +// ConnectorGrantTypes is the set of grant types that can be restricted per connector. +var ConnectorGrantTypes = map[string]bool{ + grantTypeAuthorizationCode: true, + grantTypeRefreshToken: true, + grantTypeImplicit: true, + grantTypePassword: true, + grantTypeDeviceCode: true, + grantTypeTokenExchange: true, +} + const ( // https://www.rfc-editor.org/rfc/rfc8693.html#section-3 tokenTypeAccess = "urn:ietf:params:oauth:token-type:access_token" diff --git a/server/refreshhandlers.go b/server/refreshhandlers.go index b47bd52c..a0807d07 100644 --- a/server/refreshhandlers.go +++ b/server/refreshhandlers.go @@ -202,6 +202,10 @@ func (s *Server) getRefreshTokenFromStorage(ctx context.Context, clientID *strin s.logger.ErrorContext(ctx, "connector not found", "connector_id", refresh.ConnectorID, "err", err) return nil, newInternalServerError() } + if !GrantTypeAllowed(refreshCtx.connector.GrantTypes, grantTypeRefreshToken) { + s.logger.ErrorContext(ctx, "connector does not allow refresh token grant", "connector_id", refresh.ConnectorID) + return nil, &refreshError{msg: errInvalidRequest, desc: "Connector does not support refresh tokens.", code: http.StatusBadRequest} + } // Get Connector Data session, err := s.storage.GetOfflineSessions(ctx, refresh.Claims.UserID, refresh.ConnectorID) diff --git a/server/server.go b/server/server.go index b7c08c64..c4f16536 100644 --- a/server/server.go +++ b/server/server.go @@ -13,6 +13,7 @@ import ( "net/url" "os" "path" + "slices" "sort" "strings" "sync" @@ -57,6 +58,13 @@ const LocalConnector = "local" type Connector struct { ResourceVersion string Connector connector.Connector + GrantTypes []string +} + +// GrantTypeAllowed checks if the given grant type is allowed for this connector. +// If no grant types are configured, all are allowed. +func GrantTypeAllowed(configuredTypes []string, grantType string) bool { + return len(configuredTypes) == 0 || slices.Contains(configuredTypes, grantType) } // Config holds the server's configuration options. @@ -739,6 +747,7 @@ func (s *Server) OpenConnector(conn storage.Connector) (Connector, error) { connector := Connector{ ResourceVersion: conn.ResourceVersion, Connector: c, + GrantTypes: conn.GrantTypes, } s.mu.Lock() s.connectors[conn.ID] = connector diff --git a/storage/conformance/conformance.go b/storage/conformance/conformance.go index b8c1b96d..eeb20cd9 100644 --- a/storage/conformance/conformance.go +++ b/storage/conformance/conformance.go @@ -630,10 +630,11 @@ func testConnectorCRUD(t *testing.T, s storage.Storage) { id1 := storage.NewID() config1 := []byte(`{"issuer": "https://accounts.google.com"}`) c1 := storage.Connector{ - ID: id1, - Type: "Default", - Name: "Default", - Config: config1, + ID: id1, + Type: "Default", + Name: "Default", + Config: config1, + GrantTypes: []string{"authorization_code", "refresh_token"}, } if err := s.CreateConnector(ctx, c1); err != nil { @@ -674,12 +675,14 @@ func testConnectorCRUD(t *testing.T, s storage.Storage) { if err := s.UpdateConnector(ctx, c1.ID, func(old storage.Connector) (storage.Connector, error) { old.Type = "oidc" + old.GrantTypes = []string{"urn:ietf:params:oauth:grant-type:token-exchange"} return old, nil }); err != nil { t.Fatalf("failed to update Connector: %v", err) } c1.Type = "oidc" + c1.GrantTypes = []string{"urn:ietf:params:oauth:grant-type:token-exchange"} getAndCompare(id1, c1) connectorList := []storage.Connector{c1, c2} diff --git a/storage/ent/client/connector.go b/storage/ent/client/connector.go index f0cff8ba..21e7aec2 100644 --- a/storage/ent/client/connector.go +++ b/storage/ent/client/connector.go @@ -14,6 +14,7 @@ func (d *Database) CreateConnector(ctx context.Context, connector storage.Connec SetType(connector.Type). SetResourceVersion(connector.ResourceVersion). SetConfig(connector.Config). + SetGrantTypes(connector.GrantTypes). Save(ctx) if err != nil { return convertDBError("create connector: %w", err) @@ -75,6 +76,7 @@ func (d *Database) UpdateConnector(ctx context.Context, id string, updater func( SetType(newConnector.Type). SetResourceVersion(newConnector.ResourceVersion). SetConfig(newConnector.Config). + SetGrantTypes(newConnector.GrantTypes). Save(ctx) if err != nil { return rollback(tx, "update connector uploading: %w", err) diff --git a/storage/ent/client/types.go b/storage/ent/client/types.go index ab8ee83f..4a0b41f0 100644 --- a/storage/ent/client/types.go +++ b/storage/ent/client/types.go @@ -88,10 +88,11 @@ func toStorageClient(c *db.OAuth2Client) storage.Client { func toStorageConnector(c *db.Connector) storage.Connector { return storage.Connector{ - ID: c.ID, - Type: c.Type, - Name: c.Name, - Config: c.Config, + ID: c.ID, + Type: c.Type, + Name: c.Name, + Config: c.Config, + GrantTypes: c.GrantTypes, } } diff --git a/storage/ent/db/connector.go b/storage/ent/db/connector.go index 2071d14e..812b45f7 100644 --- a/storage/ent/db/connector.go +++ b/storage/ent/db/connector.go @@ -3,6 +3,7 @@ package db import ( + "encoding/json" "fmt" "strings" @@ -23,7 +24,9 @@ type Connector struct { // ResourceVersion holds the value of the "resource_version" field. ResourceVersion string `json:"resource_version,omitempty"` // Config holds the value of the "config" field. - Config []byte `json:"config,omitempty"` + Config []byte `json:"config,omitempty"` + // GrantTypes holds the value of the "grant_types" field. + GrantTypes []string `json:"grant_types,omitempty"` selectValues sql.SelectValues } @@ -32,7 +35,7 @@ func (*Connector) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) for i := range columns { switch columns[i] { - case connector.FieldConfig: + case connector.FieldConfig, connector.FieldGrantTypes: values[i] = new([]byte) case connector.FieldID, connector.FieldType, connector.FieldName, connector.FieldResourceVersion: values[i] = new(sql.NullString) @@ -81,6 +84,14 @@ func (_m *Connector) assignValues(columns []string, values []any) error { } else if value != nil { _m.Config = *value } + case connector.FieldGrantTypes: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field grant_types", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &_m.GrantTypes); err != nil { + return fmt.Errorf("unmarshal field grant_types: %w", err) + } + } default: _m.selectValues.Set(columns[i], values[i]) } @@ -128,6 +139,9 @@ func (_m *Connector) String() string { builder.WriteString(", ") builder.WriteString("config=") builder.WriteString(fmt.Sprintf("%v", _m.Config)) + builder.WriteString(", ") + builder.WriteString("grant_types=") + builder.WriteString(fmt.Sprintf("%v", _m.GrantTypes)) builder.WriteByte(')') return builder.String() } diff --git a/storage/ent/db/connector/connector.go b/storage/ent/db/connector/connector.go index 996328c1..ca603f4d 100644 --- a/storage/ent/db/connector/connector.go +++ b/storage/ent/db/connector/connector.go @@ -19,6 +19,8 @@ const ( FieldResourceVersion = "resource_version" // FieldConfig holds the string denoting the config field in the database. FieldConfig = "config" + // FieldGrantTypes holds the string denoting the grant_types field in the database. + FieldGrantTypes = "grant_types" // Table holds the table name of the connector in the database. Table = "connectors" ) @@ -30,6 +32,7 @@ var Columns = []string{ FieldName, FieldResourceVersion, FieldConfig, + FieldGrantTypes, } // ValidColumn reports if the column name is valid (part of the table columns). diff --git a/storage/ent/db/connector/where.go b/storage/ent/db/connector/where.go index 39cc477f..a09bec60 100644 --- a/storage/ent/db/connector/where.go +++ b/storage/ent/db/connector/where.go @@ -317,6 +317,16 @@ func ConfigLTE(v []byte) predicate.Connector { return predicate.Connector(sql.FieldLTE(FieldConfig, v)) } +// GrantTypesIsNil applies the IsNil predicate on the "grant_types" field. +func GrantTypesIsNil() predicate.Connector { + return predicate.Connector(sql.FieldIsNull(FieldGrantTypes)) +} + +// GrantTypesNotNil applies the NotNil predicate on the "grant_types" field. +func GrantTypesNotNil() predicate.Connector { + return predicate.Connector(sql.FieldNotNull(FieldGrantTypes)) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Connector) predicate.Connector { return predicate.Connector(sql.AndPredicates(predicates...)) diff --git a/storage/ent/db/connector_create.go b/storage/ent/db/connector_create.go index 42da769e..4e9cc35b 100644 --- a/storage/ent/db/connector_create.go +++ b/storage/ent/db/connector_create.go @@ -43,6 +43,12 @@ func (_c *ConnectorCreate) SetConfig(v []byte) *ConnectorCreate { return _c } +// SetGrantTypes sets the "grant_types" field. +func (_c *ConnectorCreate) SetGrantTypes(v []string) *ConnectorCreate { + _c.mutation.SetGrantTypes(v) + return _c +} + // SetID sets the "id" field. func (_c *ConnectorCreate) SetID(v string) *ConnectorCreate { _c.mutation.SetID(v) @@ -161,6 +167,10 @@ func (_c *ConnectorCreate) createSpec() (*Connector, *sqlgraph.CreateSpec) { _spec.SetField(connector.FieldConfig, field.TypeBytes, value) _node.Config = value } + if value, ok := _c.mutation.GrantTypes(); ok { + _spec.SetField(connector.FieldGrantTypes, field.TypeJSON, value) + _node.GrantTypes = value + } return _node, _spec } diff --git a/storage/ent/db/connector_update.go b/storage/ent/db/connector_update.go index bbcfd565..d9b58d04 100644 --- a/storage/ent/db/connector_update.go +++ b/storage/ent/db/connector_update.go @@ -9,6 +9,7 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/dialect/sql/sqljson" "entgo.io/ent/schema/field" "github.com/dexidp/dex/storage/ent/db/connector" "github.com/dexidp/dex/storage/ent/db/predicate" @@ -75,6 +76,24 @@ func (_u *ConnectorUpdate) SetConfig(v []byte) *ConnectorUpdate { return _u } +// SetGrantTypes sets the "grant_types" field. +func (_u *ConnectorUpdate) SetGrantTypes(v []string) *ConnectorUpdate { + _u.mutation.SetGrantTypes(v) + return _u +} + +// AppendGrantTypes appends value to the "grant_types" field. +func (_u *ConnectorUpdate) AppendGrantTypes(v []string) *ConnectorUpdate { + _u.mutation.AppendGrantTypes(v) + return _u +} + +// ClearGrantTypes clears the value of the "grant_types" field. +func (_u *ConnectorUpdate) ClearGrantTypes() *ConnectorUpdate { + _u.mutation.ClearGrantTypes() + return _u +} + // Mutation returns the ConnectorMutation object of the builder. func (_u *ConnectorUpdate) Mutation() *ConnectorMutation { return _u.mutation @@ -146,6 +165,17 @@ func (_u *ConnectorUpdate) sqlSave(ctx context.Context) (_node int, err error) { if value, ok := _u.mutation.Config(); ok { _spec.SetField(connector.FieldConfig, field.TypeBytes, value) } + if value, ok := _u.mutation.GrantTypes(); ok { + _spec.SetField(connector.FieldGrantTypes, field.TypeJSON, value) + } + if value, ok := _u.mutation.AppendedGrantTypes(); ok { + _spec.AddModifier(func(u *sql.UpdateBuilder) { + sqljson.Append(u, connector.FieldGrantTypes, value) + }) + } + if _u.mutation.GrantTypesCleared() { + _spec.ClearField(connector.FieldGrantTypes, field.TypeJSON) + } if _node, err = sqlgraph.UpdateNodes(ctx, _u.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{connector.Label} @@ -214,6 +244,24 @@ func (_u *ConnectorUpdateOne) SetConfig(v []byte) *ConnectorUpdateOne { return _u } +// SetGrantTypes sets the "grant_types" field. +func (_u *ConnectorUpdateOne) SetGrantTypes(v []string) *ConnectorUpdateOne { + _u.mutation.SetGrantTypes(v) + return _u +} + +// AppendGrantTypes appends value to the "grant_types" field. +func (_u *ConnectorUpdateOne) AppendGrantTypes(v []string) *ConnectorUpdateOne { + _u.mutation.AppendGrantTypes(v) + return _u +} + +// ClearGrantTypes clears the value of the "grant_types" field. +func (_u *ConnectorUpdateOne) ClearGrantTypes() *ConnectorUpdateOne { + _u.mutation.ClearGrantTypes() + return _u +} + // Mutation returns the ConnectorMutation object of the builder. func (_u *ConnectorUpdateOne) Mutation() *ConnectorMutation { return _u.mutation @@ -315,6 +363,17 @@ func (_u *ConnectorUpdateOne) sqlSave(ctx context.Context) (_node *Connector, er if value, ok := _u.mutation.Config(); ok { _spec.SetField(connector.FieldConfig, field.TypeBytes, value) } + if value, ok := _u.mutation.GrantTypes(); ok { + _spec.SetField(connector.FieldGrantTypes, field.TypeJSON, value) + } + if value, ok := _u.mutation.AppendedGrantTypes(); ok { + _spec.AddModifier(func(u *sql.UpdateBuilder) { + sqljson.Append(u, connector.FieldGrantTypes, value) + }) + } + if _u.mutation.GrantTypesCleared() { + _spec.ClearField(connector.FieldGrantTypes, field.TypeJSON) + } _node = &Connector{config: _u.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/storage/ent/db/migrate/schema.go b/storage/ent/db/migrate/schema.go index b61d4697..b4a94a65 100644 --- a/storage/ent/db/migrate/schema.go +++ b/storage/ent/db/migrate/schema.go @@ -70,6 +70,7 @@ var ( {Name: "name", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "resource_version", Type: field.TypeString, Size: 2147483647, SchemaType: map[string]string{"mysql": "varchar(384)", "postgres": "text", "sqlite3": "text"}}, {Name: "config", Type: field.TypeBytes}, + {Name: "grant_types", Type: field.TypeJSON, Nullable: true}, } // ConnectorsTable holds the schema information for the "connectors" table. ConnectorsTable = &schema.Table{ diff --git a/storage/ent/db/mutation.go b/storage/ent/db/mutation.go index a5cb61d2..0b299bf8 100644 --- a/storage/ent/db/mutation.go +++ b/storage/ent/db/mutation.go @@ -2720,17 +2720,19 @@ func (m *AuthRequestMutation) ResetEdge(name string) error { // ConnectorMutation represents an operation that mutates the Connector nodes in the graph. type ConnectorMutation struct { config - op Op - typ string - id *string - _type *string - name *string - resource_version *string - _config *[]byte - clearedFields map[string]struct{} - done bool - oldValue func(context.Context) (*Connector, error) - predicates []predicate.Connector + op Op + typ string + id *string + _type *string + name *string + resource_version *string + _config *[]byte + grant_types *[]string + appendgrant_types []string + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*Connector, error) + predicates []predicate.Connector } var _ ent.Mutation = (*ConnectorMutation)(nil) @@ -2981,6 +2983,71 @@ func (m *ConnectorMutation) ResetConfig() { m._config = nil } +// SetGrantTypes sets the "grant_types" field. +func (m *ConnectorMutation) SetGrantTypes(s []string) { + m.grant_types = &s + m.appendgrant_types = nil +} + +// GrantTypes returns the value of the "grant_types" field in the mutation. +func (m *ConnectorMutation) GrantTypes() (r []string, exists bool) { + v := m.grant_types + if v == nil { + return + } + return *v, true +} + +// OldGrantTypes returns the old "grant_types" field's value of the Connector entity. +// If the Connector object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ConnectorMutation) OldGrantTypes(ctx context.Context) (v []string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldGrantTypes is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldGrantTypes requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldGrantTypes: %w", err) + } + return oldValue.GrantTypes, nil +} + +// AppendGrantTypes adds s to the "grant_types" field. +func (m *ConnectorMutation) AppendGrantTypes(s []string) { + m.appendgrant_types = append(m.appendgrant_types, s...) +} + +// AppendedGrantTypes returns the list of values that were appended to the "grant_types" field in this mutation. +func (m *ConnectorMutation) AppendedGrantTypes() ([]string, bool) { + if len(m.appendgrant_types) == 0 { + return nil, false + } + return m.appendgrant_types, true +} + +// ClearGrantTypes clears the value of the "grant_types" field. +func (m *ConnectorMutation) ClearGrantTypes() { + m.grant_types = nil + m.appendgrant_types = nil + m.clearedFields[connector.FieldGrantTypes] = struct{}{} +} + +// GrantTypesCleared returns if the "grant_types" field was cleared in this mutation. +func (m *ConnectorMutation) GrantTypesCleared() bool { + _, ok := m.clearedFields[connector.FieldGrantTypes] + return ok +} + +// ResetGrantTypes resets all changes to the "grant_types" field. +func (m *ConnectorMutation) ResetGrantTypes() { + m.grant_types = nil + m.appendgrant_types = nil + delete(m.clearedFields, connector.FieldGrantTypes) +} + // Where appends a list predicates to the ConnectorMutation builder. func (m *ConnectorMutation) Where(ps ...predicate.Connector) { m.predicates = append(m.predicates, ps...) @@ -3015,7 +3082,7 @@ func (m *ConnectorMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *ConnectorMutation) Fields() []string { - fields := make([]string, 0, 4) + fields := make([]string, 0, 5) if m._type != nil { fields = append(fields, connector.FieldType) } @@ -3028,6 +3095,9 @@ func (m *ConnectorMutation) Fields() []string { if m._config != nil { fields = append(fields, connector.FieldConfig) } + if m.grant_types != nil { + fields = append(fields, connector.FieldGrantTypes) + } return fields } @@ -3044,6 +3114,8 @@ func (m *ConnectorMutation) Field(name string) (ent.Value, bool) { return m.ResourceVersion() case connector.FieldConfig: return m.Config() + case connector.FieldGrantTypes: + return m.GrantTypes() } return nil, false } @@ -3061,6 +3133,8 @@ func (m *ConnectorMutation) OldField(ctx context.Context, name string) (ent.Valu return m.OldResourceVersion(ctx) case connector.FieldConfig: return m.OldConfig(ctx) + case connector.FieldGrantTypes: + return m.OldGrantTypes(ctx) } return nil, fmt.Errorf("unknown Connector field %s", name) } @@ -3098,6 +3172,13 @@ func (m *ConnectorMutation) SetField(name string, value ent.Value) error { } m.SetConfig(v) return nil + case connector.FieldGrantTypes: + v, ok := value.([]string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetGrantTypes(v) + return nil } return fmt.Errorf("unknown Connector field %s", name) } @@ -3127,7 +3208,11 @@ func (m *ConnectorMutation) AddField(name string, value ent.Value) error { // ClearedFields returns all nullable fields that were cleared during this // mutation. func (m *ConnectorMutation) ClearedFields() []string { - return nil + var fields []string + if m.FieldCleared(connector.FieldGrantTypes) { + fields = append(fields, connector.FieldGrantTypes) + } + return fields } // FieldCleared returns a boolean indicating if a field with the given name was @@ -3140,6 +3225,11 @@ func (m *ConnectorMutation) FieldCleared(name string) bool { // ClearField clears the value of the field with the given name. It returns an // error if the field is not defined in the schema. func (m *ConnectorMutation) ClearField(name string) error { + switch name { + case connector.FieldGrantTypes: + m.ClearGrantTypes() + return nil + } return fmt.Errorf("unknown Connector nullable field %s", name) } @@ -3159,6 +3249,9 @@ func (m *ConnectorMutation) ResetField(name string) error { case connector.FieldConfig: m.ResetConfig() return nil + case connector.FieldGrantTypes: + m.ResetGrantTypes() + return nil } return fmt.Errorf("unknown Connector field %s", name) } diff --git a/storage/ent/schema/connector.go b/storage/ent/schema/connector.go index 41b65eb4..191092c5 100644 --- a/storage/ent/schema/connector.go +++ b/storage/ent/schema/connector.go @@ -38,6 +38,8 @@ func (Connector) Fields() []ent.Field { field.Text("resource_version"). SchemaType(textSchema), field.Bytes("config"), + field.JSON("grant_types", []string{}). + Optional(), } } diff --git a/storage/kubernetes/types.go b/storage/kubernetes/types.go index 9e0f7e68..502df413 100644 --- a/storage/kubernetes/types.go +++ b/storage/kubernetes/types.go @@ -721,6 +721,8 @@ type Connector struct { Name string `json:"name,omitempty"` // Config holds connector specific configuration information Config []byte `json:"config,omitempty"` + // GrantTypes is a list of grant types that this connector is allowed to be used with. + GrantTypes []string `json:"grantTypes,omitempty"` } func (cli *client) fromStorageConnector(c storage.Connector) Connector { @@ -733,10 +735,11 @@ func (cli *client) fromStorageConnector(c storage.Connector) Connector { Name: c.ID, Namespace: cli.namespace, }, - ID: c.ID, - Type: c.Type, - Name: c.Name, - Config: c.Config, + ID: c.ID, + Type: c.Type, + Name: c.Name, + Config: c.Config, + GrantTypes: c.GrantTypes, } } @@ -747,6 +750,7 @@ func toStorageConnector(c Connector) storage.Connector { Name: c.Name, ResourceVersion: c.ObjectMeta.ResourceVersion, Config: c.Config, + GrantTypes: c.GrantTypes, } } diff --git a/storage/sql/crud.go b/storage/sql/crud.go index e60f29d5..c03714b3 100644 --- a/storage/sql/crud.go +++ b/storage/sql/crud.go @@ -769,15 +769,19 @@ func scanOfflineSessions(s scanner) (o storage.OfflineSessions, err error) { } func (c *conn) CreateConnector(ctx context.Context, connector storage.Connector) error { - _, err := c.Exec(` + grantTypes, err := json.Marshal(connector.GrantTypes) + if err != nil { + return fmt.Errorf("marshal connector grant types: %v", err) + } + _, err = c.Exec(` insert into connector ( - id, type, name, resource_version, config + id, type, name, resource_version, config, grant_types ) values ( - $1, $2, $3, $4, $5 + $1, $2, $3, $4, $5, $6 ); `, - connector.ID, connector.Type, connector.Name, connector.ResourceVersion, connector.Config, + connector.ID, connector.Type, connector.Name, connector.ResourceVersion, connector.Config, grantTypes, ) if err != nil { if c.alreadyExistsCheck(err) { @@ -799,16 +803,21 @@ func (c *conn) UpdateConnector(ctx context.Context, id string, updater func(s st if err != nil { return err } + grantTypes, err := json.Marshal(newConn.GrantTypes) + if err != nil { + return fmt.Errorf("marshal connector grant types: %v", err) + } _, err = tx.Exec(` update connector set type = $1, name = $2, resource_version = $3, - config = $4 - where id = $5; + config = $4, + grant_types = $5 + where id = $6; `, - newConn.Type, newConn.Name, newConn.ResourceVersion, newConn.Config, connector.ID, + newConn.Type, newConn.Name, newConn.ResourceVersion, newConn.Config, grantTypes, connector.ID, ) if err != nil { return fmt.Errorf("update connector: %v", err) @@ -824,15 +833,16 @@ func (c *conn) GetConnector(ctx context.Context, id string) (storage.Connector, func getConnector(ctx context.Context, q querier, id string) (storage.Connector, error) { return scanConnector(q.QueryRow(` select - id, type, name, resource_version, config + id, type, name, resource_version, config, grant_types from connector where id = $1; `, id)) } func scanConnector(s scanner) (c storage.Connector, err error) { + var grantTypes []byte err = s.Scan( - &c.ID, &c.Type, &c.Name, &c.ResourceVersion, &c.Config, + &c.ID, &c.Type, &c.Name, &c.ResourceVersion, &c.Config, &grantTypes, ) if err != nil { if err == sql.ErrNoRows { @@ -840,13 +850,18 @@ func scanConnector(s scanner) (c storage.Connector, err error) { } return c, fmt.Errorf("select connector: %v", err) } + if len(grantTypes) > 0 { + if err := json.Unmarshal(grantTypes, &c.GrantTypes); err != nil { + return c, fmt.Errorf("unmarshal connector grant types: %v", err) + } + } return c, nil } func (c *conn) ListConnectors(ctx context.Context) ([]storage.Connector, error) { rows, err := c.Query(` select - id, type, name, resource_version, config + id, type, name, resource_version, config, grant_types from connector; `) if err != nil { diff --git a/storage/sql/migrate.go b/storage/sql/migrate.go index 9a1807c9..01f393f1 100644 --- a/storage/sql/migrate.go +++ b/storage/sql/migrate.go @@ -374,4 +374,11 @@ var migrations = []migration{ }, flavor: &flavorMySQL, }, + { + stmts: []string{ + ` + alter table connector + add column grant_types bytea;`, + }, + }, } diff --git a/storage/storage.go b/storage/storage.go index b6e4d285..599badb6 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -388,6 +388,10 @@ type Connector struct { // However, fixing this requires migrating Kubernetes objects for all previously created connectors, // or making Dex reading both tags and act accordingly. Config []byte `json:"email"` + + // GrantTypes is a list of grant types that this connector is allowed to be used with. + // If empty, all grant types are allowed. + GrantTypes []string `json:"grantTypes,omitempty"` } // VerificationKey is a rotated signing key which can still be used to verify