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  }