Skip to content

Commit 335edd7

Browse files
authored
Merge branch 'main' into akaliugonna/winui3sampleapp
2 parents 60c4b90 + 522d9ce commit 335edd7

File tree

52 files changed

+2521
-1277
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2521
-1277
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
4.79.2
2+
======
3+
4+
### Bug fixes
5+
* Bump winsdk dependency [#5575](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5575)
6+
* ImdsV2 probe does not fire when .WithMtlsProofOfPossesstion is not used [#5579](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5579)
7+
* Downgrade System.Formats.Asn1 to match ID web [#5583](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5583)
8+
19
4.79.0
210
======
311

@@ -6,13 +14,15 @@
614
* Bearer Requests should Fallback to IMDS in Preview in https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5562
715
* Updating MSAL to send client info = 2 on client credential flow in https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5529
816
* Make `IMsalMtlsHttpClientFactory` interface public in https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5559* Adjust WithExtraQueryParameters APIs and cache key behavior https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5536
17+
* Adjust WithExtraQueryParameters APIs and cache key behavior [#5536](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5536)
918

1019
### Bug fixes
1120
* Fix instance discovery bug in Fr cloud [#5549](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5549)
1221
* Mark WithClientAssertion API as experimental [#5551](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/5551)
1322

1423

1524

25+
1626
4.78.0
1727
======
1828
### Changes

LibsAndSamples.sln

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 17
4-
VisualStudioVersion = 17.3.32708.82
3+
# Visual Studio Version 18
4+
VisualStudioVersion = 18.0.11217.181 d18.0
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9B0B5396-4D95-4C15-82ED-DC22B5A3123F}"
77
ProjectSection(SolutionItems) = preProject
@@ -117,8 +117,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Client.D
117117
EndProject
118118
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsTestApp", "tests\devapps\WinFormsTestApp\WinFormsTestApp.csproj", "{F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D}"
119119
EndProject
120-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KerberosConsole", "tests\devapps\KerberosConsole\KerberosConsole.csproj", "{94F35780-220A-4C08-83B9-41168F7017CD}"
121-
EndProject
122120
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net5TestApp", "tests\devapps\Net5TestApp\Net5TestApp.csproj", "{998D38B3-344C-4F19-833E-6181B0834AF6}"
123121
EndProject
124122
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebApi", "WebApi", "{CC07F293-91B9-45A3-AA3A-77885BBCB624}"
@@ -1052,47 +1050,6 @@ Global
10521050
{F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D}.Release|x64.Build.0 = Release|x64
10531051
{F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D}.Release|x86.ActiveCfg = Release|x86
10541052
{F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D}.Release|x86.Build.0 = Release|x86
1055-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|Any CPU.ActiveCfg = Debug + MobileApps|Any CPU
1056-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|Any CPU.Build.0 = Debug + MobileApps|Any CPU
1057-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|ARM.ActiveCfg = Debug + MobileApps|Any CPU
1058-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|ARM.Build.0 = Debug + MobileApps|Any CPU
1059-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|ARM64.ActiveCfg = Debug + MobileApps|Any CPU
1060-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|ARM64.Build.0 = Debug + MobileApps|Any CPU
1061-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|iPhone.ActiveCfg = Debug + MobileApps|Any CPU
1062-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|iPhone.Build.0 = Debug + MobileApps|Any CPU
1063-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|iPhoneSimulator.ActiveCfg = Debug + MobileApps|Any CPU
1064-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|iPhoneSimulator.Build.0 = Debug + MobileApps|Any CPU
1065-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|x64.ActiveCfg = Debug + MobileApps|Any CPU
1066-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|x64.Build.0 = Debug + MobileApps|Any CPU
1067-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|x86.ActiveCfg = Debug + MobileApps|Any CPU
1068-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug + MobileApps|x86.Build.0 = Debug + MobileApps|Any CPU
1069-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1070-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
1071-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|ARM.ActiveCfg = Debug|Any CPU
1072-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|ARM.Build.0 = Debug|Any CPU
1073-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|ARM64.ActiveCfg = Debug|Any CPU
1074-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|ARM64.Build.0 = Debug|Any CPU
1075-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|iPhone.ActiveCfg = Debug|Any CPU
1076-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|iPhone.Build.0 = Debug|Any CPU
1077-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
1078-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
1079-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|x64.ActiveCfg = Debug|Any CPU
1080-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|x64.Build.0 = Debug|Any CPU
1081-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|x86.ActiveCfg = Debug|Any CPU
1082-
{94F35780-220A-4C08-83B9-41168F7017CD}.Debug|x86.Build.0 = Debug|Any CPU
1083-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
1084-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|ARM.ActiveCfg = Release|Any CPU
1085-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|ARM.Build.0 = Release|Any CPU
1086-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|ARM64.ActiveCfg = Release|Any CPU
1087-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|ARM64.Build.0 = Release|Any CPU
1088-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|iPhone.ActiveCfg = Release|Any CPU
1089-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|iPhone.Build.0 = Release|Any CPU
1090-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
1091-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
1092-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|x64.ActiveCfg = Release|Any CPU
1093-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|x64.Build.0 = Release|Any CPU
1094-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|x86.ActiveCfg = Release|Any CPU
1095-
{94F35780-220A-4C08-83B9-41168F7017CD}.Release|x86.Build.0 = Release|Any CPU
10961053
{998D38B3-344C-4F19-833E-6181B0834AF6}.Debug + MobileApps|Any CPU.ActiveCfg = Debug + MobileApps|Any CPU
10971054
{998D38B3-344C-4F19-833E-6181B0834AF6}.Debug + MobileApps|Any CPU.Build.0 = Debug + MobileApps|Any CPU
10981055
{998D38B3-344C-4F19-833E-6181B0834AF6}.Debug + MobileApps|ARM.ActiveCfg = Debug + MobileApps|Any CPU
@@ -2106,7 +2063,6 @@ Global
21062063
{A7679FF0-19E8-41E3-9F7C-F54235124CC4} = {1A37FD75-94E9-4D6F-953A-0DABBD7B49E9}
21072064
{B8689FF1-20F9-4669-CF55-9B2E8B5F8DD5} = {1A37FD75-94E9-4D6F-953A-0DABBD7B49E9}
21082065
{F8C7D894-8B2F-4A1E-9D3C-5E4F7B8A9C6D} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB}
2109-
{94F35780-220A-4C08-83B9-41168F7017CD} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB}
21102066
{998D38B3-344C-4F19-833E-6181B0834AF6} = {384BA371-F17F-4A70-9423-D54F71BB3FCB}
21112067
{CC07F293-91B9-45A3-AA3A-77885BBCB624} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB}
21122068
{DD23D8FF-86BA-4E9F-8AF1-0EBE0D86986A} = {CC07F293-91B9-45A3-AA3A-77885BBCB624}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ This library controls how users sign-in and access services. We recommend you al
6565

6666
## Security reporting
6767

68-
If you find a security issue with our libraries or services please report it to [[email protected]](mailto:secure@microsoft.com) in as much detail as possible. Your submission may be eligible for a bounty through the [Microsoft Bug Bounty](https://aka.ms/bugbounty) program. Please do not post security issues to GitHub Issues or any other public site. We will contact you shortly after receiving the information. We encourage you to get notifications of when security incidents occur by visiting the [Microsoft Technical Security Notifications page](https://www.microsoft.com/msrc/technical-security-notifications?rtc=1) and subscribing to Security Advisory Alerts.
68+
If you find a security issue with our libraries or services please report it to https://msrc.microsoft.com/report/vulnerability in as much detail as possible. Your submission may be eligible for a bounty through the [Microsoft Bug Bounty](https://aka.ms/bugbounty) program. Please do not post security issues to GitHub Issues or any other public site. We will contact you shortly after receiving the information. We encourage you to get notifications of when security incidents occur by visiting the [Microsoft Technical Security Notifications page](https://www.microsoft.com/msrc/technical-security-notifications?rtc=1) and subscribing to Security Advisory Alerts.
6969

7070
## Data collection
7171

docs/msi_v2/cert_handling.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Certificate Handling on Windows for MSI v2 / PoP
2+
3+
## Overview
4+
In the MSI v2 flow, the client must present a certificate over mTLS.
5+
The certificate itself is the **credential** for this flow.
6+
7+
Currently, the certificate is stored only in memory.
8+
To reduce repeated calls to IMDS and enable reuse across requests,
9+
the certificate should be **rooted (persisted)** in the Windows certificate store.
10+
11+
## 1. Certificate Store Location
12+
- Use the **Windows Certificate Store**.
13+
- Scope: **CurrentUser\My** store (per-user, not global).
14+
- This provides:
15+
- Secure key isolation (KeyGuard).
16+
- OS-enforced ACLs instead of manual file permissions.
17+
18+
---
19+
20+
## 2. Certificate Lifecycle
21+
22+
1. **Check Cert Store**
23+
- Look in `CurrentUser\My` for an MSI certificate.
24+
- Identify by subject and issuer.
25+
- If found and not expired → load it.
26+
27+
2. **No Valid Certificate**
28+
- Generate a key pair (RSA) in KeyGuard (for POP).
29+
- Get an attestation token for the key.
30+
- Create CSR in memory.
31+
- Call **IMDS issuecredential** endpoint.
32+
- Receive certificate from IMDS.
33+
34+
3. **Persist the Certificate**
35+
- Store the new certificate (with private key) in `CurrentUser\My`.
36+
- Mark the key as **non-exportable**. (uses KeyGuard keys - already non-exportable)
37+
38+
4. **Use Certificate**
39+
- Load cert from store as needed.
40+
- Use it for mTLS handshake.
41+
42+
---
43+
44+
## 3. Expiration and Renewal
45+
- Certificates are short-lived (7 days).
46+
- Always check expiration before use.
47+
- If expired or close to expiry:
48+
- Remove stale cert from store.
49+
- Acquire and persist a new cert from IMDS.
50+
51+
### Proactive Renewal: Start renewal at half the certificate lifetime (typically, 3.5 days) to avoid expiry during active sessions.
52+
53+
**This is calculated based on the certificate’s NotAfter property (expiration date).**
54+
---
55+
56+
## 4. Error Handling
57+
- If store entry is corrupt → remove it and fetch new cert.
58+
- If IMDS call fails → bubble up error to caller.
59+
60+
---
61+
62+
# Certificate Store Location in Linux
63+
- Rely on .NET’s X509Store abstractions for per-user certificate storage. The framework handles platform-specific details.”
64+
65+
---
66+
67+
## 5. Security Considerations
68+
- Private keys must be generated in **CNG/KeyGuard** with `ExportPolicy = None`.
69+
- Keys should **never** be exported or persisted outside the Windows certificate store.
70+
- `CurrentUser\My` is scoped to the signed-in user.
71+
72+
---
73+
74+
## ✅ Summary
75+
- Always **check Windows cert store first** (`CurrentUser\My`).
76+
- If no valid cert, **request one from IMDS**.
77+
- **Persist it** back into the store securely.
78+
- **Refresh on expiration**.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
Microsoft.Identity.Client.MtlsPop.ManagedIdentityPopExtensions
2+
static Microsoft.Identity.Client.MtlsPop.ManagedIdentityPopExtensions.WithMtlsProofOfPossession(this Microsoft.Identity.Client.AcquireTokenForManagedIdentityParameterBuilder builder) -> Microsoft.Identity.Client.AcquireTokenForManagedIdentityParameterBuilder
13

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
Microsoft.Identity.Client.MtlsPop.ManagedIdentityPopExtensions
2-
static Microsoft.Identity.Client.MtlsPop.ManagedIdentityPopExtensions.WithMtlsProofOfPossession(this Microsoft.Identity.Client.AcquireTokenForManagedIdentityParameterBuilder builder) -> Microsoft.Identity.Client.AcquireTokenForManagedIdentityParameterBuilder
1+

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
Microsoft.Identity.Client.MtlsPop.ManagedIdentityPopExtensions
2+
static Microsoft.Identity.Client.MtlsPop.ManagedIdentityPopExtensions.WithMtlsProofOfPossession(this Microsoft.Identity.Client.AcquireTokenForManagedIdentityParameterBuilder builder) -> Microsoft.Identity.Client.AcquireTokenForManagedIdentityParameterBuilder
13

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
Microsoft.Identity.Client.MtlsPop.ManagedIdentityPopExtensions
2-
static Microsoft.Identity.Client.MtlsPop.ManagedIdentityPopExtensions.WithMtlsProofOfPossession(this Microsoft.Identity.Client.AcquireTokenForManagedIdentityParameterBuilder builder) -> Microsoft.Identity.Client.AcquireTokenForManagedIdentityParameterBuilder
1+

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Security.Cryptography.X509Certificates;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.Identity.Client.Core;
9+
10+
namespace Microsoft.Identity.Client.ManagedIdentity.V2
11+
{
12+
/// <summary>
13+
/// Abstraction over the in-memory + persisted cache for IMDSv2 mTLS binding certificates.
14+
/// </summary>
15+
internal interface IMtlsCertificateCache
16+
{
17+
/// <summary>
18+
/// Returns a cached binding certificate for the given <paramref name="cacheKey"/>,
19+
/// or uses <paramref name="factory"/> to create, persist and return one when needed.
20+
/// </summary>
21+
Task<MtlsBindingInfo> GetOrCreateAsync(
22+
string cacheKey,
23+
Func<Task<MtlsBindingInfo>> factory,
24+
CancellationToken cancellationToken,
25+
ILoggerAdapter logger);
26+
}
27+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Security.Cryptography.X509Certificates;
5+
using Microsoft.Identity.Client.Core;
6+
7+
namespace Microsoft.Identity.Client.ManagedIdentity.V2
8+
{
9+
/// <summary>
10+
/// Persistence interface for IMDSv2 mTLS binding certificates.
11+
/// Implementations must be best-effort and non-throwing so that
12+
/// certificate persistence never blocks authentication.
13+
/// </summary>
14+
internal interface IPersistentCertificateCache
15+
{
16+
/// <summary>
17+
/// Reads the newest valid (≥24h remaining, has private key) entry for the alias.
18+
/// Returns <c>true</c> on cache hit, <c>false</c> otherwise.
19+
/// </summary>
20+
bool Read(string alias, out CertificateCacheValue value, ILoggerAdapter logger);
21+
22+
/// <summary>
23+
/// Persists the certificate for the alias (best-effort).
24+
/// Implementations should log failures but must not throw; callers do not
25+
/// depend on persistence succeeding and fall back to in-memory cache only.
26+
/// </summary>
27+
void Write(string alias, X509Certificate2 cert, string endpointBase, ILoggerAdapter logger);
28+
29+
/// <summary>
30+
/// Prunes expired entries for the alias (best-effort).
31+
/// Implementations should remove stale/expired entries while leaving the
32+
/// latest valid binding for the alias in place.
33+
/// </summary>
34+
void Delete(string alias, ILoggerAdapter logger);
35+
}
36+
}

0 commit comments

Comments
 (0)