github.com/verrazzano/verrazzano@v1.7.0/authproxy/src/auth/token.go (about) 1 // Copyright (c) 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package auth 5 6 import ( 7 "context" 8 "encoding/base64" 9 "encoding/json" 10 "fmt" 11 "net/http" 12 "strings" 13 "time" 14 15 "github.com/coreos/go-oidc/v3/oidc" 16 ) 17 18 // AuthenticateToken verifies a given bearer token against the OIDC key and verifies the issuer is correct 19 func (a *OIDCAuthenticator) AuthenticateToken(ctx context.Context, token string) (bool, error) { 20 verifier, err := a.loadVerifier() 21 if err != nil { 22 return false, err 23 } 24 25 idToken, err := verifier.Verify(ctx, token) 26 if err != nil { 27 a.Log.Errorf("Failed to verify JWT token: %v", err) 28 return false, err 29 } 30 31 // Do issuer check for external URL 32 // This is skipped in the go-oidc package because it could be the service or the ingress 33 if idToken.Issuer != a.oidcConfig.ExternalURL && idToken.Issuer != a.oidcConfig.ServiceURL { 34 err := fmt.Errorf("failed to verify issuer, got %s, expected %s or %s", idToken.Issuer, a.oidcConfig.ServiceURL, a.oidcConfig.ExternalURL) 35 a.Log.Errorf("Failed to validate JWT issuer: %v", err) 36 return false, err 37 } 38 39 return true, nil 40 } 41 42 // getTokenFromAuthHeader returns the bearer token from the authorization header 43 func getTokenFromAuthHeader(authHeader string) (string, error) { 44 splitHeader := strings.SplitN(authHeader, " ", 3) 45 46 if len(splitHeader) < 2 || !strings.EqualFold(splitHeader[0], authTypeBearer) { 47 return "", fmt.Errorf("failed to verify authorization bearer header") 48 } 49 50 return splitHeader[1], nil 51 } 52 53 // initServiceOIDCVerifier creates an OIDC provider using the Service URL 54 // and populates the authenticator with a verifier 55 func (a *OIDCAuthenticator) initServiceOIDCVerifier() error { 56 if a.oidcConfig == nil { 57 err := fmt.Errorf("the OIDC config is not initialized") 58 a.Log.Errorf("Failed to set up token verifier: %v", err) 59 return err 60 } 61 62 provider, err := oidc.NewProvider(context.TODO(), a.oidcConfig.ServiceURL) 63 if err != nil { 64 a.Log.Errorf("Failed to load OIDC provider: %v", err) 65 return err 66 } 67 68 config := &oidc.Config{ 69 ClientID: a.oidcConfig.ClientID, 70 SkipIssuerCheck: true, 71 SupportedSigningAlgs: []string{oidc.RS256}, 72 Now: time.Now, 73 } 74 75 verifier := provider.Verifier(config) 76 a.verifier.Store(verifier) 77 return nil 78 } 79 80 // loadVerifier returns the stored value and casts it to a verifier object 81 func (a *OIDCAuthenticator) loadVerifier() (verifier, error) { 82 vAny := a.verifier.Load() 83 if vAny == nil { 84 err := fmt.Errorf("nil verifier object") 85 a.Log.Errorf("Failed to load verifier: %v", err) 86 } 87 88 if vTyped, ok := vAny.(verifier); ok { 89 return vTyped, nil 90 } 91 92 err := fmt.Errorf("object does not implement the verifier interface") 93 a.Log.Errorf("Failed to load verifier: %v", err) 94 return nil, err 95 } 96 97 // GetImpersonationHeadersFromRequest returns the user and group fields from the bearer token to be used as 98 // impersonation headers for the API server request 99 func GetImpersonationHeadersFromRequest(req *http.Request) (ImpersonationHeaders, error) { 100 var headers ImpersonationHeaders 101 102 token, err := getTokenFromAuthHeader(req.Header.Get(authHeaderKey)) 103 if err != nil { 104 return headers, err 105 } 106 107 jwtParts := strings.SplitN(token, ".", 3) 108 if len(jwtParts) != 3 { 109 return headers, fmt.Errorf("malformed jwt token, found %d sections", len(jwtParts)) 110 } 111 112 payload, err := base64.RawURLEncoding.DecodeString(jwtParts[1]) 113 if err != nil { 114 return headers, err 115 } 116 117 err = json.Unmarshal(payload, &headers) 118 if err != nil { 119 return headers, err 120 } 121 122 return headers, nil 123 }