github.com/verrazzano/verrazzano@v1.7.1/authproxy/src/auth/login.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/rand" 9 "crypto/x509" 10 "encoding/base64" 11 "fmt" 12 "net/http" 13 14 "github.com/coreos/go-oidc/v3/oidc" 15 "github.com/verrazzano/verrazzano/authproxy/internal/httputil" 16 "github.com/verrazzano/verrazzano/pkg/certs" 17 "golang.org/x/oauth2" 18 "k8s.io/client-go/util/cert" 19 ) 20 21 // initExternalOIDCProvider initializes the external URL based OIDC Provider in the given Authenticator 22 func (a *OIDCAuthenticator) initExternalOIDCProvider() error { 23 ctx, err := a.createContextWithHTTPClient() 24 if err != nil { 25 return err 26 } 27 provider, err := oidc.NewProvider(ctx, a.oidcConfig.ExternalURL) 28 if err != nil { 29 return err 30 } 31 a.ExternalProvider = provider 32 return nil 33 } 34 35 // createContextWithHTTPClient creates a context with the correct certificates and 36 // client to redirect to the OIDC provider 37 func (a *OIDCAuthenticator) createContextWithHTTPClient() (context.Context, error) { 38 caBundleData, err := certs.GetLocalClusterCABundleData(a.Log, a.k8sClient, context.TODO()) 39 if err != nil { 40 return nil, err 41 } 42 var certPool *x509.CertPool 43 if caBundleData != nil { 44 if certPool, err = cert.NewPoolFromBytes(caBundleData); err != nil { 45 return nil, err 46 } 47 } 48 49 httpClient := httputil.GetHTTPClientWithCABundle(certPool) 50 ctx := context.Background() 51 return context.WithValue(ctx, oauth2.HTTPClient, httpClient.HTTPClient), nil 52 } 53 54 // performLoginRedirect redirects the incoming request to the OIDC provider 55 func (a *OIDCAuthenticator) performLoginRedirect(req *http.Request, rw http.ResponseWriter) error { 56 var state string 57 var nonce string 58 var err error 59 if state, err = randomBase64(32); err != nil { 60 return fmt.Errorf("could not redirect for login - failed to generate random base64: %v", err) 61 } 62 if nonce, err = randomBase64(32); err != nil { 63 return fmt.Errorf("could not redirect for login - failed to generate random base64: %v", err) 64 } 65 66 oauthConfig := oauth2.Config{ 67 ClientID: a.oidcConfig.ClientID, 68 Endpoint: a.ExternalProvider.Endpoint(), 69 RedirectURL: a.oidcConfig.CallbackURL, 70 Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, 71 } 72 http.Redirect(rw, req, oauthConfig.AuthCodeURL(state, oidc.Nonce(nonce)), http.StatusFound) 73 return nil 74 } 75 76 // randomBase64 returns a random base64-encoded string of the given size 77 func randomBase64(size int) (string, error) { 78 b := make([]byte, size) 79 if _, err := rand.Read(b); err != nil { 80 return "", err 81 } 82 return base64.RawURLEncoding.EncodeToString(b), nil 83 }