@@ -36,6 +36,7 @@ import (
3636 "github.com/kubernetes-sigs/headlamp/backend/pkg/auth"
3737 "github.com/kubernetes-sigs/headlamp/backend/pkg/cache"
3838 "github.com/kubernetes-sigs/headlamp/backend/pkg/kubeconfig"
39+ "github.com/kubernetes-sigs/headlamp/backend/pkg/telemetry"
3940 "github.com/stretchr/testify/assert"
4041 "github.com/stretchr/testify/require"
4142 "golang.org/x/oauth2"
@@ -604,6 +605,17 @@ func newOIDCProviderServer(t *testing.T, tokenHandler http.HandlerFunc) *httptes
604605 return srv
605606}
606607
608+ func findAuthCookie (resp * http.Response , cluster string ) (string , bool ) {
609+ want := fmt .Sprintf ("headlamp-auth-%s.0" , auth .SanitizeClusterName (cluster ))
610+ for _ , cookie := range resp .Cookies () {
611+ if cookie .Name == want {
612+ return cookie .Value , true
613+ }
614+ }
615+
616+ return "" , false
617+ }
618+
607619var oauthSuccessBody = map [string ]any {
608620 "access_token" : "AT" ,
609621 "token_type" : "Bearer" ,
@@ -795,6 +807,131 @@ func TestRefreshAndCacheNewToken_TokenError(t *testing.T) {
795807 assert .Len (t , fc .setWithTTLCalls , 0 )
796808}
797809
810+ func TestRefreshAndSetToken_DefaultsToIDToken (t * testing.T ) {
811+ const (
812+ oldToken = "OLD"
813+ cluster = "test"
814+ )
815+
816+ fc := & fakeCache {store : map [string ]interface {}{"oidc-token-" + oldToken : "REFRESH_OLD" }}
817+
818+ srv := newOIDCProviderServer (t , func (w http.ResponseWriter , r * http.Request ) {
819+ require .NoError (t , r .ParseForm ())
820+ require .Equal (t , "refresh_token" , r .PostForm .Get ("grant_type" ))
821+ require .Equal (t , "REFRESH_OLD" , r .PostForm .Get ("refresh_token" ))
822+
823+ w .Header ().Set ("Content-Type" , "application/json" )
824+ require .NoError (t , json .NewEncoder (w ).Encode (oauthSuccessBody ))
825+ })
826+
827+ req := httptest .NewRequest (http .MethodGet , "/clusters/" + cluster , nil )
828+ rr := httptest .NewRecorder ()
829+
830+ auth .RefreshAndSetToken (auth.RefreshAndSetTokenParams {
831+ Ctx : context .Background (),
832+ OIDCAuthConfig : & kubeconfig.OidcConfig {ClientID : "cid" , ClientSecret : "secret" , IdpIssuerURL : srv .URL },
833+ Cache : fc ,
834+ Token : oldToken ,
835+ Cluster : cluster ,
836+ Writer : rr ,
837+ Request : req ,
838+ TelemetryHandler : & telemetry.RequestHandler {},
839+ OIDCIdpIssuerURL : "" ,
840+ BaseURL : "" ,
841+ })
842+
843+ resp := rr .Result ()
844+ defer resp .Body .Close ()
845+
846+ cookieVal , ok := findAuthCookie (resp , cluster )
847+ require .True (t , ok , "expected auth cookie to be set" )
848+ assert .Equal (t , "NEW" , cookieVal )
849+ }
850+
851+ func TestRefreshAndSetToken_UsesAccessToken (t * testing.T ) {
852+ const (
853+ oldToken = "OLD"
854+ cluster = "test"
855+ )
856+
857+ fc := & fakeCache {store : map [string ]interface {}{"oidc-token-" + oldToken : "REFRESH_OLD" }}
858+
859+ tokenBody := map [string ]any {
860+ "access_token" : "ACCESS_NEW" ,
861+ "token_type" : "Bearer" ,
862+ "expires_in" : 3600 ,
863+ "refresh_token" : refreshNew ,
864+ "id_token" : "IGNORED" ,
865+ }
866+
867+ srv := newOIDCProviderServer (t , func (w http.ResponseWriter , r * http.Request ) {
868+ require .NoError (t , r .ParseForm ())
869+ require .Equal (t , "REFRESH_OLD" , r .PostForm .Get ("refresh_token" ))
870+
871+ w .Header ().Set ("Content-Type" , "application/json" )
872+ require .NoError (t , json .NewEncoder (w ).Encode (tokenBody ))
873+ })
874+
875+ req := httptest .NewRequest (http .MethodGet , "/clusters/" + cluster , nil )
876+ rr := httptest .NewRecorder ()
877+
878+ auth .RefreshAndSetToken (auth.RefreshAndSetTokenParams {
879+ Ctx : context .Background (),
880+ OIDCAuthConfig : & kubeconfig.OidcConfig {ClientID : "cid" , ClientSecret : "secret" },
881+ Cache : fc ,
882+ Token : oldToken ,
883+ Cluster : cluster ,
884+ Writer : rr ,
885+ Request : req ,
886+ TelemetryHandler : & telemetry.RequestHandler {},
887+ OIDCUseAccessToken : true ,
888+ OIDCIdpIssuerURL : srv .URL ,
889+ BaseURL : "" ,
890+ })
891+
892+ resp := rr .Result ()
893+ defer resp .Body .Close ()
894+
895+ cookieVal , ok := findAuthCookie (resp , cluster )
896+ require .True (t , ok , "expected auth cookie to be set" )
897+ assert .Equal (t , "ACCESS_NEW" , cookieVal )
898+ }
899+
900+ func TestRefreshAndSetToken_ErrorDoesNotSetCookie (t * testing.T ) {
901+ const (
902+ oldToken = "OLD"
903+ cluster = "test"
904+ )
905+
906+ fc := & fakeCache {store : map [string ]interface {}{"oidc-token-" + oldToken : "REFRESH_OLD" }}
907+
908+ srv := newOIDCProviderServer (t , func (w http.ResponseWriter , _ * http.Request ) {
909+ http .Error (w , "token refresh failed" , http .StatusInternalServerError )
910+ })
911+
912+ req := httptest .NewRequest (http .MethodGet , "/clusters/" + cluster , nil )
913+ rr := httptest .NewRecorder ()
914+
915+ auth .RefreshAndSetToken (auth.RefreshAndSetTokenParams {
916+ Ctx : context .Background (),
917+ OIDCAuthConfig : & kubeconfig.OidcConfig {ClientID : "cid" , ClientSecret : "secret" },
918+ Cache : fc ,
919+ Token : oldToken ,
920+ Cluster : cluster ,
921+ Writer : rr ,
922+ Request : req ,
923+ TelemetryHandler : & telemetry.RequestHandler {},
924+ OIDCIdpIssuerURL : srv .URL ,
925+ BaseURL : "" ,
926+ })
927+
928+ resp := rr .Result ()
929+ defer resp .Body .Close ()
930+
931+ _ , ok := findAuthCookie (resp , cluster )
932+ assert .False (t , ok , "expected no auth cookie to be set on error" )
933+ }
934+
798935// TestConfigureTLSContext_NoConfig tests when both skipTLSVerify and caCert are not set.
799936func TestConfigureTLSContext_NoConfig (t * testing.T ) {
800937 baseCtx := context .Background ()
0 commit comments