// Copyright 2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 // Package clientregistry defines Pinniped's OAuth2/OIDC clients. package clientregistry import ( "context" "fmt" "time" "github.com/coreos/go-oidc/v3/oidc" "github.com/ory/fosite" ) // Client represents a Pinniped OAuth/OIDC client. type Client struct { fosite.DefaultOpenIDConnectClient } func (c Client) GetResponseModes() []fosite.ResponseModeType { // For now, all Pinniped clients always support "" (unspecified), "query", and "form_post" response modes. return []fosite.ResponseModeType{fosite.ResponseModeDefault, fosite.ResponseModeQuery, fosite.ResponseModeFormPost} } // It implements both the base, OIDC, and response_mode client interfaces of Fosite. var ( _ fosite.Client = (*Client)(nil) _ fosite.OpenIDConnectClient = (*Client)(nil) _ fosite.ResponseModeClient = (*Client)(nil) ) // StaticClientManager is a fosite.ClientManager with statically-defined clients. type StaticClientManager struct{} var _ fosite.ClientManager = (*StaticClientManager)(nil) // GetClient returns a static client specified by the given ID. // // It returns a fosite.ErrNotFound if an unknown client is specified. func (StaticClientManager) GetClient(_ context.Context, id string) (fosite.Client, error) { switch id { case "pinniped-cli": return PinnipedCLI(), nil default: return nil, fosite.ErrNotFound.WithDescription("no such client") } } // ClientAssertionJWTValid returns an error if the JTI is // known or the DB check failed and nil if the JTI is not known. // // This functionality is not supported by the StaticClientManager. func (StaticClientManager) ClientAssertionJWTValid(ctx context.Context, jti string) error { return fmt.Errorf("not implemented") } // SetClientAssertionJWT marks a JTI as known for the given // expiry time. Before inserting the new JTI, it will clean // up any existing JTIs that have expired as those tokens can // not be replayed due to the expiry. // // This functionality is not supported by the StaticClientManager. func (StaticClientManager) SetClientAssertionJWT(ctx context.Context, jti string, exp time.Time) error { return fmt.Errorf("not implemented") } // PinnipedCLI returns the static Client corresponding to the Pinniped CLI. func PinnipedCLI() *Client { return &Client{ DefaultOpenIDConnectClient: fosite.DefaultOpenIDConnectClient{ DefaultClient: &fosite.DefaultClient{ ID: "pinniped-cli", Secret: nil, RedirectURIs: []string{"http://127.0.0.1/callback"}, GrantTypes: fosite.Arguments{ "authorization_code", "refresh_token", "urn:ietf:params:oauth:grant-type:token-exchange", }, ResponseTypes: []string{"code"}, Scopes: fosite.Arguments{ oidc.ScopeOpenID, oidc.ScopeOfflineAccess, "profile", "email", "pinniped:request-audience", }, Audience: nil, Public: true, }, RequestURIs: nil, JSONWebKeys: nil, JSONWebKeysURI: "", RequestObjectSigningAlgorithm: "", TokenEndpointAuthSigningAlgorithm: oidc.RS256, TokenEndpointAuthMethod: "none", }, } }