Skip to content

Commit 7c7626e

Browse files
Add more tests for TokenAcquisitionMetadata.ExpiresOn from AuthenticationResult (#3904)
* Populate TokenAcquisitionMetadata.ExpiresOn from AuthenticationResult Maps AuthenticationResult.ExpiresOn into the token-acquisition metadata surface so callers get the access token's absolute expiry on success. Adds unit coverage (present/absent metadata) and an end-to-end assertion on the DefaultAuthorizationHeaderProvider metadata flow. Requires Microsoft.Identity.Abstractions 12.4.0 (adds ExpiresOn). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add FromMsal test asserting ExpiresOn on top-level result and metadata Covers the top-level AcquireTokenResult.ExpiresOn mapping, complementing the existing GetMetadata (metadata surface) and provider e2e coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove duplicate ExpiresOn mapping (master already has it) master gained the ExpiresOn mapping independently; the merge left two identical assignments in MapMetadata, causing CS1912. Drop the duplicate so the factory matches master and this PR carries just the tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d963e30 commit 7c7626e

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

tests/Microsoft.Identity.Web.Test/AcquireTokenResultFactoryEnumRoundTripTests.cs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using System;
45
using Microsoft.Identity.Client;
56
using Microsoft.Identity.Client.Cache;
67
using Microsoft.Identity.Client.Region;
@@ -90,5 +91,93 @@ public void EnumMemberCounts_MatchAbstractions()
9091
System.Enum.GetValues(typeof(RegionOutcome)).Length,
9192
System.Enum.GetValues(typeof(Abstractions.AcquiredTokenRegionOutcome)).Length);
9293
}
94+
95+
[Fact]
96+
public void GetMetadata_SetsExpiresOn_FromResult_WhenMetadataAvailable()
97+
{
98+
// Arrange
99+
DateTimeOffset expiresOn = DateTimeOffset.UtcNow.AddHours(1);
100+
DateTimeOffset extendedExpiresOn = DateTimeOffset.UtcNow.AddHours(2);
101+
DateTimeOffset refreshOn = DateTimeOffset.UtcNow.AddMinutes(30);
102+
var source = new AuthenticationResultMetadata(TokenSource.IdentityProvider)
103+
{
104+
RefreshOn = refreshOn,
105+
};
106+
var result = new AuthenticationResult(
107+
"access-token",
108+
false,
109+
null,
110+
expiresOn,
111+
extendedExpiresOn,
112+
"tenant",
113+
null,
114+
null,
115+
new[] { "scope" },
116+
Guid.NewGuid(),
117+
source);
118+
119+
// Act
120+
Abstractions.TokenAcquisitionMetadata? metadata = AcquireTokenResultFactory.GetMetadata(result);
121+
122+
// Assert
123+
Assert.NotNull(metadata);
124+
Assert.Equal(expiresOn, metadata!.ExpiresOn);
125+
// ExpiresOn flows from result.ExpiresOn, distinct from the metadata's RefreshOn hint.
126+
Assert.Equal(refreshOn, metadata.RefreshOn);
127+
}
128+
129+
[Fact]
130+
public void GetMetadata_ReturnsNull_WhenMetadataAbsent()
131+
{
132+
// Arrange
133+
DateTimeOffset expiresOn = DateTimeOffset.UtcNow.AddHours(1);
134+
DateTimeOffset extendedExpiresOn = DateTimeOffset.UtcNow.AddHours(2);
135+
var result = new AuthenticationResult(
136+
"access-token",
137+
false,
138+
null,
139+
expiresOn,
140+
extendedExpiresOn,
141+
"tenant",
142+
null,
143+
null,
144+
new[] { "scope" },
145+
Guid.NewGuid());
146+
147+
// Act
148+
Abstractions.TokenAcquisitionMetadata? metadata = AcquireTokenResultFactory.GetMetadata(result);
149+
150+
// Assert
151+
Assert.Null(metadata);
152+
}
153+
154+
[Fact]
155+
public void FromMsal_MapsExpiresOn_ToTopLevelAndMetadata()
156+
{
157+
// Arrange
158+
DateTimeOffset expiresOn = DateTimeOffset.UtcNow.AddHours(1);
159+
DateTimeOffset extendedExpiresOn = DateTimeOffset.UtcNow.AddHours(2);
160+
var source = new AuthenticationResultMetadata(TokenSource.IdentityProvider);
161+
var result = new AuthenticationResult(
162+
"access-token",
163+
false,
164+
null,
165+
expiresOn,
166+
extendedExpiresOn,
167+
"tenant",
168+
null,
169+
null,
170+
new[] { "scope" },
171+
Guid.NewGuid(),
172+
source);
173+
174+
// Act
175+
Abstractions.AcquireTokenResult acquired = AcquireTokenResultFactory.FromMsal(result);
176+
177+
// Assert — ExpiresOn is surfaced both at the top level and on the metadata surface.
178+
Assert.Equal(expiresOn, acquired.ExpiresOn);
179+
Assert.NotNull(acquired.Metadata);
180+
Assert.Equal(expiresOn, acquired.Metadata!.ExpiresOn);
181+
}
93182
}
94183
}

tests/Microsoft.Identity.Web.Test/DefaultAuthorizationHeaderProviderV2Tests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ public async Task CreateAuthorizationHeaderInformationForUserAsync_PropagatesMet
154154
Assert.Equal(AcquiredTokenSource.Cache, result.Result.Metadata!.TokenSource);
155155
Assert.Equal(AcquiredTokenCacheLevel.L1Cache, result.Result.Metadata.CacheLevel);
156156
Assert.Equal(42, result.Result.Metadata.DurationTotalInMs);
157+
Assert.Equal(auth.ExpiresOn, result.Result.Metadata.ExpiresOn);
157158
Assert.NotNull(result.Result.AdditionalResponseParameters);
158159
Assert.Equal("value", result.Result.AdditionalResponseParameters!["extra"]);
159160
}

0 commit comments

Comments
 (0)