diff --git a/api/middleware/auth/authentication.go b/api/middleware/auth/authentication.go index ac2ce272..b722bc9b 100644 --- a/api/middleware/auth/authentication.go +++ b/api/middleware/auth/authentication.go @@ -94,7 +94,7 @@ func NewZerologAuthenticationDetailsMiddleware() negroni.HandlerFunc { logContext := log.Ctx(ctx).With() if user.IsAuthenticated() { - logContext = logContext.Str("azure_oid", user.Id()) + logContext = logContext.Str("user_id", user.Id()) } else { logContext = logContext.Bool("anonymous", true) } diff --git a/api/utils/token/unchecked_principal.go b/api/utils/token/unchecked_principal.go new file mode 100644 index 00000000..8073d857 --- /dev/null +++ b/api/utils/token/unchecked_principal.go @@ -0,0 +1,52 @@ +package token + +import ( + "context" + "fmt" + + "github.com/go-jose/go-jose/v4/jwt" +) + +func (c *unchechedClaimsPrincipal) Validate(_ context.Context) error { + return nil +} + +type unchechedClaimsPrincipal struct { + token string + claims *jwt.Claims + azureClaims *azureClaims +} + +func (p *unchechedClaimsPrincipal) Token() string { + return p.token +} +func (p *unchechedClaimsPrincipal) IsAuthenticated() bool { + return true +} +func (p *unchechedClaimsPrincipal) Id() string { + if p.azureClaims.ObjectId != "" { + return fmt.Sprintf("oid:%s", p.azureClaims.ObjectId) + } + + return fmt.Sprintf("sub:%s", p.claims.Subject) +} + +func (p *unchechedClaimsPrincipal) Name() string { + if p.azureClaims.Upn != "" { + return p.azureClaims.Upn + } + + if p.azureClaims.AppDisplayName != "" { + return p.azureClaims.AppDisplayName + } + + if p.azureClaims.AppId != "" { + return p.azureClaims.AppId + } + + if p.azureClaims.ObjectId != "" { + return p.azureClaims.ObjectId + } + + return p.claims.Subject +} diff --git a/api/utils/token/unchecked_validator.go b/api/utils/token/unchecked_validator.go new file mode 100644 index 00000000..4446be22 --- /dev/null +++ b/api/utils/token/unchecked_validator.go @@ -0,0 +1,36 @@ +package token + +import ( + "context" + "fmt" + "net/url" + + "github.com/equinor/radix-common/net/http" + "github.com/go-jose/go-jose/v4" + josejwt "github.com/go-jose/go-jose/v4/jwt" +) + +type UncheckedValidator struct{} + +var _ ValidatorInterface = &UncheckedValidator{} + +func NewUncheckedValidator(_ *url.URL, _ string) (*UncheckedValidator, error) { + return &UncheckedValidator{}, nil +} + +func (v *UncheckedValidator) ValidateToken(_ context.Context, token string) (TokenPrincipal, error) { + var registeredClaims josejwt.Claims + var azureClaims azureClaims + + jwt, err := josejwt.ParseSigned(token, []jose.SignatureAlgorithm{jose.HS256, jose.RS256}) + if err != nil { + return nil, http.ForbiddenError("invalid token") + } + err = jwt.UnsafeClaimsWithoutVerification(®isteredClaims, &azureClaims) + if err != nil { + return nil, http.ForbiddenError(fmt.Sprintf("failed to extract JWT unsafeClaims: %s", err.Error())) + } + + principal := &unchechedClaimsPrincipal{token: token, claims: ®isteredClaims, azureClaims: &azureClaims} + return principal, nil +} diff --git a/go.mod b/go.mod index 4dac852e..23fb4970 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,10 @@ require ( github.com/cert-manager/cert-manager v1.15.0 github.com/equinor/radix-common v1.9.5 github.com/equinor/radix-job-scheduler v1.11.0 - github.com/equinor/radix-operator v1.61.0 + github.com/equinor/radix-operator v1.62.0 github.com/evanphx/json-patch/v5 v5.9.0 github.com/felixge/httpsnoop v1.0.4 + github.com/go-jose/go-jose/v4 v4.0.2 github.com/golang/mock v1.6.0 github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 diff --git a/go.sum b/go.sum index a21e0507..d3fb7c3f 100644 --- a/go.sum +++ b/go.sum @@ -91,6 +91,8 @@ github.com/equinor/radix-job-scheduler v1.11.0 h1:8wCmXOVl/1cto8q2WJQEE06Cw68/Qm github.com/equinor/radix-job-scheduler v1.11.0/go.mod h1:yPXn3kDcMY0Z3kBkosjuefsdY1x2g0NlBeybMmHz5hc= github.com/equinor/radix-operator v1.61.0 h1:kHWHn5p9S+wKqOTSKtju2URW5FKgAFng1p6RLRnaTmE= github.com/equinor/radix-operator v1.61.0/go.mod h1:uRW9SgVZ94hkpq87npVv2YVviRuXNJ1zgCleya1uvr8= +github.com/equinor/radix-operator v1.62.0 h1:lurDVymrDhlyopd46KMV28eUltrVUPCk3bnBRFuyCsU= +github.com/equinor/radix-operator v1.62.0/go.mod h1:uRW9SgVZ94hkpq87npVv2YVviRuXNJ1zgCleya1uvr8= github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls= github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= @@ -107,6 +109,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk= +github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= diff --git a/main.go b/main.go index 65a4f041..c6848f57 100644 --- a/main.go +++ b/main.go @@ -76,14 +76,15 @@ func initializeServer(c config.Config) *http.Server { return srv } -func initializeTokenValidator(c config.Config) *token.Validator { +func initializeTokenValidator(c config.Config) token.ValidatorInterface { issuerUrl, err := url.Parse(c.OidcIssuer) if err != nil { log.Fatal().Err(err).Msg("Error parsing issuer url") } // Set up the validator. - jwtValidator, err := token.NewValidator(issuerUrl, c.OidcAudience) + // jwtValidator, err := token.NewValidator(issuerUrl, c.OidcAudience) + jwtValidator, err := token.NewUncheckedValidator(issuerUrl, c.OidcAudience) if err != nil { log.Fatal().Err(err).Msg("Error creating JWT validator") }