mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2024-11-28 09:08:44 +02:00
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
129
oauthproxy.go
129
oauthproxy.go
@ -88,35 +88,36 @@ type OAuthProxy struct {
|
||||
AuthOnlyPath string
|
||||
UserInfoPath string
|
||||
|
||||
redirectURL *url.URL // the url to receive requests at
|
||||
whitelistDomains []string
|
||||
provider providers.Provider
|
||||
providerNameOverride string
|
||||
sessionStore sessionsapi.SessionStore
|
||||
ProxyPrefix string
|
||||
SignInMessage string
|
||||
HtpasswdFile *HtpasswdFile
|
||||
DisplayHtpasswdForm bool
|
||||
serveMux http.Handler
|
||||
SetXAuthRequest bool
|
||||
PassBasicAuth bool
|
||||
SetBasicAuth bool
|
||||
SkipProviderButton bool
|
||||
PassUserHeaders bool
|
||||
BasicAuthPassword string
|
||||
PassAccessToken bool
|
||||
SetAuthorization bool
|
||||
PassAuthorization bool
|
||||
PreferEmailToUser bool
|
||||
skipAuthRegex []string
|
||||
skipAuthPreflight bool
|
||||
skipJwtBearerTokens bool
|
||||
jwtBearerVerifiers []*oidc.IDTokenVerifier
|
||||
compiledRegex []*regexp.Regexp
|
||||
templates *template.Template
|
||||
realClientIPParser ipapi.RealClientIPParser
|
||||
Banner string
|
||||
Footer string
|
||||
redirectURL *url.URL // the url to receive requests at
|
||||
whitelistDomains []string
|
||||
provider providers.Provider
|
||||
providerNameOverride string
|
||||
sessionStore sessionsapi.SessionStore
|
||||
ProxyPrefix string
|
||||
SignInMessage string
|
||||
HtpasswdFile *HtpasswdFile
|
||||
DisplayHtpasswdForm bool
|
||||
serveMux http.Handler
|
||||
SetXAuthRequest bool
|
||||
PassBasicAuth bool
|
||||
SetBasicAuth bool
|
||||
SkipProviderButton bool
|
||||
PassUserHeaders bool
|
||||
BasicAuthPassword string
|
||||
PassAccessToken bool
|
||||
SetAuthorization bool
|
||||
PassAuthorization bool
|
||||
PreferEmailToUser bool
|
||||
skipAuthRegex []string
|
||||
skipAuthPreflight bool
|
||||
skipJwtBearerTokens bool
|
||||
mainJwtBearerVerifier *oidc.IDTokenVerifier
|
||||
extraJwtBearerVerifiers []*oidc.IDTokenVerifier
|
||||
compiledRegex []*regexp.Regexp
|
||||
templates *template.Template
|
||||
realClientIPParser ipapi.RealClientIPParser
|
||||
Banner string
|
||||
Footer string
|
||||
}
|
||||
|
||||
// UpstreamProxy represents an upstream server to proxy to
|
||||
@ -317,32 +318,33 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) *OAuthPro
|
||||
AuthOnlyPath: fmt.Sprintf("%s/auth", opts.ProxyPrefix),
|
||||
UserInfoPath: fmt.Sprintf("%s/userinfo", opts.ProxyPrefix),
|
||||
|
||||
ProxyPrefix: opts.ProxyPrefix,
|
||||
provider: opts.GetProvider(),
|
||||
providerNameOverride: opts.ProviderName,
|
||||
sessionStore: opts.GetSessionStore(),
|
||||
serveMux: serveMux,
|
||||
redirectURL: redirectURL,
|
||||
whitelistDomains: opts.WhitelistDomains,
|
||||
skipAuthRegex: opts.SkipAuthRegex,
|
||||
skipAuthPreflight: opts.SkipAuthPreflight,
|
||||
skipJwtBearerTokens: opts.SkipJwtBearerTokens,
|
||||
jwtBearerVerifiers: opts.GetJWTBearerVerifiers(),
|
||||
compiledRegex: opts.GetCompiledRegex(),
|
||||
realClientIPParser: opts.GetRealClientIPParser(),
|
||||
SetXAuthRequest: opts.SetXAuthRequest,
|
||||
PassBasicAuth: opts.PassBasicAuth,
|
||||
SetBasicAuth: opts.SetBasicAuth,
|
||||
PassUserHeaders: opts.PassUserHeaders,
|
||||
BasicAuthPassword: opts.BasicAuthPassword,
|
||||
PassAccessToken: opts.PassAccessToken,
|
||||
SetAuthorization: opts.SetAuthorization,
|
||||
PassAuthorization: opts.PassAuthorization,
|
||||
PreferEmailToUser: opts.PreferEmailToUser,
|
||||
SkipProviderButton: opts.SkipProviderButton,
|
||||
templates: loadTemplates(opts.CustomTemplatesDir),
|
||||
Banner: opts.Banner,
|
||||
Footer: opts.Footer,
|
||||
ProxyPrefix: opts.ProxyPrefix,
|
||||
provider: opts.GetProvider(),
|
||||
providerNameOverride: opts.ProviderName,
|
||||
sessionStore: opts.GetSessionStore(),
|
||||
serveMux: serveMux,
|
||||
redirectURL: redirectURL,
|
||||
whitelistDomains: opts.WhitelistDomains,
|
||||
skipAuthRegex: opts.SkipAuthRegex,
|
||||
skipAuthPreflight: opts.SkipAuthPreflight,
|
||||
skipJwtBearerTokens: opts.SkipJwtBearerTokens,
|
||||
mainJwtBearerVerifier: opts.GetOIDCVerifier(),
|
||||
extraJwtBearerVerifiers: opts.GetJWTBearerVerifiers(),
|
||||
compiledRegex: opts.GetCompiledRegex(),
|
||||
realClientIPParser: opts.GetRealClientIPParser(),
|
||||
SetXAuthRequest: opts.SetXAuthRequest,
|
||||
PassBasicAuth: opts.PassBasicAuth,
|
||||
SetBasicAuth: opts.SetBasicAuth,
|
||||
PassUserHeaders: opts.PassUserHeaders,
|
||||
BasicAuthPassword: opts.BasicAuthPassword,
|
||||
PassAccessToken: opts.PassAccessToken,
|
||||
SetAuthorization: opts.SetAuthorization,
|
||||
PassAuthorization: opts.PassAuthorization,
|
||||
PreferEmailToUser: opts.PreferEmailToUser,
|
||||
SkipProviderButton: opts.SkipProviderButton,
|
||||
templates: loadTemplates(opts.CustomTemplatesDir),
|
||||
Banner: opts.Banner,
|
||||
Footer: opts.Footer,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1139,15 +1141,24 @@ func (p *OAuthProxy) GetJwtSession(req *http.Request) (*sessionsapi.SessionState
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, verifier := range p.jwtBearerVerifiers {
|
||||
bearerToken, err := verifier.Verify(req.Context(), rawBearerToken)
|
||||
// If we are using an oidc provider, go ahead and try that provider first with its Verifier
|
||||
// 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 {
|
||||
logger.Printf("failed to verify bearer token: %v", err)
|
||||
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"))
|
||||
}
|
||||
|
@ -178,10 +178,6 @@ func Validate(o *options.Options) error {
|
||||
}
|
||||
|
||||
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
|
||||
if len(o.ExtraJwtIssuers) > 0 {
|
||||
var jwtIssuers []jwtIssuer
|
||||
|
@ -124,7 +124,6 @@ func newOIDCServer(body []byte) (*url.URL, *httptest.Server) {
|
||||
}
|
||||
|
||||
func newSignedTestIDToken(tokenClaims idTokenClaims) (string, error) {
|
||||
|
||||
key, _ := rsa.GenerateKey(rand.Reader, 2048)
|
||||
standardClaims := jwt.NewWithClaims(jwt.SigningMethodRS256, tokenClaims)
|
||||
return standardClaims.SignedString(key)
|
||||
|
@ -2,6 +2,10 @@ package providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"github.com/coreos/go-oidc"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
@ -47,3 +51,35 @@ func TestAcrValuesConfigured(t *testing.T) {
|
||||
result := p.GetLoginURL("https://my.test.app/oauth", "")
|
||||
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
Block a user