@@ -565,6 +565,104 @@ func handleOIDCCallback(
565565 processOIDCCallback (config , w , r , oauthConfig , state )
566566}
567567
568+ func writeOIDCError (w http.ResponseWriter , err error , msg string ) {
569+ if err != nil {
570+ msg = fmt .Sprintf ("%s: %v" , msg , err )
571+ }
572+
573+ http .Error (w , msg , http .StatusBadRequest )
574+ }
575+
576+ func validateState (state string ) error {
577+ if _ , err := base64 .StdEncoding .DecodeString (state ); err != nil {
578+ return fmt .Errorf ("failed to decode state: %w" , err )
579+ }
580+
581+ return nil
582+ }
583+
584+ func getOAuthConfigFromState (
585+ state string ,
586+ oauthRequestMap map [string ]* OauthConfig ,
587+ ) * OauthConfig {
588+ return oauthRequestMap [state ]
589+ }
590+
591+ func processOIDCCallback (
592+ config * HeadlampConfig ,
593+ w http.ResponseWriter ,
594+ r * http.Request ,
595+ oauthConfig * OauthConfig ,
596+ state string ,
597+ ) {
598+ token , err := exchangeCode (oauthConfig , r )
599+ if err != nil {
600+ writeOIDCError (w , err , "failed to exchange token" )
601+ return
602+ }
603+
604+ tokenType := "id_token"
605+ if config .oidcUseAccessToken {
606+ tokenType = "access_token"
607+ }
608+
609+ rawToken := getRawToken (token , tokenType )
610+ if rawToken == "" {
611+ writeOIDCError (w , nil , fmt .Sprintf ("no %s field" , tokenType ))
612+ return
613+ }
614+
615+ cacheToken (config .cache , rawToken , token .RefreshToken )
616+ verifyToken (oauthConfig , rawToken )
617+ redirectUser (config , w , r , state , rawToken )
618+ }
619+
620+ func exchangeCode (oauthConfig * OauthConfig , r * http.Request ) (* oauth2.Token , error ) {
621+ return oauthConfig .Config .Exchange (oauthConfig .Ctx , r .URL .Query ().Get ("code" ))
622+ }
623+
624+ func getRawToken (token * oauth2.Token , tokenType string ) string {
625+ rawToken , _ := token .Extra (tokenType ).(string )
626+ return rawToken
627+ }
628+
629+ func cacheToken (cache cache.Cache [interface {}], rawToken , refreshToken string ) {
630+ _ = cache .Set (context .Background (),
631+ fmt .Sprintf ("oidc-token-%s" , rawToken ),
632+ refreshToken )
633+ }
634+
635+ func verifyToken (oauthConfig * OauthConfig , rawToken string ) {
636+ _ , _ = oauthConfig .Verifier .Verify (oauthConfig .Ctx , rawToken )
637+ }
638+
639+ func redirectUser (
640+ config * HeadlampConfig ,
641+ w http.ResponseWriter ,
642+ r * http.Request ,
643+ state ,
644+ rawToken string ,
645+ ) {
646+ redirectURL := buildRedirectURL (config , state , rawToken )
647+ http .Redirect (w , r , redirectURL , http .StatusSeeOther )
648+ }
649+
650+ func buildRedirectURL (config * HeadlampConfig , state , rawToken string ) string {
651+ base := "http://localhost:3000/"
652+ if ! config .DevMode {
653+ base = "/"
654+ }
655+
656+ if trimmed := strings .Trim (config .BaseURL , "/" ); trimmed != "" {
657+ base += trimmed + "/"
658+ }
659+
660+ decodedState , _ := base64 .StdEncoding .DecodeString (state )
661+
662+ return fmt .Sprintf ("%sauth?cluster=%s&token=%s" ,
663+ base , decodedState , rawToken )
664+ }
665+
568666func handleOIDC (
569667 config * HeadlampConfig ,
570668 w http.ResponseWriter ,
0 commit comments