From 9cb11be54455e580917e4bf60c5c41be7a07d9c1 Mon Sep 17 00:00:00 2001 From: Andrew Martinez Date: Tue, 11 Jun 2024 14:06:06 -0400 Subject: [PATCH] fixes standalone OIDC where the server JWT signer token was not added --- controller/sync_strats/sync_instant.go | 9 ++ tests/auth_oidc_refresh_test.go | 170 ++++++++----------------- 2 files changed, 65 insertions(+), 114 deletions(-) diff --git a/controller/sync_strats/sync_instant.go b/controller/sync_strats/sync_instant.go index 6432c55e5..9b06503be 100644 --- a/controller/sync_strats/sync_instant.go +++ b/controller/sync_strats/sync_instant.go @@ -878,6 +878,15 @@ func (strategy *InstantStrategy) BuildServicePolicies(tx *bbolt.Tx) error { } func (strategy *InstantStrategy) BuildPublicKeys(tx *bbolt.Tx) error { + serverTls := strategy.ae.HostController.Identity().ServerCert() + + newModel := &edge_ctrl_pb.DataState_Event_PublicKey{PublicKey: newPublicKey(serverTls[0].Certificate[0], edge_ctrl_pb.DataState_PublicKey_X509CertDer, []edge_ctrl_pb.DataState_PublicKey_Usage{edge_ctrl_pb.DataState_PublicKey_JWTValidation, edge_ctrl_pb.DataState_PublicKey_ClientX509CertValidation})} + newEvent := &edge_ctrl_pb.DataState_Event{ + Action: edge_ctrl_pb.DataState_Create, + Model: newModel, + } + strategy.HandlePublicKeyEvent(newEvent, newModel) + for cursor := strategy.ae.GetStores().Controller.IterateIds(tx, ast.BoolNodeTrue); cursor.IsValid(); cursor.Next() { currentBytes := cursor.Current() currentId := string(currentBytes) diff --git a/tests/auth_oidc_refresh_test.go b/tests/auth_oidc_refresh_test.go index 0e42e3718..083ec16b6 100644 --- a/tests/auth_oidc_refresh_test.go +++ b/tests/auth_oidc_refresh_test.go @@ -1,116 +1,58 @@ package tests -// -//import ( -// "bytes" -// "encoding/json" -// "github.com/go-resty/resty/v2" -// "github.com/openziti/ziti/common" -// "github.com/openziti/ziti/controller/oidc_auth" -// "github.com/zitadel/oidc/v2/pkg/oidc" -// "io" -// "net/http" -// "testing" -// "time" -//) -// -//func Test_Authenticate_OIDC_Refresh(t *testing.T) { -// ctx := NewTestContext(t) -// defer ctx.Teardown() -// ctx.StartServer() -// -// rpServer, err := newOidcTestRp(ctx.ApiHost) -// ctx.Req.NoError(err) -// -// rpServer.Start() -// defer rpServer.Stop() -// -// //clientApiUrl, err := url.Parse("https://" + ctx.ApiHost + EdgeClientApiPath) -// //ctx.Req.NoError(err) -// // -// //managementApiUrl, err := url.Parse("https://" + ctx.ApiHost + EdgeManagementApiPath) -// //ctx.Req.NoError(err) -// -// t.Run("authenticate", func(t *testing.T) { -// ctx.testContextChanged(t) -// -// client := resty.NewWithClient(ctx.NewHttpClient(ctx.NewTransport())) -// client.SetRedirectPolicy(resty.DomainCheckRedirectPolicy("127.0.0.1", "localhost")) -// resp, err := client.R().Get(rpServer.LoginUri) -// -// ctx.Req.NoError(err) -// ctx.Req.Equal(http.StatusOK, resp.StatusCode()) -// -// authRequestId := resp.Header().Get(oidc_auth.AuthRequestIdHeader) -// ctx.Req.NotEmpty(authRequestId) -// -// opLoginUri := "https://" + resp.RawResponse.Request.URL.Host + "/oidc/login/username" -// -// resp, err = client.R().SetFormData(map[string]string{"id": authRequestId, "username": ctx.AdminAuthenticator.Username, "password": ctx.AdminAuthenticator.Password}).Post(opLoginUri) -// -// ctx.Req.NoError(err) -// ctx.Req.Equal(http.StatusOK, resp.StatusCode()) -// -// var outTokens *oidc.Tokens[*common.IdTokenClaims] -// -// select { -// case tokens := <-rpServer.TokenChan: -// outTokens = tokens -// case <-time.After(5 * time.Second): -// ctx.Fail("no tokens received, hit timeout") -// } -// -// ctx.Req.NotNil(outTokens) -// ctx.Req.NotEmpty(outTokens.IDToken) -// ctx.Req.NotEmpty(outTokens.IDTokenClaims) -// ctx.Req.NotEmpty(outTokens.AccessToken) -// ctx.Req.NotEmpty(outTokens.RefreshToken) -// -// t.Run("attempt to exchange tokens", func(t *testing.T) { -// refreshToken := outTokens.RefreshToken -// clientID := "native" -// -// // OIDC token endpoint for your provider -// tokenEndpoint := "https://" + resp.RawResponse.Request.URL.Host + "/oidc/token" -// -// // Prepare the request body -// requestBody, _ := json.Marshal(map[string]string{ -// "grant_type": "refresh_token", -// "refresh_token": refreshToken, -// "client_id": clientID, -// }) -// -// // Create a new HTTP request -// req, err := http.NewRequest("POST", tokenEndpoint, bytes.NewBuffer(requestBody)) -// if err != nil { -// panic(err) -// } -// -// // Set appropriate headers -// req.Header.Set("Content-Type", "application/json") -// -// // Make the HTTP request -// client := &http.Client{} -// resp, err := client.Do(req) -// if err != nil { -// panic(err) -// } -// defer resp.Body.Close() -// -// // Read and unmarshal the response body -// body, err := io.ReadAll(resp.Body) -// if err != nil { -// panic(err) -// } -// -// var tokenResponse oidc.TokenExchangeResponse -// err = json.Unmarshal(body, &tokenResponse) -// if err != nil { -// panic(err) -// } -// -// println(tokenResponse) -// -// }) -// }) -//} +import ( + service2 "github.com/openziti/edge-api/rest_client_api_client/service" + edge_apis "github.com/openziti/sdk-golang/edge-apis" + "net/url" + "testing" +) + +func Test_Authenticate_OIDC_Refresh(t *testing.T) { + ctx := NewTestContext(t) + defer ctx.Teardown() + ctx.StartServer() + + rpServer, err := newOidcTestRp(ctx.ApiHost) + ctx.Req.NoError(err) + + rpServer.Start() + defer rpServer.Stop() + + clientApiUrl, err := url.Parse("https://" + ctx.ApiHost + EdgeClientApiPath) + ctx.Req.NoError(err) + + client := edge_apis.NewClientApiClient([]*url.URL{clientApiUrl}, ctx.ControllerConfig.Id.CA(), nil) + + client.Credentials = edge_apis.NewUpdbCredentials(ctx.AdminAuthenticator.Username, ctx.AdminAuthenticator.Password) + client.SetUseOidc(true) + + t.Run("can authenticate to obtain a new token backed API Session", func(t *testing.T) { + ctx.testContextChanged(t) + + apiSession, err := client.Authenticate(client.Credentials, nil) + ctx.Req.NoError(err) + ctx.Req.IsType(&edge_apis.ApiSessionOidc{}, apiSession) + + t.Run("can refresh the token backed API Session", func(t *testing.T) { + ctx.testContextChanged(t) + + newSession, err := client.API.RefreshApiSession(apiSession, client.HttpClient) + + ctx.Req.NoError(err) + ctx.NotNil(newSession) + ctx.NotNil(newSession.GetToken()) + ctx.NotEqual(newSession.GetToken(), apiSession.GetToken()) + + t.Run("can use the new token backed API Session", func(t *testing.T) { + ctx.testContextChanged(t) + client.ApiSession.Store(&newSession) + + params := service2.NewListServicesParams() + result, err := client.API.Service.ListServices(params, nil) + ctx.Req.NoError(err) + ctx.NotNil(result) + }) + }) + }) + +}