github.com/verrazzano/verrazzano@v1.7.0/authproxy/src/auth/auth.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 "crypto/x509" 9 "fmt" 10 "net/http" 11 12 "github.com/coreos/go-oidc/v3/oidc" 13 "github.com/verrazzano/verrazzano/authproxy/internal/httputil" 14 "go.uber.org/zap" 15 k8sclient "sigs.k8s.io/controller-runtime/pkg/client" 16 ) 17 18 const ( 19 authHeaderKey = "Authorization" 20 21 authTypeBearer string = "Bearer" 22 ) 23 24 // verifier interface is implemented by the OIDC token verifier 25 type verifier interface { 26 Verify(ctx context.Context, rawIDToken string) (*oidc.IDToken, error) 27 } 28 29 // NewAuthenticator returns a new OIDC authenticator with an initialized verifier 30 func NewAuthenticator(oidcConfig *OIDCConfiguration, log *zap.SugaredLogger, client k8sclient.Client) (*OIDCAuthenticator, error) { 31 authenticator := &OIDCAuthenticator{ 32 Log: log, 33 client: httputil.GetHTTPClientWithCABundle(&x509.CertPool{}), 34 oidcConfig: oidcConfig, 35 k8sClient: client, 36 } 37 38 if err := authenticator.initExternalOIDCProvider(); err != nil { 39 log.Errorf("Failed to initialize OIDC provider for the authenticator: %v", err) 40 return nil, err 41 } 42 43 if err := authenticator.initServiceOIDCVerifier(); err != nil { 44 log.Errorf("Failed to store verifier for the authenticator: %v", err) 45 return nil, err 46 } 47 48 return authenticator, nil 49 } 50 51 // AuthenticateRequest performs login redirect if the authorization header is not provided. 52 // If the header is provided, the bearer token is validated against the OIDC key 53 func (a *OIDCAuthenticator) AuthenticateRequest(req *http.Request, rw http.ResponseWriter) (bool, error) { 54 authHeader := req.Header.Get(authHeaderKey) 55 56 if a.ExternalProvider == nil { 57 return false, fmt.Errorf("the OIDC provider for authentication is not initialized") 58 } 59 if authHeader == "" { 60 err := a.performLoginRedirect(req, rw) 61 if err != nil { 62 return false, fmt.Errorf("could not redirect for login: %v", err) 63 } 64 // we performed a redirect, so request processing is done and 65 // no further processing is needed 66 return false, nil 67 } 68 69 token, err := getTokenFromAuthHeader(authHeader) 70 if err != nil { 71 return false, fmt.Errorf("failed to get token from authorization header: %v", err) 72 } 73 74 return a.AuthenticateToken(req.Context(), token) 75 } 76 77 // SetCallbackURL sets the OIDC Callback URL for redirects 78 func (a *OIDCAuthenticator) SetCallbackURL(url string) { 79 a.oidcConfig.CallbackURL = url 80 }