diff --git a/.cspell.json b/.cspell.json new file mode 100644 index 0000000..d64540d --- /dev/null +++ b/.cspell.json @@ -0,0 +1,61 @@ +{ + "language": "en", + "dictionaries": ["companies", "filetypes", "fullstack", "softwareTerms"], + "words": [ + "trufflehog", + "golangci", + "godotenv", + "doublestar", + "clientcredentials", + "logrus", + "nosniff", + "tcsh", + "jasig", + "linuxfoundation", + "jaegertracing", + "pprof", + "zpages", + "fluentbit", + "chainguard", + "hadolint", + "GOARCH", + "trimpath", + "ldflags", + "nonroot", + "otelhttp", + "vhost", + "hostmetrics", + "otelcol", + "otlptracegrpc", + "sdktrace", + "tracecontext", + "semconv", + "securecookie", + "zoneinfo", + "chardata" + ], + "flagWords": [ + "abort", + "abortion", + "blackhat", + "black-hat", + "whitehat", + "white-hat", + "cripple", + "crippled", + "master", + "slave", + "tribe", + "sanity-check", + "whitelist", + "white-list", + "blacklist", + "black-list" + ], + "ignorePaths": [ + ".cspell.json", + "LICENSE", + "LICENSE-docs", + "megalinter-reports" + ] +} diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 2ea5b6c..8a2b425 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -30,4 +30,4 @@ jobs: - name: MegaLinter id: ml # Use the Go flavor. - uses: oxsecurity/megalinter/flavors/go@v7 + uses: oxsecurity/megalinter/flavors/go@v8 diff --git a/.mega-linter.yml b/.mega-linter.yml index 79afc0b..b6833e2 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -5,8 +5,6 @@ DISABLE_LINTERS: # Revive covers this, plus golangci-lint has trouble with newer go toolchains # in go.mod. - GO_GOLANGCI_LINT - # cspell is laughably bad at code/comments/etc. - - SPELL_CSPELL # Link checking more likely to cause false positives than be useful for us. - SPELL_LYCHEE # yamllint is sufficient for us. diff --git a/0_config.go b/0_config.go index 75547fe..79c0291 100644 --- a/0_config.go +++ b/0_config.go @@ -4,6 +4,7 @@ // The auth0-cas-service-go service. package main +// spell-checker:disable import ( "fmt" "os" @@ -13,6 +14,8 @@ import ( "github.com/sirupsen/logrus" ) +// spell-checker:enable + type config struct { Auth0Tenant string Auth0Domain string diff --git a/Dockerfile b/Dockerfile index e603140..d18d318 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,8 +6,8 @@ FROM --platform=$BUILDPLATFORM cgr.dev/chainguard/go:latest AS builder -# Set necessary environment variables needed for our image. Allow building to -# other architectures via cross-compliation build-arg. +# Set necessary environment variables needed for our image. Allow cross-compile +# builds to other architectures via build-arg. ARG TARGETARCH ENV CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH diff --git a/Makefile b/Makefile index ce0cc27..95e17da 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,8 @@ bin/auth0-cas-server-go: *.go go.mod go.sum all: bin/auth0-cas-server-go docker-build lint: - docker pull --platform linux/amd64 oxsecurity/megalinter-go:v7 - docker run --rm --platform linux/amd64 -v '$(CURDIR):/tmp/lint:rw' oxsecurity/megalinter-go:v7 + docker pull --platform linux/amd64 oxsecurity/megalinter-go:v8 + docker run --rm --platform linux/amd64 -v '$(CURDIR):/tmp/lint:rw' oxsecurity/megalinter-go:v8 test: @echo "No tests to run ... would you like to 'make lint'?" diff --git a/README.md b/README.md index b67cf25..12e1391 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,18 @@ This service was inspired by Auth0, through their `auth0-cas-server` service formerly hosted at `github.com/auth0-samples/auth0-cas-server` (link now dead). -It is a simple authentication redirector which wraps an OpenID Connect -authentication flow to expose it as server implementing the Central -Authentication Service (CAS) SSO protocol. The service leverages configuration -stored within Auth0 client metadata, which it reads using a privileged -connection to the Auth0 API, in order to emulate multiple different clients -dynamically per login session. +Like that service, it uses HTTP redirects to wrap an OpenID Connect +authentication flow with the Central Authentication Service (CAS) SSO protocol, +emulating multiple CAS clients from a single instance of the service. It does +this by using a privileged connection to the Auth0 Management API to find +clients tagged with CAS metadata, and dynamically adopting their client +credentials. -Notable differeces with this implementation: +Notable differences include: - Rewritten in Go, including OpenTelemetry instrumentation and multi-arch build outputs including SPDX SBOMs. -- Supports several additional CAS protocol endpoints implementing multiple CAS - versions. +- Additional HTTP endpoints to implement additional CAS protocol versions. - Implements CAS single-logout. - Implements CAS "gateway mode" to test for authentication without prompting the user. @@ -55,7 +54,19 @@ Please see `env-example` for a list of required and optional environment variables that can be used to configure the server. For local development, you can copy this file to `.env` and modify it to suit your needs. -## Auth0 client configuration +## Auth0 API client configuration + +This service requires a non-interactive (machine-to-machine) client that +supports the `client_credentials` grant type and is authorized for the +following scopes on the Auth0 Management API: + +- `read:clients` +- `read:client_keys` + +The client ID and client secret for this API client must be passed as +environmental variables to the service. + +## Auth0 CAS client configuration To create a CAS-enabled Auth0 application, specify the follow settings: diff --git a/auth0_clients.go b/auth0_clients.go index 4ab2abf..782a99f 100644 --- a/auth0_clients.go +++ b/auth0_clients.go @@ -4,6 +4,7 @@ // The auth0-cas-service-go service. package main +// spell-checker:disable import ( "context" "encoding/json" @@ -22,6 +23,8 @@ import ( "golang.org/x/oauth2/clientcredentials" ) +// spell-checker:enable + var ( auth0Client *http.Client auth0Cache = cache.New(60*time.Minute, 5*time.Minute) @@ -171,7 +174,7 @@ func getAuth0ClientByService(ctx context.Context, serviceURL string) (*auth0Clie } // There is a match - appLogger(ctx).WithFields(logrus.Fields{"service": serviceURL, "glob": glob, "auth0_client": client.Name}).Debugln("matched service in glob cache") + appLogger(ctx).WithFields(logrus.Fields{"service": serviceURL, "glob": glob, "auth0_client": client.Name}).Debug("matched service in glob cache") auth0Cache.Set("cas-service-url/"+url.PathEscape(serviceURL), client, cache.NoExpiration) return &client, nil } @@ -204,7 +207,7 @@ func getAuth0ClientByService(ctx context.Context, serviceURL string) (*auth0Clie serviceGlobs := strings.Split(client.ClientMetadata["cas_service"], ",") - // Iterate over any comma-delimeted cas_service globs in the + // Iterate over any comma-delimited cas_service globs in the // client_metadata. for _, glob := range serviceGlobs { match, err := doublestar.Match(glob, serviceURL) @@ -222,7 +225,7 @@ func getAuth0ClientByService(ctx context.Context, serviceURL string) (*auth0Clie continue } - appLogger(ctx).WithFields(logrus.Fields{"service": serviceURL, "glob": glob, "auth0_client": client.Name}).Debugln("matched service") + appLogger(ctx).WithFields(logrus.Fields{"service": serviceURL, "glob": glob, "auth0_client": client.Name}).Debug("matched service") // If the glob matches, save the match, but keep processing remaining // comma-delimited globs AND clients to complete the glob-to-client cache // update. diff --git a/cas.go b/cas.go index b59c833..bf6c0da 100644 --- a/cas.go +++ b/cas.go @@ -4,6 +4,7 @@ // The auth0-cas-service-go service. package main +// spell-checker:disable import ( "context" "crypto/rand" @@ -21,6 +22,8 @@ import ( "golang.org/x/oauth2" ) +// spell-checker:enable + var store *sessions.CookieStore type userAttributes struct { diff --git a/check-headers.sh b/check-headers.sh index c9f42a5..582c118 100755 --- a/check-headers.sh +++ b/check-headers.sh @@ -8,7 +8,7 @@ # Exits with a 1 if one or more source files are missing a license header # Exclude code coming from a third-party. Typically these won't be checked into -# source control, but occassionally "vendored" code is committed. +# source control, but occasionally "vendored" code is committed. exclude_pattern='^(.*/)?(node_modules|vendor)/' # Include build definitions. diff --git a/go.mod b/go.mod index 0d8b1cc..d4bb8a6 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/linuxfoundation/auth0-cas-server-go -go 1.23.6 +go 1.24.2 require ( github.com/bmatcuk/doublestar/v4 v4.8.1 @@ -12,13 +12,13 @@ require ( github.com/joho/godotenv v1.5.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/sirupsen/logrus v1.9.3 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 - go.opentelemetry.io/otel v1.34.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 - go.opentelemetry.io/otel/sdk v1.34.0 - go.opentelemetry.io/otel/trace v1.34.0 - golang.org/x/oauth2 v0.26.0 - golang.org/x/text v0.22.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 + go.opentelemetry.io/otel v1.35.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 + go.opentelemetry.io/otel/sdk v1.35.0 + go.opentelemetry.io/otel/trace v1.35.0 + golang.org/x/oauth2 v0.29.0 + golang.org/x/text v0.24.0 ) require ( @@ -30,17 +30,17 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect github.com/tinylib/msgp v1.2.5 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect - go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect + go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect - golang.org/x/net v0.34.0 // indirect - golang.org/x/sys v0.30.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 // indirect - google.golang.org/grpc v1.70.0 // indirect - google.golang.org/protobuf v1.36.5 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/sys v0.32.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a // indirect + google.golang.org/grpc v1.71.1 // indirect + google.golang.org/protobuf v1.36.6 // indirect ) diff --git a/go.sum b/go.sum index 1d6bc26..dba154c 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -30,8 +30,8 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 h1:VD1gqscl4nYs1YxVuSdemTrSgTKrwOWDK0FVFMqm+Cg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -56,43 +56,43 @@ github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po= github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= -go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= -go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= -go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= -go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= -go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= -go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= -go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= +go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= +go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= +go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= +go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= -golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= +golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o= -google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489 h1:5bKytslY8ViY0Cj/ewmRtrWHW64bNF03cAatUUFCdFI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250204164813-702378808489/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk= -google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= -google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a h1:OQ7sHVzkx6L57dQpzUS4ckfWJ51KDH74XHTDe23xWAs= +google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a/go.mod h1:2R6XrVC8Oc08GlNh8ujEpc7HkLiEZ16QeY7FxIs20ac= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a h1:GIqLhp/cYUkuGuiT+vJk8vhOP86L4+SP5j8yXgeVpvI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/main.go b/main.go index c91b597..2c1e67b 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ // The auth0-cas-service-go service. package main +// spell-checker:disable import ( "context" _ "expvar" @@ -21,6 +22,8 @@ import ( "go.opentelemetry.io/otel/trace" ) +// spell-checker:enable + type contextID int const ( @@ -35,8 +38,8 @@ var ( // main parses optional flags and starts http listener. func main() { var debug = flag.Bool("d", false, "enable debug logging") - var logJSON = flag.Bool("json", false, "force json logging to console (default: autodetect enviroment)") - var noTrace = flag.Bool("notrace", false, "disable OTLP tracing output") + var logJSON = flag.Bool("json", false, "force json logging to console (default: autodetect environment)") + var noTrace = flag.Bool("no-trace", false, "disable OTLP tracing output") var port = flag.String("p", "5000", "port") var bind = flag.String("bind", "*", "interface to bind on") flag.Usage = func() { diff --git a/responses.go b/responses.go index 47b4154..474d2ee 100644 --- a/responses.go +++ b/responses.go @@ -4,6 +4,7 @@ // The auth0-cas-service-go service. package main +// spell-checker:disable import ( "encoding/json" "encoding/xml" @@ -14,12 +15,14 @@ import ( "golang.org/x/text/unicode/norm" ) +// spell-checker:enable + type casValidationResponse struct { ServiceResponse casServiceResponse `json:"serviceResponse" xml:"-"` } type casServiceResponse struct { - // I'm not able to get xmlnas:cas to show up using native namespace in + // I'm not able to get `xmlns:cas` to show up using native namespace in // XMLName, so we're using a workaround of setting a XMLNS attribute. XMLName xml.Name `json:"-" xml:"cas:serviceResponse"` XMLNS string `json:"-" xml:"xmlns:cas,attr"` @@ -38,19 +41,20 @@ type casAttributes struct { // document, and we are preserving as much as possible the output from // our reference implementation. (Including first/full/last for field_* but // first/last/full for profile_*). - AttraStyle string `json:"-" xml:"cas:attraStyle"` - UID string `json:"-" xml:"cas:uid"` - Email string `json:"email" xml:"cas:mail"` - Created uint64 `json:"-" xml:"cas:created"` - Timezone string `json:"timezone,omitempty" xml:"cas:timezone,omitempty"` - Language string `json:"-" xml:"cas:language"` - Groups []string `json:"groups" xml:"cas:group,omitempty"` - GivenName string `json:"given_name" xml:"cas:field_lf_first_name"` - FullName string `json:"name" xml:"cas:field_lf_full_name"` - FamilyName string `json:"family_name" xml:"cas:field_lf_last_name"` - GivenNameOld string `json:"-" xml:"cas:profile_name_first"` - FamilyNameOld string `json:"-" xml:"cas:profile_name_last"` - FullNameOld string `json:"-" xml:"cas:profile_name_full"` + // cspell:disable-next-line + AttributesStyle string `json:"-" xml:"cas:attraStyle"` + UID string `json:"-" xml:"cas:uid"` + Email string `json:"email" xml:"cas:mail"` + Created uint64 `json:"-" xml:"cas:created"` + Timezone string `json:"timezone,omitempty" xml:"cas:timezone,omitempty"` + Language string `json:"-" xml:"cas:language"` + Groups []string `json:"groups" xml:"cas:group,omitempty"` + GivenName string `json:"given_name" xml:"cas:field_lf_first_name"` + FullName string `json:"name" xml:"cas:field_lf_full_name"` + FamilyName string `json:"family_name" xml:"cas:field_lf_last_name"` + GivenNameOld string `json:"-" xml:"cas:profile_name_first"` + FamilyNameOld string `json:"-" xml:"cas:profile_name_last"` + FullNameOld string `json:"-" xml:"cas:profile_name_full"` } type casAuthenticationFailure struct { @@ -59,6 +63,7 @@ type casAuthenticationFailure struct { } var ( + // spell-checker:disable // mb4RE matches anything outside the range of mb3 characters (\u0000-\uD7FF and // \uE000-\uEEEE) with mb3 emoji excluded (\u203C-\u26ff). mb4RE = regexp.MustCompile(`[^\x{0000}-\x{203B}\x{2700}-\x{D7FF}\x{E000}-\x{FFFF}]`) @@ -67,6 +72,8 @@ var ( // usernames. mbIllegalRE = regexp.MustCompile(`[\x{80}-\x{A0}\x{AD}\x{2000}-\x{200F}\x{2028}-\x{202F}\x{205F}-\x{206F}\x{FEFF}\x{FF01}-\x{FF60}\x{FFF9}-\x{FFFD}\x{0}-\x{1F}]`) spacesRE = regexp.MustCompile(`[[:space:]]+`) + + // spell-checker:enable ) func validationResponse(success *casAuthenticationSuccess, failure *casAuthenticationFailure, useJSON bool) (string, error) { @@ -105,9 +112,9 @@ func validationResponse(success *casAuthenticationSuccess, failure *casAuthentic // Normalize processes a passed attributes object and ensure attributes are // safe for storage in MySQL legacy utf8 (3-byte encoding). func (attr *casAttributes) Normalize() { - // Set AttraStyle to the default "jasig" if unset. - if attr.AttraStyle == "" { - attr.AttraStyle = "Jasig" + // Set phpCAS "attributes style" flag to the default if unset. + if attr.AttributesStyle == "" { + attr.AttributesStyle = "Jasig" } // Normalize name(s). diff --git a/tracing.go b/tracing.go index bf501cc..0846ea5 100644 --- a/tracing.go +++ b/tracing.go @@ -4,6 +4,7 @@ // The auth0-cas-service-go service. package main +// spell-checker:disable import ( "context" "os" @@ -18,6 +19,8 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.10.0" ) +// spell-checker:enable + type otelErrorHandler struct{} func (h *otelErrorHandler) Handle(err error) {