Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jwt validation #171

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,28 @@ CACHE_ALLOWED_STATUSES=200,301,302
# though it is recommended to specify them explicitly.
# Default: HEAD,GET
CACHE_ALLOWED_METHODS=HEAD,GET

# --- JWT
# A list of space-separated paths.
# JWT_EXCLUDED_PATHS=
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the same example values from config.yml.dist:

Suggested change
# JWT_EXCLUDED_PATHS=
# JWT_EXCLUDED_PATHS=/


# A list of space-separated scopes to be allowed.
# JWT_ALLOWED_SCOPES=
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the same example values from config.yml.dist:

Suggested change
# JWT_ALLOWED_SCOPES=
# JWT_ALLOWED_SCOPES=scope1, scope2


# The JSON Web Key Set (JWKS) URL where it is stored the the public keys used to verify the JSON Web Token (JWT).
# - For global configuration:
# JWT_JWKS_URL=
# - For domain configuration:
# JWT_JWKS_URL_<domain_name_specified_in_config.yml>=
# *e.g: JWT_JWKS_URL_example_com=http://testJwksUrl.com
# Global Configuration - The value of the JwksUrl field is taken by following this preference order:
# - JWT_JWKS_URL enviroment variable
# - global jwks_url variable in config.yaml
# Domain Configuration - The value of the JwksUrl field is taken by following this preference order:
# - JWT_JWKS_URL_<domain_name_specified_in_config.yml> enviroment variable
# - domain jwks_url variable specified in config.yaml
# - global jwks_url variable specified in config.yaml
# - JWT_JWKS_URL enviroment variable

# Time in minutes that takes for JWKS to refresh automatically
# JWT_REFRESH_INTERVAL=
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the same example values from config.yml.dist:

Suggested change
# JWT_REFRESH_INTERVAL=
# JWT_REFRESH_INTERVAL=15

13 changes: 13 additions & 0 deletions config.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,19 @@ tracing:
# Default: 1.0
sampling_ratio: 1.0

# --- JWT (careful, setting JWT config here affects all domains)
# jwt:
# # A list of space-separated paths.
# excluded_paths:
# - /
# # A list of space-separated scopes to be allowed.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space or comma separated?

# allowed_scopes:
# - scope1, scope2
# # The JSON Web Key Set (JWKS) URL where it is stored the the public keys used to verify the JSON Web Token (JWT).
# jwks_url: ~
# # Time in minutes that takes for JWKS to refresh automatically
# jwks_refresh_interval: 15

### PER DOMAIN CONFIGURATION OVERRIDE
################################################################################
domains:
Expand Down
30 changes: 30 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package config
// Repo: https://github.com/fabiocicerchia/go-proxy-cache

import (
"context"
"crypto/tls"
"fmt"
"os"
Expand All @@ -19,6 +20,7 @@ import (

"github.com/jinzhu/copier"
"github.com/kelseyhightower/envconfig"
"github.com/lestrrat-go/jwx/v2/jwk"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"

Expand Down Expand Up @@ -91,13 +93,30 @@ func loadYAMLFilefile(file string) (YamlConfig Configuration) {
return YamlConfig
}

// InitJWT - Configure the jwk auto-refresh and save it into the JWT config
func InitJWT(jwtConfig *Jwt) {
refreshIntervalDuration := time.Duration(jwtConfig.JwksRefreshInterval) * time.Minute
jwtKeyFetcher := jwk.NewCache(jwtConfig.Context, jwk.WithRefreshWindow(refreshIntervalDuration))
jwtKeyFetcher.Register(
jwtConfig.JwksUrl,
jwk.WithMinRefreshInterval(refreshIntervalDuration),
)
jwtConfig.JwkCache = jwtKeyFetcher
}

func copyGlobalOverDomainConfig(file string) {
if Config.Domains != nil {
domains := Config.Domains
for k, v := range domains {
domain := Config
domain.CopyOverWith(v, &file)
domain.Domains = Domains{}
domainName := k
_, isJWKSUrl := os.LookupEnv("JWT_JWKS_URL_" + domainName)
if isJWKSUrl {
domain.Jwt.JwksUrl = os.Getenv("JWT_JWKS_URL_" + domainName)
}
InitJWT(&domain.Jwt)
domains[k] = domain
}

Expand Down Expand Up @@ -137,6 +156,7 @@ func (c *Configuration) CopyOverWith(overrides Configuration, file *string) {
c.copyOverWithCache(overrides.Cache)
c.copyOverWithTracing(overrides.Tracing)
c.copyOverWithLog(overrides.Log)
c.copyOverWithJwt(overrides.Jwt)
}

// --- SERVER.
Expand Down Expand Up @@ -217,6 +237,16 @@ func (c *Configuration) copyOverWithLog(overrides Log) {
c.Log.SyslogEndpoint = utils.Coalesce(overrides.SyslogEndpoint, c.Log.SyslogEndpoint).(string)
}

// --- JWT.
func (c *Configuration) copyOverWithJwt(overrides Jwt) {
c.Jwt.ExcludedPaths = utils.Coalesce(overrides.ExcludedPaths, c.Jwt.ExcludedPaths).([]string)
c.Jwt.AllowedScopes = utils.Coalesce(overrides.AllowedScopes, c.Jwt.AllowedScopes).([]string)
c.Jwt.JwksUrl = utils.Coalesce(overrides.JwksUrl, c.Jwt.JwksUrl).(string)
c.Jwt.JwksRefreshInterval = utils.Coalesce(overrides.JwksRefreshInterval, c.Jwt.JwksRefreshInterval).(int)
c.Jwt.Context = context.Background()
c.Jwt.Logger = log.New()
}

// Print - Shows the current configuration.
func Print() {
obfuscatedConfig := Configuration{}
Expand Down
21 changes: 21 additions & 0 deletions config/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ package config
// Repo: https://github.com/fabiocicerchia/go-proxy-cache

import (
"context"
"crypto/tls"
"net/http"
"time"

"github.com/fabiocicerchia/go-proxy-cache/utils"
circuitbreaker "github.com/fabiocicerchia/go-proxy-cache/utils/circuit-breaker"
"github.com/lestrrat-go/jwx/v2/jwk"
"github.com/sirupsen/logrus"
)

// DefaultTimeoutRead - Default value used for http.Server.ReadTimeout
Expand Down Expand Up @@ -57,6 +60,7 @@ type Configuration struct {
Log Log `yaml:"log"`
Tracing Tracing `yaml:"tracing"`
domainsCache map[string]Configuration
Jwt Jwt `yaml:"jwt"`
}

// Domains - Overrides per domain.
Expand Down Expand Up @@ -162,6 +166,23 @@ type DomainSet struct {
Scheme string
}

// Jwt - Defines the config for the jwt validation.
type Jwt struct {
ExcludedPaths []string `yaml:"excluded_paths" envconfig:"JWT_EXCLUDED_PATHS" split_words:"true"`
AllowedScopes []string `yaml:"allowed_scopes" envconfig:"JWT_ALLOWED_SCOPES" split_words:"true"`
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scope1, scope2 will end up in having item 0 scope1, and item 1 scope2

JwksUrl string `yaml:"jwks_url" envconfig:"JWT_JWKS_URL"`
JwksRefreshInterval int `yaml:"jwks_refresh_interval" envconfig:"JWT_REFRESH_INTERVAL" default:"15"`
JwkCache *jwk.Cache
Context context.Context
Logger *logrus.Logger
}

// Jwt - Defines the jwt validation error.
type JwtError struct {
ErrorCode string `json:"errorCode"`
ErrorDescription string `json:"errorDescription"`
}

// Config - Holds the server configuration.
var Config Configuration = Configuration{
Server: Server{
Expand Down
18 changes: 18 additions & 0 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
- `TLS_KEY_FILE`
- `TRACING_ENABLED`
- `TRACING_JAEGER_ENDPOINT`
- `JWT_EXCLUDED_PATHS`
- `JWT_ALLOWED_SCOPES`
- `JWT_JWKS_URL`
- `JWT_JWKS_URL_<domain_name_specified_in_config.yml>`
- `JWT_REFRESH_INTERVAL`

## YAML

Expand Down Expand Up @@ -353,6 +358,19 @@ tracing:
# Default: 1.0
sampling_ratio: 1.0

# --- JWT
# jwt:
# # A list of space-separated paths.
# excluded_paths:
# - /
# # A list of space-separated scopes to be allowed.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to clarify if it is space or comma separated

# allowed_scopes:
# - scope1, scope2
# # The JSON Web Key Set (JWKS) URL where it is stored the the public keys used to verify the JSON Web Token (JWT).
# jwks_url: ~
# # Time in minutes that takes for JWKS to refresh automatically
# jwks_refresh_interval: 15

### PER DOMAIN CONFIGURATION OVERRIDE
################################################################################
domains:
Expand Down
53 changes: 30 additions & 23 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,27 @@ require (
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a
github.com/go-redis/redis/v8 v8.11.5
github.com/go-redsync/redsync/v4 v4.10.0
github.com/gorilla/websocket v1.5.0
github.com/go-redsync/redsync/v4 v4.12.1
github.com/gorilla/websocket v1.5.1
github.com/jinzhu/copier v0.4.0
github.com/kelseyhightower/envconfig v1.4.0
github.com/lestrrat-go/jwx/v2 v2.0.21
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.17.0
github.com/prometheus/client_golang v1.19.0
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529
github.com/rs/xid v1.5.0
github.com/sirupsen/logrus v1.9.3
github.com/sony/gobreaker v0.5.0
github.com/stretchr/testify v1.8.4
github.com/ugorji/go/codec v1.2.11
github.com/stretchr/testify v1.9.0
github.com/ugorji/go/codec v1.2.12
github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0
go.opentelemetry.io/otel v1.21.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0
go.opentelemetry.io/otel v1.24.0
go.opentelemetry.io/otel/exporters/jaeger v1.17.0
go.opentelemetry.io/otel/sdk v1.21.0
go.opentelemetry.io/otel/trace v1.21.0
golang.org/x/crypto v0.14.0
golang.org/x/net v0.17.0
go.opentelemetry.io/otel/sdk v1.24.0
go.opentelemetry.io/otel/trace v1.24.0
golang.org/x/crypto v0.21.0
golang.org/x/net v0.22.0
gopkg.in/yaml.v2 v2.4.0
)

Expand All @@ -35,24 +36,30 @@ require (
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/getsentry/raven-go v0.2.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc v1.0.5 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
go.opentelemetry.io/otel/metric v1.21.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/segmentio/asm v1.2.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading
Loading