Skip to content
This repository has been archived by the owner on Jun 30, 2023. It is now read-only.

cache format tests + format changes #1350

Merged
merged 11 commits into from
Oct 26, 2018
Merged

cache format tests + format changes #1350

merged 11 commits into from
Oct 26, 2018

Conversation

SomkaPe
Copy link
Contributor

@SomkaPe SomkaPe commented Oct 24, 2018

Cache format tests

While writing cache format test some cache format inconsistencies with current version of unified schema were found:

  1. Timestamps should be stored as strings in Json
  2. It was decided to not store client_info(which is optional field) in all cache entities - just in account
  3. Credential Type field should be Case sensitive
  4. Keys of cache entities should be in lower case (including iOS key chain key)
  5. Scopes should not be stored in sorted form, instead should be stored as is (as returned from STS)
  6. Change "preferred_username not in id_token" to "Missing from the token response"
  7. Changing iOS key component "Generic" for account cache entity - store "username" instead of "local_account_id" (requested by Olga)

Others:

  1. Persisting given_name and family_name optional claims in account cache entity
  2. Fixing issue of client_info misuse:
    2.1. AccounId is derived from ClientInfo (Not opposite way - ClientInfo can not be recreated from accountId, it can contains more fields )
    2.2. Some code was written based on assumption that client info is always persisted with cache entities, which is wrong because it is optional field, so some library can not persist it.

public const string RefreshToken = "refreshtoken";
public const string IdToken = "IdToken";
public const string AccessToken = "AccessToken";
public const string RefreshToken = "RefreshToken";
Copy link
Contributor

@henrik-me henrik-me Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I understand why you are CamelCasing these. Though I see that the methods lowercases everything. #Pending

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok... not sure though why the values here are CamelCased (if it's being lower cased later anyway).


In reply to: 227980008 [](ancestors = 227980008)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same values stored in cache entity in Camel Case but in corresponding key in lower case (it was agreed to have lower cased keys for all cache entities)

@@ -60,8 +60,8 @@ internal MsalAccessTokenCacheItem
NormalizedScopes = scopes;
TenantId = tenantId;
Secret = secret;
ExpiresOnUnixTimestamp = CoreHelpers.DateTimeToUnixTimestamp(accessTokenExpiresOn);
CachedAt = CoreHelpers.CurrDateTimeInUnixTimestamp();
ExpiresOnUnixTimestamp = CoreHelpers.DateTimeToUnixTimestamp(accessTokenExpiresOn).ToString();
Copy link
Contributor

@henrik-me henrik-me Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to make the DateTimeToUnixTimestamp return as string or perhaps to add another helper e.g. DateTimeToUnixTimestampAsString ensuring people do not have to rememeber to add .ToString() ? #Closed

Copy link
Contributor Author

@SomkaPe SomkaPe Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will change #Closed

@@ -45,7 +45,7 @@ internal MsalAccessTokenCacheItem()
internal MsalAccessTokenCacheItem
(string environment, string clientId, MsalTokenResponse response, string tenantId) :

this(environment, clientId, response.TokenType, ScopeHelper.ConvertStringToLowercaseSortedSet(response.Scope).AsSingleString(),
this(environment, clientId, response.TokenType, response.Scope,
Copy link
Contributor

@henrik-me henrik-me Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response.Scope [](start = 60, length = 14)

Does this handle sorting and normalizing? I believe that is a requirement we wanted to ensure happened for the cache? #Pending

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to schema scopes should be stored as returned from sts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great, that was not how I understood it. Are we sure the server is sorting etc.?


In reply to: 227981415 [](ancestors = 227981415)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, it does not , we should do it during cache lookup logic

@@ -35,7 +35,7 @@ public MsalUserAccessTokenControl()
private void expireAccessTokenButton_Click(object sender, System.EventArgs e)
{
expiresOnLabel.Text = DateTimeOffset.UtcNow.ToString();
_item.ExpiresOnUnixTimestamp = CoreHelpers.DateTimeToUnixTimestamp(DateTimeOffset.UtcNow);
_item.ExpiresOnUnixTimestamp = CoreHelpers.DateTimeToUnixTimestamp(DateTimeOffset.UtcNow).ToString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.ToString(); [](start = 101, length = 12)

made a comment elsewhere on this

@@ -52,7 +53,7 @@ public partial class AccessTokenCacheItemDetails : ContentPage
expiresOnLabel.Text = msalAccessTokenCacheItem.ExpiresOn.ToString();
scopesLabel.Text = msalAccessTokenCacheItem.NormalizedScopes;

cachedAtLabel.Text = CoreHelpers.UnixTimestampToDateTime(msalAccessTokenCacheItem.CachedAt).ToString();
cachedAtLabel.Text = CoreHelpers.UnixTimestampToDateTime(Convert.ToInt64(msalAccessTokenCacheItem.CachedAt)).ToString();
Copy link
Contributor

@henrik-me henrik-me Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convert.ToInt64( [](start = 69, length = 16)

can this be moved to the MsalAccessTokenCacheItem class? #Closed

Copy link
Contributor Author

@SomkaPe SomkaPe Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, will change #Closed

@henrik-me
Copy link
Contributor

henrik-me commented Oct 24, 2018

Thanks a lot for looking into this Petro! #Closed

@henrik-me
Copy link
Contributor

{

for my education, are these test data the same across all libraries?


Refers to: msal/tests/Test.MSAL.NET.Unit/Resources/AADTestData.txt:1 in cc222be. [](commit_id = cc222be, deletion_comment = False)

Copy link
Contributor

@henrik-me henrik-me left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

@@ -72,6 +74,12 @@ internal class IdToken
[DataMember(Name = IdTokenClaim.HomeObjectId, IsRequired = false)]
public string HomeObjectId { get; set; }

[DataMember(Name = IdTokenClaim.GivenName)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one doesn't need IsRequired = false?

Copy link
Contributor Author

@SomkaPe SomkaPe Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is optional, which means that other sdk might not persist it #ByDesign

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. thanks.


In reply to: 227982217 [](ancestors = 227982217)

@@ -56,7 +56,7 @@ namespace Microsoft.Identity.Client
public sealed class TokenCache
#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
{
internal const string NullPreferredUsernameDisplayLabel = "preferred_username not in id_token";
internal const string NullPreferredUsernameDisplayLabel = "Missing from the token response";
Copy link
Contributor

@jennyf19 jennyf19 Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing from the token response [](start = 67, length = 31)

much better wording #Closed

Copy link
Contributor Author

@SomkaPe SomkaPe Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

) #Closed

@SomkaPe
Copy link
Contributor Author

SomkaPe commented Oct 24, 2018

{

for my education, are these test data the same across all libraries?

Refers to: msal/tests/Test.MSAL.NET.Unit/Resources/AADTestData.txt:1 in cc222be. [](commit_id = cc222be, deletion_comment = False)

Yes Test cases can be found at VSTS at AuthLibrariesApiReview /UnifiedSchema/testcases #Closed

}

public string GetiOSServiceKey()
{
return _tenantId ?? "";
return (_tenantId ?? "").ToLower();
Copy link
Contributor

@henrik-me henrik-me Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return (_tenantId ?? "").ToLower(); [](start = 7, length = 40)

I'm speculating, however wouldn't this righ backwards compatibility? #Closed

Copy link
Contributor Author

@SomkaPe SomkaPe Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do not access cache by individual key , we do it by cache entity type - like read all access tokens,
so this is not a problem #Closed

@@ -0,0 +1,308 @@
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Internal;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing the header info

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will add


[DataMember(Name = "user_assertion_hash")]
[DataMember(Name = "user_assertion_hash", EmitDefaultValue = false)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EmitDefaultValue = false [](start = 50, length = 24)

what's this for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is used to determine whether to serialize the default value for a field or property being serialized

@@ -41,7 +41,6 @@ internal abstract class MsalCacheItemBase
[DataMember(Name = "environment", IsRequired = true)]
internal string Environment { get; set; }

[DataMember(Name = "client_info")]
Copy link
Contributor

@jennyf19 jennyf19 Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this as a datamember because it's not required...correct? #Closed

Copy link
Contributor Author

@SomkaPe SomkaPe Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was decided to persist it only with account object #Closed

}
}
}
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is pretty cool. What about ADFS scenarios?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be also included quite easily, main challenge is to create test data for adfs -> sts response and expectations , it probably should be done in separate PR related to enabling ADFS in msal

internal MsalAccountCacheKey GetKey()
{
return new MsalAccountCacheKey(Environment, TenantId, HomeAccountId, LocalAccountId);
return new MsalAccountCacheKey(Environment, TenantId, HomeAccountId, PreferredUsername);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PreferredUsername [](start = 81, length = 17)

Why is this changing to PreferredUsername? Will that impact existing cache (pre-next release)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change was requested by iOS team, purpose is to optimize cache lookups,
it will not affect .NET Msal lookup because it does not perform lookup on individual keys

@@ -39,9 +39,9 @@ internal class MsalAccountCacheKey
private readonly string _environment;
private readonly string _homeAccountId;
private readonly string _tenantId;
private readonly string _localAccountId;
private readonly string _username;
Copy link
Contributor

@jennyf19 jennyf19 Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_username [](start = 32, length = 9)

why the switch to _username? #Closed

Copy link
Contributor Author

@SomkaPe SomkaPe Oct 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this field is used only for persistence on iOS - as value for "Generic", iOS team requested this change
to optimize cache lookup, from .Net side we need to change it to be compatible with iOS Msal #Closed

@@ -111,7 +111,7 @@ public void OnExpire(object sender, EventArgs e)
var tokenCache = App.MsalPublicClient.UserTokenCache;

// set access token as expired
accessTokenCacheItem.ExpiresOnUnixTimestamp = GetCurrentTimestamp();
accessTokenCacheItem.ExpiresOnUnixTimestamp = GetCurrentTimestamp().ToString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetCurrentTimestamp [](start = 58, length = 19)

nit: consider making the method return a string

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

@@ -61,7 +61,7 @@ internal MsalAccessTokenCacheItem
TenantId = tenantId;
Secret = secret;
ExpiresOnUnixTimestamp = CoreHelpers.DateTimeToUnixTimestamp(accessTokenExpiresOn);
CachedAt = CoreHelpers.CurrDateTimeInUnixTimestamp();
CachedAt = CoreHelpers.CurrDateTimeInUnixTimestamp().ToString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CurrDateTimeInUnixTimestamp(). [](start = 35, length = 30)

is this used anywhere else where it's supposed to return a long or can the method be updated to return a string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Copy link
Contributor

@henrik-me henrik-me left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@SomkaPe SomkaPe merged commit 37b0eb5 into dev Oct 26, 2018
@SomkaPe SomkaPe deleted the somkape/cacheFormatTest branch December 13, 2018 18:26
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants