Verify main v extra JWT bearers differently
When using the configured provider JWT Verifier, it makes sense to use the provider `CreateSessionStateFromBearerToken` method. For any extra JWT Issuers, they should use a generic default verifier.
This commit is contained in:
		
							parent
							
								
									5817028bb1
								
							
						
					
					
						commit
						788d8ecc1b
					
				| 
						 | 
					@ -111,7 +111,8 @@ type OAuthProxy struct {
 | 
				
			||||||
	skipAuthRegex           []string
 | 
						skipAuthRegex           []string
 | 
				
			||||||
	skipAuthPreflight       bool
 | 
						skipAuthPreflight       bool
 | 
				
			||||||
	skipJwtBearerTokens     bool
 | 
						skipJwtBearerTokens     bool
 | 
				
			||||||
	jwtBearerVerifiers   []*oidc.IDTokenVerifier
 | 
						mainJwtBearerVerifier   *oidc.IDTokenVerifier
 | 
				
			||||||
 | 
						extraJwtBearerVerifiers []*oidc.IDTokenVerifier
 | 
				
			||||||
	compiledRegex           []*regexp.Regexp
 | 
						compiledRegex           []*regexp.Regexp
 | 
				
			||||||
	templates               *template.Template
 | 
						templates               *template.Template
 | 
				
			||||||
	realClientIPParser      ipapi.RealClientIPParser
 | 
						realClientIPParser      ipapi.RealClientIPParser
 | 
				
			||||||
| 
						 | 
					@ -327,7 +328,8 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) *OAuthPro
 | 
				
			||||||
		skipAuthRegex:           opts.SkipAuthRegex,
 | 
							skipAuthRegex:           opts.SkipAuthRegex,
 | 
				
			||||||
		skipAuthPreflight:       opts.SkipAuthPreflight,
 | 
							skipAuthPreflight:       opts.SkipAuthPreflight,
 | 
				
			||||||
		skipJwtBearerTokens:     opts.SkipJwtBearerTokens,
 | 
							skipJwtBearerTokens:     opts.SkipJwtBearerTokens,
 | 
				
			||||||
		jwtBearerVerifiers:   opts.GetJWTBearerVerifiers(),
 | 
							mainJwtBearerVerifier:   opts.GetOIDCVerifier(),
 | 
				
			||||||
 | 
							extraJwtBearerVerifiers: opts.GetJWTBearerVerifiers(),
 | 
				
			||||||
		compiledRegex:           opts.GetCompiledRegex(),
 | 
							compiledRegex:           opts.GetCompiledRegex(),
 | 
				
			||||||
		realClientIPParser:      opts.GetRealClientIPParser(),
 | 
							realClientIPParser:      opts.GetRealClientIPParser(),
 | 
				
			||||||
		SetXAuthRequest:         opts.SetXAuthRequest,
 | 
							SetXAuthRequest:         opts.SetXAuthRequest,
 | 
				
			||||||
| 
						 | 
					@ -1139,15 +1141,24 @@ func (p *OAuthProxy) GetJwtSession(req *http.Request) (*sessionsapi.SessionState
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, verifier := range p.jwtBearerVerifiers {
 | 
						// If we are using an oidc provider, go ahead and try that provider first with its Verifier
 | 
				
			||||||
		bearerToken, err := verifier.Verify(req.Context(), rawBearerToken)
 | 
						// and Bearer Token -> Session converter
 | 
				
			||||||
 | 
						if p.mainJwtBearerVerifier != nil {
 | 
				
			||||||
 | 
							bearerToken, err := p.mainJwtBearerVerifier.Verify(req.Context(), rawBearerToken)
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								return p.provider.CreateSessionStateFromBearerToken(req.Context(), rawBearerToken, bearerToken)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Otherwise, attempt to verify against the extra JWT issuers and use a more generic
 | 
				
			||||||
 | 
						// Bearer Token -> Session converter
 | 
				
			||||||
 | 
						for _, verifier := range p.extraJwtBearerVerifiers {
 | 
				
			||||||
 | 
							bearerToken, err := verifier.Verify(req.Context(), rawBearerToken)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			logger.Printf("failed to verify bearer token: %v", err)
 | 
					 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return p.provider.CreateSessionStateFromBearerToken(req.Context(), rawBearerToken, bearerToken)
 | 
							return (*providers.ProviderData)(nil).CreateSessionStateFromBearerToken(req.Context(), rawBearerToken, bearerToken)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil, fmt.Errorf("unable to verify jwt token %s", req.Header.Get("Authorization"))
 | 
						return nil, fmt.Errorf("unable to verify jwt token %s", req.Header.Get("Authorization"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,10 +178,6 @@ func Validate(o *options.Options) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if o.SkipJwtBearerTokens {
 | 
						if o.SkipJwtBearerTokens {
 | 
				
			||||||
		// If we are using an oidc provider, go ahead and add that provider to the list
 | 
					 | 
				
			||||||
		if o.GetOIDCVerifier() != nil {
 | 
					 | 
				
			||||||
			o.SetJWTBearerVerifiers(append(o.GetJWTBearerVerifiers(), o.GetOIDCVerifier()))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// Configure extra issuers
 | 
							// Configure extra issuers
 | 
				
			||||||
		if len(o.ExtraJwtIssuers) > 0 {
 | 
							if len(o.ExtraJwtIssuers) > 0 {
 | 
				
			||||||
			var jwtIssuers []jwtIssuer
 | 
								var jwtIssuers []jwtIssuer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,7 +124,6 @@ func newOIDCServer(body []byte) (*url.URL, *httptest.Server) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newSignedTestIDToken(tokenClaims idTokenClaims) (string, error) {
 | 
					func newSignedTestIDToken(tokenClaims idTokenClaims) (string, error) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	key, _ := rsa.GenerateKey(rand.Reader, 2048)
 | 
						key, _ := rsa.GenerateKey(rand.Reader, 2048)
 | 
				
			||||||
	standardClaims := jwt.NewWithClaims(jwt.SigningMethodRS256, tokenClaims)
 | 
						standardClaims := jwt.NewWithClaims(jwt.SigningMethodRS256, tokenClaims)
 | 
				
			||||||
	return standardClaims.SignedString(key)
 | 
						return standardClaims.SignedString(key)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,10 @@ package providers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"crypto/rand"
 | 
				
			||||||
 | 
						"crypto/rsa"
 | 
				
			||||||
 | 
						"github.com/coreos/go-oidc"
 | 
				
			||||||
 | 
						"github.com/dgrijalva/jwt-go"
 | 
				
			||||||
	"net/url"
 | 
						"net/url"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
| 
						 | 
					@ -47,3 +51,35 @@ func TestAcrValuesConfigured(t *testing.T) {
 | 
				
			||||||
	result := p.GetLoginURL("https://my.test.app/oauth", "")
 | 
						result := p.GetLoginURL("https://my.test.app/oauth", "")
 | 
				
			||||||
	assert.Contains(t, result, "acr_values=testValue")
 | 
						assert.Contains(t, result, "acr_values=testValue")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCreateSessionStateFromBearerToken(t *testing.T) {
 | 
				
			||||||
 | 
						minimalIDToken := jwt.StandardClaims{
 | 
				
			||||||
 | 
							Audience:  "asdf1234",
 | 
				
			||||||
 | 
							ExpiresAt: time.Now().Add(time.Duration(5) * time.Minute).Unix(),
 | 
				
			||||||
 | 
							Id:        "id-some-id",
 | 
				
			||||||
 | 
							IssuedAt:  time.Now().Unix(),
 | 
				
			||||||
 | 
							Issuer:    "https://issuer.example.com",
 | 
				
			||||||
 | 
							NotBefore: 0,
 | 
				
			||||||
 | 
							Subject:   "123456789",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// From oidc_test.go
 | 
				
			||||||
 | 
						verifier := oidc.NewVerifier(
 | 
				
			||||||
 | 
							"https://issuer.example.com",
 | 
				
			||||||
 | 
							fakeKeySetStub{},
 | 
				
			||||||
 | 
							&oidc.Config{ClientID: "asdf1234"},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key, _ := rsa.GenerateKey(rand.Reader, 2048)
 | 
				
			||||||
 | 
						rawIDToken, _ := jwt.NewWithClaims(jwt.SigningMethodRS256, minimalIDToken).SignedString(key)
 | 
				
			||||||
 | 
						idToken, err := verifier.Verify(context.Background(), rawIDToken)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session, err := (*ProviderData)(nil).CreateSessionStateFromBearerToken(context.Background(), rawIDToken, idToken)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert.Equal(t, nil, err)
 | 
				
			||||||
 | 
						assert.Equal(t, rawIDToken, session.AccessToken)
 | 
				
			||||||
 | 
						assert.Equal(t, rawIDToken, session.IDToken)
 | 
				
			||||||
 | 
						assert.Equal(t, "", session.RefreshToken)
 | 
				
			||||||
 | 
						assert.Equal(t, "123456789", session.Email)
 | 
				
			||||||
 | 
						assert.Equal(t, "123456789", session.User)
 | 
				
			||||||
 | 
						assert.Equal(t, "", session.PreferredUsername)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue