github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/plugin/oauth2/jwt_manager.go (about)

     1  package oauth2
     2  
     3  import (
     4  	"context"
     5  
     6  	jwtBase "github.com/dgrijalva/jwt-go"
     7  	"github.com/hellofresh/janus/pkg/jwt"
     8  	"github.com/hellofresh/janus/pkg/metrics"
     9  	obs "github.com/hellofresh/janus/pkg/observability"
    10  	"github.com/hellofresh/stats-go/bucket"
    11  	"github.com/hellofresh/stats-go/client"
    12  	log "github.com/sirupsen/logrus"
    13  	"go.opencensus.io/stats"
    14  	"go.opencensus.io/tag"
    15  )
    16  
    17  // JWTManager is responsible for managing the JWT tokens
    18  type JWTManager struct {
    19  	parser *jwt.Parser
    20  }
    21  
    22  // NewJWTManager creates a new instance of JWTManager
    23  func NewJWTManager(parser *jwt.Parser) *JWTManager {
    24  	return &JWTManager{parser}
    25  }
    26  
    27  // IsKeyAuthorized checks if the access token is valid
    28  func (m *JWTManager) IsKeyAuthorized(ctx context.Context, accessToken string) bool {
    29  	if ctx == nil {
    30  		return false
    31  	}
    32  
    33  	stats := metrics.WithContext(ctx)
    34  	if stats == nil {
    35  		return false
    36  	}
    37  
    38  	if _, err := m.parser.Parse(accessToken); err != nil {
    39  		log.WithError(err).Info("Failed to parse and validate the JWT")
    40  
    41  		switch jwtErr := err.(type) {
    42  		case *jwtBase.ValidationError:
    43  			shouldReport(ctx, stats, jwtErr.Errors&jwtBase.ValidationErrorExpired != 0, "ValidationErrorExpired")
    44  			shouldReport(ctx, stats, jwtErr.Errors&jwtBase.ValidationErrorClaimsInvalid != 0, "ValidationErrorClaimsInvalid")
    45  			shouldReport(ctx, stats, jwtErr.Errors&jwtBase.ValidationErrorIssuedAt != 0, "ValidationErrorIssuedAt")
    46  			shouldReport(ctx, stats, jwtErr.Errors&jwtBase.ValidationErrorNotValidYet != 0, "ValidationErrorNotValidYet")
    47  			shouldReport(ctx, stats, jwtErr.Errors&jwtBase.ValidationErrorIssuer != 0, "ValidationErrorIssuer")
    48  			shouldReport(ctx, stats, jwtErr.Errors&jwtBase.ValidationErrorMalformed != 0, "ValidationErrorMalformed")
    49  			shouldReport(ctx, stats, jwtErr.Errors&jwtBase.ValidationErrorSignatureInvalid != 0, "ValidationErrorSignatureInvalid")
    50  			shouldReport(ctx, stats, jwtErr.Errors&jwtBase.ValidationErrorUnverifiable != 0, "ValidationErrorUnverifiable")
    51  			return false
    52  		default:
    53  			shouldReport(ctx, stats, true, "ErrFailedToParse")
    54  			return false
    55  		}
    56  	}
    57  
    58  	return true
    59  }
    60  
    61  func shouldReport(ctx context.Context, client client.Client, typeCheck bool, operation string) {
    62  	if typeCheck {
    63  		client.TrackMetric("tokens", bucket.MetricOperation{"jwt-manager", "parse-error", operation})
    64  
    65  		// OpenCensus stats
    66  		ctx, _ := tag.New(ctx, tag.Insert(obs.KeyJWTValidationErrorType, operation))
    67  		stats.Record(ctx, obs.MJWTManagerValidationErrors.M(1))
    68  
    69  	}
    70  }