Added Discovery to grpc (#3598)

Signed-off-by: Koen de Laat <koen.de.laat@philips.com>
This commit is contained in:
Koen de Laat
2024-08-29 17:12:25 +02:00
committed by GitHub
parent 14d31a75ec
commit d0f1777c41
7 changed files with 540 additions and 173 deletions
+442 -159
View File
File diff suppressed because it is too large Load Diff
+24
View File
@@ -178,6 +178,28 @@ message VersionResp {
int32 api = 2;
}
// DiscoveryReq is a request to fetch discover information.
message DiscoveryReq {}
//DiscoverResp holds the version oidc disovery info.
message DiscoveryResp {
string issuer = 1;
string authorization_endpoint = 2;
string token_endpoint = 3;
string jwks_uri = 4;
string userinfo_endpoint = 5;
string device_authorization_endpoint = 6;
string introspection_endpoint = 7;
repeated string grant_types_supported = 8;
repeated string response_types_supported = 9;
repeated string subject_types_supported = 10;
repeated string id_token_signing_alg_values_supported = 11;
repeated string code_challenge_methods_supported = 12;
repeated string scopes_supported = 13;
repeated string token_endpoint_auth_methods_supported = 14;
repeated string claims_supported = 15;
}
// RefreshTokenRef contains the metadata for a refresh token that is managed by the storage.
message RefreshTokenRef {
// ID of the refresh token.
@@ -249,6 +271,8 @@ service Dex {
rpc ListConnectors(ListConnectorReq) returns (ListConnectorResp) {};
// GetVersion returns version information of the server.
rpc GetVersion(VersionReq) returns (VersionResp) {};
// GetDiscovery returns discovery information of the server.
rpc GetDiscovery(DiscoveryReq) returns (DiscoveryResp) {};
// ListRefresh lists all the refresh token entries for a particular user.
rpc ListRefresh(ListRefreshReq) returns (ListRefreshResp) {};
// RevokeRefresh revokes the refresh token for the provided user-client pair.
+39
View File
@@ -32,6 +32,7 @@ const (
Dex_DeleteConnector_FullMethodName = "/api.Dex/DeleteConnector"
Dex_ListConnectors_FullMethodName = "/api.Dex/ListConnectors"
Dex_GetVersion_FullMethodName = "/api.Dex/GetVersion"
Dex_GetDiscovery_FullMethodName = "/api.Dex/GetDiscovery"
Dex_ListRefresh_FullMethodName = "/api.Dex/ListRefresh"
Dex_RevokeRefresh_FullMethodName = "/api.Dex/RevokeRefresh"
Dex_VerifyPassword_FullMethodName = "/api.Dex/VerifyPassword"
@@ -67,6 +68,8 @@ type DexClient interface {
ListConnectors(ctx context.Context, in *ListConnectorReq, opts ...grpc.CallOption) (*ListConnectorResp, error)
// GetVersion returns version information of the server.
GetVersion(ctx context.Context, in *VersionReq, opts ...grpc.CallOption) (*VersionResp, error)
// GetDiscovery returns discovery information of the server.
GetDiscovery(ctx context.Context, in *DiscoveryReq, opts ...grpc.CallOption) (*DiscoveryResp, error)
// ListRefresh lists all the refresh token entries for a particular user.
ListRefresh(ctx context.Context, in *ListRefreshReq, opts ...grpc.CallOption) (*ListRefreshResp, error)
// RevokeRefresh revokes the refresh token for the provided user-client pair.
@@ -202,6 +205,15 @@ func (c *dexClient) GetVersion(ctx context.Context, in *VersionReq, opts ...grpc
return out, nil
}
func (c *dexClient) GetDiscovery(ctx context.Context, in *DiscoveryReq, opts ...grpc.CallOption) (*DiscoveryResp, error) {
out := new(DiscoveryResp)
err := c.cc.Invoke(ctx, Dex_GetDiscovery_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *dexClient) ListRefresh(ctx context.Context, in *ListRefreshReq, opts ...grpc.CallOption) (*ListRefreshResp, error) {
out := new(ListRefreshResp)
err := c.cc.Invoke(ctx, Dex_ListRefresh_FullMethodName, in, out, opts...)
@@ -259,6 +271,8 @@ type DexServer interface {
ListConnectors(context.Context, *ListConnectorReq) (*ListConnectorResp, error)
// GetVersion returns version information of the server.
GetVersion(context.Context, *VersionReq) (*VersionResp, error)
// GetDiscovery returns discovery information of the server.
GetDiscovery(context.Context, *DiscoveryReq) (*DiscoveryResp, error)
// ListRefresh lists all the refresh token entries for a particular user.
ListRefresh(context.Context, *ListRefreshReq) (*ListRefreshResp, error)
// RevokeRefresh revokes the refresh token for the provided user-client pair.
@@ -313,6 +327,9 @@ func (UnimplementedDexServer) ListConnectors(context.Context, *ListConnectorReq)
func (UnimplementedDexServer) GetVersion(context.Context, *VersionReq) (*VersionResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented")
}
func (UnimplementedDexServer) GetDiscovery(context.Context, *DiscoveryReq) (*DiscoveryResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetDiscovery not implemented")
}
func (UnimplementedDexServer) ListRefresh(context.Context, *ListRefreshReq) (*ListRefreshResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListRefresh not implemented")
}
@@ -569,6 +586,24 @@ func _Dex_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(inte
return interceptor(ctx, in, info, handler)
}
func _Dex_GetDiscovery_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DiscoveryReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DexServer).GetDiscovery(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Dex_GetDiscovery_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DexServer).GetDiscovery(ctx, req.(*DiscoveryReq))
}
return interceptor(ctx, in, info, handler)
}
func _Dex_ListRefresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListRefreshReq)
if err := dec(in); err != nil {
@@ -682,6 +717,10 @@ var Dex_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetVersion",
Handler: _Dex_GetVersion_Handler,
},
{
MethodName: "GetDiscovery",
Handler: _Dex_GetDiscovery_Handler,
},
{
MethodName: "ListRefresh",
Handler: _Dex_ListRefresh_Handler,
+1 -1
View File
@@ -508,7 +508,7 @@ func runServe(options serveOptions) error {
}
grpcSrv := grpc.NewServer(grpcOptions...)
api.RegisterDexServer(grpcSrv, server.NewAPI(serverConfig.Storage, logger, version))
api.RegisterDexServer(grpcSrv, server.NewAPI(serverConfig.Storage, logger, version, serv))
grpcMetrics.InitializeMetrics(grpcSrv)
if c.GRPC.Reflection {
+17 -1
View File
@@ -31,11 +31,12 @@ const (
)
// NewAPI returns a server which implements the gRPC API interface.
func NewAPI(s storage.Storage, logger *slog.Logger, version string) api.DexServer {
func NewAPI(s storage.Storage, logger *slog.Logger, version string, server *Server) api.DexServer {
return dexAPI{
s: s,
logger: logger.With("component", "api"),
version: version,
server: server,
}
}
@@ -45,6 +46,7 @@ type dexAPI struct {
s storage.Storage
logger *slog.Logger
version string
server *Server
}
func (d dexAPI) GetClient(ctx context.Context, req *api.GetClientReq) (*api.GetClientResp, error) {
@@ -250,6 +252,20 @@ func (d dexAPI) GetVersion(ctx context.Context, req *api.VersionReq) (*api.Versi
}, nil
}
func (d dexAPI) GetDiscovery(ctx context.Context, req *api.DiscoveryReq) (*api.DiscoveryResp, error) {
discoveryDoc := d.server.constructDiscovery()
data, err := json.Marshal(discoveryDoc)
if err != nil {
return nil, fmt.Errorf("failed to marshal discovery data: %v", err)
}
resp := api.DiscoveryResp{}
err = json.Unmarshal(data, &resp)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal discovery data: %v", err)
}
return &resp, nil
}
func (d dexAPI) ListPasswords(ctx context.Context, req *api.ListPasswordReq) (*api.ListPasswordResp, error) {
passwordList, err := d.s.ListPasswords()
if err != nil {
+1 -1
View File
@@ -38,7 +38,7 @@ func newAPI(s storage.Storage, logger *slog.Logger, t *testing.T) *apiClient {
}
serv := grpc.NewServer()
api.RegisterDexServer(serv, NewAPI(s, logger, "test"))
api.RegisterDexServer(serv, NewAPI(s, logger, "test", nil))
go serv.Serve(l)
// NewClient will retry automatically if the serv.Serve() goroutine
+16 -11
View File
@@ -90,6 +90,21 @@ type discovery struct {
}
func (s *Server) discoveryHandler() (http.HandlerFunc, error) {
d := s.constructDiscovery()
data, err := json.MarshalIndent(d, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal discovery data: %v", err)
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Length", strconv.Itoa(len(data)))
w.Write(data)
}), nil
}
func (s *Server) constructDiscovery() discovery {
d := discovery{
Issuer: s.issuerURL.String(),
Auth: s.absURL("/auth"),
@@ -115,17 +130,7 @@ func (s *Server) discoveryHandler() (http.HandlerFunc, error) {
sort.Strings(d.ResponseTypes)
d.GrantTypes = s.supportedGrantTypes
data, err := json.MarshalIndent(d, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal discovery data: %v", err)
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Length", strconv.Itoa(len(data)))
w.Write(data)
}), nil
return d
}
// handleAuthorization handles the OAuth2 auth endpoint.