From e39146c98e7f4c801b377954d3d6da40d9e77c78 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 31 Jan 2022 07:27:52 +0100 Subject: [PATCH 1/4] fix: ensure signer has key on OP creation --- pkg/op/op.go | 2 +- pkg/op/signer.go | 36 +++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/pkg/op/op.go b/pkg/op/op.go index 8a5be26..1c233ea 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -125,8 +125,8 @@ func NewOpenIDProvider(ctx context.Context, config *Config, storage Storage, opO } keyCh := make(chan jose.SigningKey) - o.signer = NewSigner(ctx, storage, keyCh) go storage.GetSigningKey(ctx, keyCh) + o.signer = NewSigner(ctx, storage, keyCh) o.httpHandler = CreateRouter(o, o.interceptors...) diff --git a/pkg/op/signer.go b/pkg/op/signer.go index d59ea8e..aaa24d0 100644 --- a/pkg/op/signer.go +++ b/pkg/op/signer.go @@ -25,6 +25,12 @@ func NewSigner(ctx context.Context, storage AuthStorage, keyCh <-chan jose.Signi storage: storage, } + select { + case <-ctx.Done(): + return nil + case key := <-keyCh: + s.exchangeSigningKey(key) + } go s.refreshSigningKey(ctx, keyCh) return s @@ -50,23 +56,27 @@ func (s *tokenSigner) refreshSigningKey(ctx context.Context, keyCh <-chan jose.S case <-ctx.Done(): return case key := <-keyCh: - s.alg = key.Algorithm - if key.Algorithm == "" || key.Key == nil { - s.signer = nil - logging.Log("OP-DAvt4").Warn("signer has no key") - continue - } - var err error - s.signer, err = jose.NewSigner(key, &jose.SignerOptions{}) - if err != nil { - logging.Log("OP-pf32aw").WithError(err).Error("error creating signer") - continue - } - logging.Log("OP-agRf2").Info("signer exchanged signing key") + s.exchangeSigningKey(key) } } } +func (s *tokenSigner) exchangeSigningKey(key jose.SigningKey) { + s.alg = key.Algorithm + if key.Algorithm == "" || key.Key == nil { + s.signer = nil + logging.Log("OP-DAvt4").Warn("signer has no key") + return + } + var err error + s.signer, err = jose.NewSigner(key, &jose.SignerOptions{}) + if err != nil { + logging.Log("OP-pf32aw").WithError(err).Error("error creating signer") + return + } + logging.Log("OP-agRf2").Info("signer exchanged signing key") +} + func (s *tokenSigner) SignatureAlgorithm() jose.SignatureAlgorithm { return s.alg } From 5601add62829840514aca8e2896d6d7282e601bb Mon Sep 17 00:00:00 2001 From: Ydris Rebibane Date: Wed, 16 Feb 2022 09:14:54 +0100 Subject: [PATCH 2/4] feat: Allow the use of a custom discovery endpoint (#152) * Allow the use of custom endpoints * Remove the custom constrtouctor and replace with an optional argument to override the discovery endpoit --- pkg/client/client.go | 7 ++++++- pkg/client/rp/relaying_party.go | 20 ++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pkg/client/client.go b/pkg/client/client.go index 1828d1d..ac6cd56 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -26,8 +26,13 @@ var ( ) //Discover calls the discovery endpoint of the provided issuer and returns its configuration -func Discover(issuer string, httpClient *http.Client) (*oidc.DiscoveryConfiguration, error) { +//It accepts an optional argument "wellknownUrl" which can be used to overide the dicovery endpoint url +func Discover(issuer string, httpClient *http.Client, wellKnownUrl ...string) (*oidc.DiscoveryConfiguration, error) { + wellKnown := strings.TrimSuffix(issuer, "/") + oidc.DiscoveryEndpoint + if len(wellKnownUrl) == 1 && wellKnownUrl[0] != "" { + wellKnown = wellKnownUrl[0] + } req, err := http.NewRequest("GET", wellKnown, nil) if err != nil { return nil, err diff --git a/pkg/client/rp/relaying_party.go b/pkg/client/rp/relaying_party.go index 23c37fc..98ab354 100644 --- a/pkg/client/rp/relaying_party.go +++ b/pkg/client/rp/relaying_party.go @@ -69,11 +69,12 @@ var ( ) type relyingParty struct { - issuer string - endpoints Endpoints - oauthConfig *oauth2.Config - oauth2Only bool - pkce bool + issuer string + DiscoveryEndpoint string + endpoints Endpoints + oauthConfig *oauth2.Config + oauth2Only bool + pkce bool httpClient *http.Client cookieHandler *httphelper.CookieHandler @@ -170,7 +171,7 @@ func NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI string, sco return nil, err } } - discoveryConfiguration, err := client.Discover(rp.issuer, rp.httpClient) + discoveryConfiguration, err := client.Discover(rp.issuer, rp.httpClient, rp.DiscoveryEndpoint) if err != nil { return nil, err } @@ -184,6 +185,13 @@ func NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI string, sco //Option is the type for providing dynamic options to the relyingParty type Option func(*relyingParty) error +func WithCustomDiscoveryUrl(url string) Option { + return func(rp *relyingParty) error { + rp.DiscoveryEndpoint = url + return nil + } +} + //WithCookieHandler set a `CookieHandler` for securing the various redirects func WithCookieHandler(cookieHandler *httphelper.CookieHandler) Option { return func(rp *relyingParty) error { From b914990e15cf1910debf05bfeac6f16a128ad0b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Mar 2022 06:59:53 +0100 Subject: [PATCH 3/4] chore(deps): bump actions/checkout from 2 to 3 (#161) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0101ea5..6bdfcdf 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 471c09e..c404ba3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: go: ['1.14', '1.15', '1.16', '1.17'] name: Go ${{ matrix.go }} test steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup go uses: actions/setup-go@v2 with: @@ -36,7 +36,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Source checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Semantic Release uses: cycjimmy/semantic-release-action@v2 with: From c07557be026cbef2e5373a37da54b12b01b5d098 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 16 Mar 2022 10:55:29 +0100 Subject: [PATCH 4/4] feat: build the redirect after a successful login with AuthCallbackURL function (#164) --- pkg/op/op.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/op/op.go b/pkg/op/op.go index 1c233ea..e910bf6 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -19,6 +19,7 @@ import ( const ( healthEndpoint = "/healthz" readinessEndpoint = "/ready" + authCallbackPathSuffix = "/callback" defaultAuthorizationEndpoint = "authorize" defaultTokenEndpoint = "oauth/token" defaultIntrospectEndpoint = "oauth/introspect" @@ -72,7 +73,7 @@ func CreateRouter(o OpenIDProvider, interceptors ...HttpInterceptor) *mux.Router router.HandleFunc(readinessEndpoint, readyHandler(o.Probes())) router.HandleFunc(oidc.DiscoveryEndpoint, discoveryHandler(o, o.Signer())) router.Handle(o.AuthorizationEndpoint().Relative(), intercept(authorizeHandler(o))) - router.NewRoute().Path(o.AuthorizationEndpoint().Relative()+"/callback").Queries("id", "{id}").Handler(intercept(authorizeCallbackHandler(o))) + router.NewRoute().Path(authCallbackPath(o)).Queries("id", "{id}").Handler(intercept(authorizeCallbackHandler(o))) router.Handle(o.TokenEndpoint().Relative(), intercept(tokenHandler(o))) router.HandleFunc(o.IntrospectionEndpoint().Relative(), introspectionHandler(o)) router.HandleFunc(o.UserinfoEndpoint().Relative(), userinfoHandler(o)) @@ -82,6 +83,17 @@ func CreateRouter(o OpenIDProvider, interceptors ...HttpInterceptor) *mux.Router return router } +//AuthCallbackURL builds the url for the redirect (with the requestID) after a successful login +func AuthCallbackURL(o OpenIDProvider) func(string) string { + return func(requestID string) string { + return o.AuthorizationEndpoint().Absolute(o.Issuer()) + authCallbackPathSuffix + "?id=" + requestID + } +} + +func authCallbackPath(o OpenIDProvider) string { + return o.AuthorizationEndpoint().Relative() + authCallbackPathSuffix +} + type Config struct { Issuer string CryptoKey [32]byte