From bb638f51a0e3ed74b7aff8eb1515f2c73e3279b6 Mon Sep 17 00:00:00 2001 From: Charles Lowell <10964656+chlowell@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:57:10 -0700 Subject: [PATCH] Enable unmarshaling partitioned caches --- apps/internal/base/internal/storage/items.go | 12 ++-- .../storage/partitioned_storage_test.go | 34 +++++++++++ .../testdata/test_partitioned_cache.json | 61 +++++++++++++++++++ 3 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 apps/internal/base/internal/storage/testdata/test_partitioned_cache.json diff --git a/apps/internal/base/internal/storage/items.go b/apps/internal/base/internal/storage/items.go index f9be9027..71bb2fc0 100644 --- a/apps/internal/base/internal/storage/items.go +++ b/apps/internal/base/internal/storage/items.go @@ -33,11 +33,13 @@ type Contract struct { // the internal cache. This design is shared between MSAL versions in many languages. // This cannot be changed without design that includes other SDKs. type InMemoryContract struct { - AccessTokensPartition map[string]map[string]AccessToken - RefreshTokensPartition map[string]map[string]accesstokens.RefreshToken - IDTokensPartition map[string]map[string]IDToken - AccountsPartition map[string]map[string]shared.Account - AppMetaData map[string]AppMetaData + AccessTokensPartition map[string]map[string]AccessToken `json:"AccessTokensPartition,omitempty"` + RefreshTokensPartition map[string]map[string]accesstokens.RefreshToken `json:"RefreshTokensPartition,omitempty"` + IDTokensPartition map[string]map[string]IDToken `json:"IdTokensPartition,omitempty"` + AccountsPartition map[string]map[string]shared.Account `json:"AccountsPartition,omitempty"` + AppMetaData map[string]AppMetaData `json:"AppMetadata,omitempty"` + + AdditionalFields map[string]interface{} } // NewContract is the constructor for Contract. diff --git a/apps/internal/base/internal/storage/partitioned_storage_test.go b/apps/internal/base/internal/storage/partitioned_storage_test.go index 86859cf2..5dcf852f 100644 --- a/apps/internal/base/internal/storage/partitioned_storage_test.go +++ b/apps/internal/base/internal/storage/partitioned_storage_test.go @@ -6,6 +6,7 @@ package storage import ( "context" "fmt" + "os" "reflect" "testing" "time" @@ -253,6 +254,39 @@ func TestReadPartitionedAccount(t *testing.T) { } } +func TestUnmarshalPartitioned(t *testing.T) { + manager := newPartitionedManagerForTest(nil) + b, err := os.ReadFile("testdata/test_partitioned_cache.json") + if err != nil { + t.Fatal(err) + } + err = manager.Unmarshal(b) + if err != nil { + t.Fatal(err) + } + hash := "0EuY9I6Pi8wVxq5awFCAHNbc_UKPtfnmXE4W54BzQPo=" + actual := manager.contract.AccessTokensPartition[hash]["uid.utid-login.windows.net-accesstoken-my_client_id-contoso-s2 s1 s3"].Secret + if actual != accessTokenSecret { + t.Errorf("got access token %q, want %q", actual, accessTokenSecret) + } + actual = manager.contract.RefreshTokensPartition[hash]["uid.utid-login.windows.net-refreshtoken-my_client_id--s2 s1 s3"].Secret + if actual != rtSecret { + t.Errorf("got refresh token %q, want %q", actual, rtSecret) + } + actual = manager.contract.IDTokensPartition[hash]["uid.utid-login.windows.net-idtoken-my_client_id-contoso-"].Secret + if actual != idSecret { + t.Errorf("got ID token %q, want %q", actual, idSecret) + } + actual = manager.contract.AccountsPartition[hash]["uid.utid-login.windows.net-contoso"].PreferredUsername + if actual != accUser { + t.Errorf("got username %q, want %q", actual, accUser) + } + actual = manager.contract.AppMetaData["appmetadata-login.windows.net-my_client_id"].FamilyID + if actual != "1" { + t.Errorf(`got family ID %q, want "1"`, actual) + } +} + func TestWritePartitionedAccount(t *testing.T) { storageManager := newPartitionedManagerForTest(nil) testAcc := shared.NewAccount("hid", "env", "realm", "lid", accAuth, "username") diff --git a/apps/internal/base/internal/storage/testdata/test_partitioned_cache.json b/apps/internal/base/internal/storage/testdata/test_partitioned_cache.json new file mode 100644 index 00000000..d4292926 --- /dev/null +++ b/apps/internal/base/internal/storage/testdata/test_partitioned_cache.json @@ -0,0 +1,61 @@ +{ + "AccountsPartition": { + "0EuY9I6Pi8wVxq5awFCAHNbc_UKPtfnmXE4W54BzQPo=": { + "uid.utid-login.windows.net-contoso": { + "username": "John Doe", + "local_account_id": "object1234", + "realm": "contoso", + "environment": "login.windows.net", + "home_account_id": "uid.utid", + "authority_type": "MSSTS" + } + } + }, + "RefreshTokensPartition": { + "0EuY9I6Pi8wVxq5awFCAHNbc_UKPtfnmXE4W54BzQPo=": { + "uid.utid-login.windows.net-refreshtoken-my_client_id--s2 s1 s3": { + "target": "s2 s1 s3", + "environment": "login.windows.net", + "credential_type": "RefreshToken", + "secret": "a refresh token", + "client_id": "my_client_id", + "home_account_id": "uid.utid" + } + } + }, + "AccessTokensPartition": { + "0EuY9I6Pi8wVxq5awFCAHNbc_UKPtfnmXE4W54BzQPo=": { + "uid.utid-login.windows.net-accesstoken-my_client_id-contoso-s2 s1 s3": { + "environment": "login.windows.net", + "credential_type": "AccessToken", + "secret": "an access token", + "realm": "contoso", + "target": "s2 s1 s3", + "client_id": "my_client_id", + "cached_at": "1000", + "home_account_id": "uid.utid", + "extended_expires_on": "4600", + "expires_on": "4600" + } + } + }, + "IDTokensPartition": { + "0EuY9I6Pi8wVxq5awFCAHNbc_UKPtfnmXE4W54BzQPo=": { + "uid.utid-login.windows.net-idtoken-my_client_id-contoso-": { + "realm": "contoso", + "environment": "login.windows.net", + "credential_type": "IdToken", + "secret": "header.eyJvaWQiOiAib2JqZWN0MTIzNCIsICJwcmVmZXJyZWRfdXNlcm5hbWUiOiAiSm9obiBEb2UiLCAic3ViIjogInN1YiJ9.signature", + "client_id": "my_client_id", + "home_account_id": "uid.utid" + } + } + }, + "AppMetadata": { + "appmetadata-login.windows.net-my_client_id": { + "environment": "login.windows.net", + "client_id": "my_client_id", + "family_id": "1" + } + } +} \ No newline at end of file