diff --git a/configs/config.hcl b/configs/config.hcl index f2b40b5a7..87a72f8f2 100644 --- a/configs/config.hcl +++ b/configs/config.hcl @@ -210,6 +210,9 @@ okta { // disabled disables Okta authorization. disabled = true + + // jwt_signer is the trusted signer for the ALB JWT header. + jwt_signer = "" } // postgres configures PostgreSQL as the app database. diff --git a/internal/auth/oktaalb/oktaalb.go b/internal/auth/oktaalb/oktaalb.go index a9e6487d8..ac762ffca 100644 --- a/internal/auth/oktaalb/oktaalb.go +++ b/internal/auth/oktaalb/oktaalb.go @@ -37,6 +37,9 @@ type Config struct { // Disabled disables Okta authorization. Disabled bool `hcl:"disabled,optional"` + + // JWTSigner is the trusted signer for the ALB JWT header. + JWTSigner string `hcl:"jwt_signer,optional"` } // New returns a new Okta authorizer. @@ -72,6 +75,10 @@ func (oa *OktaAuthorizer) EnforceOktaAuth(next http.Handler) http.Handler { // verifyOIDCToken checks if the request is authorized and returns the user // identity. func (oa *OktaAuthorizer) verifyOIDCToken(r *http.Request) (string, error) { + if oa.cfg.JWTSigner == "" { + return "", fmt.Errorf("JWT signer not configured") + } + // Get the key ID from JWT headers (the kid field). encodedJWT := r.Header.Get("x-amzn-oidc-data") if encodedJWT == "" { @@ -96,6 +103,15 @@ func (oa *OktaAuthorizer) verifyOIDCToken(r *http.Request) (string, error) { return "", fmt.Errorf("kid not found in decoded JSON") } + // Validate signer. + signer, ok := decodedJSON["signer"].(string) + if !ok { + return "", fmt.Errorf("signer not found in decoded JSON") + } + if signer != oa.cfg.JWTSigner { + return "", fmt.Errorf("unexpected signer: %s", signer) + } + // Get the public key from the regional endpoint. url := fmt.Sprintf("https://public-keys.auth.elb.%s.amazonaws.com/%s", oa.cfg.AWSRegion, kid) diff --git a/internal/cmd/commands/server/server.go b/internal/cmd/commands/server/server.go index 8f964565a..a25c73ebf 100644 --- a/internal/cmd/commands/server/server.go +++ b/internal/cmd/commands/server/server.go @@ -144,6 +144,9 @@ func (c *Command) Run(args []string) int { cfg.Okta.Disabled = true } } + if val, ok := os.LookupEnv("HERMES_SERVER_OKTA_JWT_SIGNER"); ok { + cfg.Okta.JWTSigner = val + } if c.flagOktaDisabled { cfg.Okta.Disabled = true } @@ -193,6 +196,10 @@ func (c *Command) Run(args []string) int { c.UI.Error("error initializing server: Okta client ID is required") return 1 } + if cfg.Okta.JWTSigner == "" { + c.UI.Error("error initializing server: Okta JWT signer is required") + return 1 + } } // Initialize Datadog.