Merge branch 'main' into dependabot/go_modules/github.com/caos/logging-0.3.1
# Conflicts: # pkg/op/signer.go
This commit is contained in:
commit
c8d9da150e
6 changed files with 60 additions and 25 deletions
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
# We must fetch at least the immediate parents so that if this is
|
# We must fetch at least the immediate parents so that if this is
|
||||||
# a pull request then we can checkout the head.
|
# a pull request then we can checkout the head.
|
||||||
|
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
||||||
go: ['1.14', '1.15', '1.16', '1.17']
|
go: ['1.14', '1.15', '1.16', '1.17']
|
||||||
name: Go ${{ matrix.go }} test
|
name: Go ${{ matrix.go }} test
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
|
@ -36,7 +36,7 @@ jobs:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
- name: Source checkout
|
- name: Source checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Semantic Release
|
- name: Semantic Release
|
||||||
uses: cycjimmy/semantic-release-action@v2
|
uses: cycjimmy/semantic-release-action@v2
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -26,8 +26,13 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
//Discover calls the discovery endpoint of the provided issuer and returns its configuration
|
//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
|
wellKnown := strings.TrimSuffix(issuer, "/") + oidc.DiscoveryEndpoint
|
||||||
|
if len(wellKnownUrl) == 1 && wellKnownUrl[0] != "" {
|
||||||
|
wellKnown = wellKnownUrl[0]
|
||||||
|
}
|
||||||
req, err := http.NewRequest("GET", wellKnown, nil)
|
req, err := http.NewRequest("GET", wellKnown, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -70,6 +70,7 @@ var (
|
||||||
|
|
||||||
type relyingParty struct {
|
type relyingParty struct {
|
||||||
issuer string
|
issuer string
|
||||||
|
DiscoveryEndpoint string
|
||||||
endpoints Endpoints
|
endpoints Endpoints
|
||||||
oauthConfig *oauth2.Config
|
oauthConfig *oauth2.Config
|
||||||
oauth2Only bool
|
oauth2Only bool
|
||||||
|
@ -170,7 +171,7 @@ func NewRelyingPartyOIDC(issuer, clientID, clientSecret, redirectURI string, sco
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
discoveryConfiguration, err := client.Discover(rp.issuer, rp.httpClient)
|
discoveryConfiguration, err := client.Discover(rp.issuer, rp.httpClient, rp.DiscoveryEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
//Option is the type for providing dynamic options to the relyingParty
|
||||||
type Option func(*relyingParty) error
|
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
|
//WithCookieHandler set a `CookieHandler` for securing the various redirects
|
||||||
func WithCookieHandler(cookieHandler *httphelper.CookieHandler) Option {
|
func WithCookieHandler(cookieHandler *httphelper.CookieHandler) Option {
|
||||||
return func(rp *relyingParty) error {
|
return func(rp *relyingParty) error {
|
||||||
|
|
16
pkg/op/op.go
16
pkg/op/op.go
|
@ -19,6 +19,7 @@ import (
|
||||||
const (
|
const (
|
||||||
healthEndpoint = "/healthz"
|
healthEndpoint = "/healthz"
|
||||||
readinessEndpoint = "/ready"
|
readinessEndpoint = "/ready"
|
||||||
|
authCallbackPathSuffix = "/callback"
|
||||||
defaultAuthorizationEndpoint = "authorize"
|
defaultAuthorizationEndpoint = "authorize"
|
||||||
defaultTokenEndpoint = "oauth/token"
|
defaultTokenEndpoint = "oauth/token"
|
||||||
defaultIntrospectEndpoint = "oauth/introspect"
|
defaultIntrospectEndpoint = "oauth/introspect"
|
||||||
|
@ -72,7 +73,7 @@ func CreateRouter(o OpenIDProvider, interceptors ...HttpInterceptor) *mux.Router
|
||||||
router.HandleFunc(readinessEndpoint, readyHandler(o.Probes()))
|
router.HandleFunc(readinessEndpoint, readyHandler(o.Probes()))
|
||||||
router.HandleFunc(oidc.DiscoveryEndpoint, discoveryHandler(o, o.Signer()))
|
router.HandleFunc(oidc.DiscoveryEndpoint, discoveryHandler(o, o.Signer()))
|
||||||
router.Handle(o.AuthorizationEndpoint().Relative(), intercept(authorizeHandler(o)))
|
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.Handle(o.TokenEndpoint().Relative(), intercept(tokenHandler(o)))
|
||||||
router.HandleFunc(o.IntrospectionEndpoint().Relative(), introspectionHandler(o))
|
router.HandleFunc(o.IntrospectionEndpoint().Relative(), introspectionHandler(o))
|
||||||
router.HandleFunc(o.UserinfoEndpoint().Relative(), userinfoHandler(o))
|
router.HandleFunc(o.UserinfoEndpoint().Relative(), userinfoHandler(o))
|
||||||
|
@ -82,6 +83,17 @@ func CreateRouter(o OpenIDProvider, interceptors ...HttpInterceptor) *mux.Router
|
||||||
return 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 {
|
type Config struct {
|
||||||
Issuer string
|
Issuer string
|
||||||
CryptoKey [32]byte
|
CryptoKey [32]byte
|
||||||
|
@ -125,8 +137,8 @@ func NewOpenIDProvider(ctx context.Context, config *Config, storage Storage, opO
|
||||||
}
|
}
|
||||||
|
|
||||||
keyCh := make(chan jose.SigningKey)
|
keyCh := make(chan jose.SigningKey)
|
||||||
o.signer = NewSigner(ctx, storage, keyCh)
|
|
||||||
go storage.GetSigningKey(ctx, keyCh)
|
go storage.GetSigningKey(ctx, keyCh)
|
||||||
|
o.signer = NewSigner(ctx, storage, keyCh)
|
||||||
|
|
||||||
o.httpHandler = CreateRouter(o, o.interceptors...)
|
o.httpHandler = CreateRouter(o, o.interceptors...)
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,12 @@ func NewSigner(ctx context.Context, storage AuthStorage, keyCh <-chan jose.Signi
|
||||||
storage: storage,
|
storage: storage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil
|
||||||
|
case key := <-keyCh:
|
||||||
|
s.exchangeSigningKey(key)
|
||||||
|
}
|
||||||
go s.refreshSigningKey(ctx, keyCh)
|
go s.refreshSigningKey(ctx, keyCh)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
@ -50,21 +56,25 @@ func (s *tokenSigner) refreshSigningKey(ctx context.Context, keyCh <-chan jose.S
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case key := <-keyCh:
|
case key := <-keyCh:
|
||||||
|
s.exchangeSigningKey(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *tokenSigner) exchangeSigningKey(key jose.SigningKey) {
|
||||||
s.alg = key.Algorithm
|
s.alg = key.Algorithm
|
||||||
if key.Algorithm == "" || key.Key == nil {
|
if key.Algorithm == "" || key.Key == nil {
|
||||||
s.signer = nil
|
s.signer = nil
|
||||||
logging.Warn("signer has no key")
|
logging.Warn("signer has no key")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
s.signer, err = jose.NewSigner(key, &jose.SignerOptions{})
|
s.signer, err = jose.NewSigner(key, &jose.SignerOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.New().WithError(err).Error("error creating signer")
|
logging.New().WithError(err).Error("error creating signer")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
logging.Info("signer exchanged signing key")
|
logging.Info("signer exchanged signing key")
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *tokenSigner) SignatureAlgorithm() jose.SignatureAlgorithm {
|
func (s *tokenSigner) SignatureAlgorithm() jose.SignatureAlgorithm {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue