Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#if SUPPORTS_SYSTEM_TEXT_JSON
using Microsoft.Identity.Client.Platforms.net;
using JsonProperty = System.Text.Json.Serialization.JsonPropertyNameAttribute;
using JsonIgnore = System.Text.Json.Serialization.JsonIgnoreAttribute;
#else
using Microsoft.Identity.Json;
#endif
Expand All @@ -29,8 +30,22 @@ internal class ManagedIdentityResponse
/// </summary>
Copy link
Member

Choose a reason for hiding this comment

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

How will we keep this object ManagedIdentityResponse in sync with MsalTokenResponse, e.g. RefreshIn is missing?

/// <remarks>The date is represented as the number of seconds from "1970-01-01T0:0:0Z UTC"
/// (corresponds to the token's exp claim).</remarks>
[JsonIgnore]
public string ExpiresOn { get; set; } // The actual property consumers use

[JsonProperty("expires_on")]
public string ExpiresOn { get; set; }
public string ExpiresOnRaw // Proxy for "expires_on" JSON field
{
get => ExpiresOn; // When serializing, return ExpiresOn value
set => ExpiresOn = value; // When deserializing, store in ExpiresOn
}

[JsonProperty("expires_in")]
public string ExpiresInRaw // Proxy for "expires_in" JSON field
{
get => null; // Never serialize this (return null)
set => ExpiresOn = value; // When deserializing, store in ExpiresOn
}

/// <summary>
/// The resource the access token was requested for.
Expand Down
10 changes: 9 additions & 1 deletion src/client/Microsoft.Identity.Client/Utils/DateTimeHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,15 @@ public static long GetDurationFromManagedIdentityTimestamp(string dateTimeStamp)
// Example: "1697490590" (Unix timestamp representing seconds since 1970-01-01)
if (long.TryParse(dateTimeStamp, out long expiresOnUnixTimestamp))
{
return expiresOnUnixTimestamp - DateTimeHelpers.CurrDateTimeInUnixTimestamp();
var timestamp = expiresOnUnixTimestamp - DateTimeHelpers.CurrDateTimeInUnixTimestamp();

// If the timestamp is negative, return the original expiresOnUnixTimestamp. Its format is "seconds from now".
if (timestamp < 0)
{
return expiresOnUnixTimestamp;
}

return timestamp;
}

// Try parsing as ISO 8601
Expand Down
15 changes: 8 additions & 7 deletions tests/Microsoft.Identity.Test.Common/Core/Mocks/MockHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,25 +125,26 @@ public static string GetBridgedHybridSpaTokenResponse(string spaAccountId)
public static string GetMsiSuccessfulResponse(
int expiresInHours = 1,
bool useIsoFormat = false,
bool mTLSPop = false)
bool mTLSPop = false,
bool imdsV2 = false)
{
string expiresOn;

var expiresOnKey = imdsV2 ? "expires_in" : "expires_on";
string expiresOnValue;
if (useIsoFormat)
{
// Return ISO 8601 format
expiresOn = DateTime.UtcNow.AddHours(expiresInHours).ToString("o", CultureInfo.InvariantCulture);
expiresOnValue = DateTime.UtcNow.AddHours(expiresInHours).ToString("o", CultureInfo.InvariantCulture);
}
else
{
// Return Unix timestamp format
expiresOn = DateTimeHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow.AddHours(expiresInHours));
expiresOnValue = DateTimeHelpers.DateTimeToUnixTimestamp(DateTime.UtcNow.AddHours(expiresInHours));
}

var tokenType = mTLSPop ? "mtls_pop" : "Bearer";

return
"{\"access_token\":\"" + TestConstants.ATSecret + "\",\"expires_on\":\"" + expiresOn + "\",\"resource\":\"https://management.azure.com/\"," +
"{\"access_token\":\"" + TestConstants.ATSecret + "\",\"" + expiresOnKey + "\":\"" + expiresOnValue + "\",\"resource\":\"https://management.azure.com/\"," +
"\"token_type\":\"" + tokenType + "\",\"client_id\":\"client_id\"}";
}

Expand Down Expand Up @@ -730,7 +731,7 @@ public static MockHttpMessageHandler MockImdsV2EntraTokenRequestResponse(
PresentRequestHeaders = presentRequestHeaders,
ResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(GetMsiSuccessfulResponse(mTLSPop: mTLSPop)),
Content = new StringContent(GetMsiSuccessfulResponse(mTLSPop: mTLSPop, imdsV2: true)),
}
};

Expand Down