Skip to content
Open
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
47 changes: 1 addition & 46 deletions LibsAndSamples.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
VisualStudioVersion = 18.0.11217.181 d18.0
Copy link
Member

Choose a reason for hiding this comment

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

The solution file does not add the new project, only deletes the old one.

VisualStudioVersion = 18.0.11217.181
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9B0B5396-4D95-4C15-82ED-DC22B5A3123F}"
ProjectSection(SolutionItems) = preProject
Expand Down Expand Up @@ -192,8 +192,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MacMauiAppWithBroker", "tes
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MacConsoleAppWithBroker", "tests\devapps\MacConsoleAppWithBroker\MacConsoleAppWithBroker.csproj", "{DBD18BC8-72E4-47D4-BD79-8DEBD9F2C0D0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Identity.Client.MtlsPop", "src\client\Microsoft.Identity.Client.MtlsPop\Microsoft.Identity.Client.MtlsPop.csproj", "{3E1C29E5-6E67-D9B2-28DF-649A609937A2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinUI3PackagedSampleApp", "tests\devapps\WinUI3PackagedSampleApp\WinUI3PackagedSampleApp.csproj", "{CE282240-0806-EB91-87E4-D791DC86DEE8}"
EndProject
Global
Expand Down Expand Up @@ -1948,48 +1946,6 @@ Global
{DBD18BC8-72E4-47D4-BD79-8DEBD9F2C0D0}.Release|x64.Build.0 = Release|Any CPU
{DBD18BC8-72E4-47D4-BD79-8DEBD9F2C0D0}.Release|x86.ActiveCfg = Release|Any CPU
{DBD18BC8-72E4-47D4-BD79-8DEBD9F2C0D0}.Release|x86.Build.0 = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|Any CPU.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|Any CPU.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|ARM.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|ARM.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|ARM64.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|ARM64.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|iPhone.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|iPhone.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|iPhoneSimulator.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|x64.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|x64.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|x86.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug + MobileApps|x86.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|ARM.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|ARM.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|ARM64.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|iPhone.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|x64.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|x64.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|x86.ActiveCfg = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Debug|x86.Build.0 = Debug|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|Any CPU.Build.0 = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|ARM.ActiveCfg = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|ARM.Build.0 = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|ARM64.ActiveCfg = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|ARM64.Build.0 = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|iPhone.ActiveCfg = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|iPhone.Build.0 = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|x64.ActiveCfg = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|x64.Build.0 = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|x86.ActiveCfg = Release|Any CPU
{3E1C29E5-6E67-D9B2-28DF-649A609937A2}.Release|x86.Build.0 = Release|Any CPU
{CE282240-0806-EB91-87E4-D791DC86DEE8}.Debug + MobileApps|Any CPU.ActiveCfg = Debug|x64
{CE282240-0806-EB91-87E4-D791DC86DEE8}.Debug + MobileApps|Any CPU.Build.0 = Debug|x64
{CE282240-0806-EB91-87E4-D791DC86DEE8}.Debug + MobileApps|ARM.ActiveCfg = Debug|x64
Expand Down Expand Up @@ -2089,7 +2045,6 @@ Global
{97995B86-AA0F-3AF9-DA40-85A6263E4391} = {9B0B5396-4D95-4C15-82ED-DC22B5A3123F}
{AEF6BB00-931F-4638-955D-24D735625C34} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB}
{DBD18BC8-72E4-47D4-BD79-8DEBD9F2C0D0} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB}
{3E1C29E5-6E67-D9B2-28DF-649A609937A2} = {1A37FD75-94E9-4D6F-953A-0DABBD7B49E9}
{CE282240-0806-EB91-87E4-D791DC86DEE8} = {34BE693E-3496-45A4-B1D2-D3A0E068EEDB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
1 change: 0 additions & 1 deletion prototype/MsiV2DemoApp/MsiV2DemoApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

<ItemGroup>
<PackageReference Include="Microsoft.Identity.Client" />
<PackageReference Include="Microsoft.Identity.Client.MtlsPop" />
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need to add the new project reference?

</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace Microsoft.Identity.Client.MtlsPop.Attestation
namespace Microsoft.Identity.Client.KeyAttestation
{
/// <summary>
/// Managed façade for <c>AttestationClientLib.dll</c>. Holds initialization state,
/// does ref-count hygiene on <see cref="SafeNCryptKeyHandle"/>, and returns a JWT.
/// </summary>
internal sealed class AttestationClient : IDisposable
Copy link
Member

Choose a reason for hiding this comment

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

This should not be part of the public API

public sealed class AttestationClient : IDisposable
{
private bool _initialized;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.Win32.SafeHandles;
using System;
using System.IO;
using System.Runtime.InteropServices;

namespace Microsoft.Identity.Client.MtlsPop.Attestation
namespace Microsoft.Identity.Client.KeyAttestation
{
internal static class AttestationClientLib
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.Identity.Client.MtlsPop.Attestation
namespace Microsoft.Identity.Client.KeyAttestation
{
internal static class AttestationErrors
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Microsoft.Identity.Client.MtlsPop.Attestation
namespace Microsoft.Identity.Client.KeyAttestation
{
internal static class AttestationLogger
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.Identity.Client.MtlsPop.Attestation
namespace Microsoft.Identity.Client.KeyAttestation
{
/// <summary>
/// AttestationResult is the result of an attestation operation.
Expand All @@ -20,7 +20,7 @@ namespace Microsoft.Identity.Client.MtlsPop.Attestation
/// expression, e.g.: var updated = result with { Jwt = newJwt };
/// The netstandard2.0 target relies on the IsExternalInit shim (see IsExternalInit.cs) to enable 'init'.
/// </remarks>
internal sealed record AttestationResult(
public sealed record AttestationResult(
Copy link
Contributor

Choose a reason for hiding this comment

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

does this need to be public? think the safest way it to just rename the project and not recreate a new project. seems like there are many changes that are not necessary

AttestationStatus Status,
string Jwt,
int NativeErrorCode,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.Identity.Client.MtlsPop.Attestation
namespace Microsoft.Identity.Client.KeyAttestation
{
/// <summary>
/// Error codes returned by <c>AttestationClientLib.dll</c>.
Expand Down Expand Up @@ -35,7 +35,7 @@ internal enum AttestationResultErrorCode
/// <summary>The attestation enclave rejected the supplied evidence (policy or signature failure).</summary>
ERRORATTESTATIONFAILED = -6,

/// <summary>libcurl reported couldnt send (DNS resolution, TLS handshake, or socket error).</summary>
/// <summary>libcurl reported "couldn't send" (DNS resolution, TLS handshake, or socket error).</summary>
ERRORSENDINGCURLREQUESTFAILED = -7,

/// <summary>One or more input parameters passed to the native API were invalid or null.</summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.Identity.Client.MtlsPop.Attestation
namespace Microsoft.Identity.Client.KeyAttestation
{
/// <summary>
/// High-level outcome categories returned by <see cref="AttestationClient.Attest"/>.
/// </summary>
internal enum AttestationStatus
public enum AttestationStatus
Copy link
Member

Choose a reason for hiding this comment

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

Should not be part of the public API

{
/// <summary>Everything succeeded; <see cref="AttestationResult.Jwt"/> is populated.</summary>
Success = 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#if NETSTANDARD
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.ManagedIdentity;

namespace Microsoft.Identity.Client.KeyAttestation
{
/// <summary>
/// Extension methods for enabling KeyGuard attestation support in managed identity mTLS PoP flows.
/// </summary>
public static class ManagedIdentityAttestationExtensions
{
/// <summary>
/// Enables KeyGuard attestation support for managed identity mTLS Proof-of-Possession flows.
/// This method should be called after <see cref="ManagedIdentityPopExtensions.WithMtlsProofOfPossession"/>.
/// </summary>
/// <param name="builder">The AcquireTokenForManagedIdentityParameterBuilder instance.</param>
/// <returns>The builder to chain .With methods.</returns>
public static AcquireTokenForManagedIdentityParameterBuilder WithAttestationSupport(
this AcquireTokenForManagedIdentityParameterBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}

// Register the attestation token provider
return builder.WithAttestationProviderForTests(async (req, ct) =>
Copy link
Member

Choose a reason for hiding this comment

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

Why is builder method suffixed with "ForTests" ? It is production code.

{
// Get the caller-provided KeyGuard/CNG handle
var keyHandle = req.KeyHandle;

if (keyHandle == null)
{
throw new MsalClientException(
"attestation_key_handle_missing",
"KeyHandle is required for attestation but was not provided.");
}

// Call the native interop via PopKeyAttestor
AttestationResult attestationResult = await PopKeyAttestor.AttestKeyGuardAsync(
req.AttestationEndpoint.AbsoluteUri,
keyHandle,
req.ClientId ?? string.Empty,
ct).ConfigureAwait(false);

// Map to MSAL's internal response
if (attestationResult != null &&
attestationResult.Status == AttestationStatus.Success &&
!string.IsNullOrWhiteSpace(attestationResult.Jwt))
{
return new AttestationTokenResponse { AttestationToken = attestationResult.Jwt };
}

throw new MsalClientException(
"attestation_failure",
$"Key Attestation failed " +
$"(status={attestationResult?.Status}, " +
$"code={attestationResult?.NativeErrorCode}). {attestationResult?.ErrorMessage}");
});
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<!-- ─── Target frameworks ─────────────────────────────────────────────── -->
<PropertyGroup>
Expand All @@ -19,20 +19,14 @@
<!--This will generate AssemblyVersion, AssemblyFileVersion and AssemblyInformationVersion-->
<Version>$(MicrosoftIdentityClientVersion)-preview</Version>
<!-- Copyright needs to be in the form of © not (c) to be compliant -->
<Title>MSAL.NET extension for managed identity proof-of-possession flows</Title>
<Title>MSAL.NET extension for KeyGuard attestation support</Title>
Copy link
Contributor

Choose a reason for hiding this comment

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

<Description>
This package contains binaries needed to use managed identity proof-of-possession (MTLS PoP) flows in applications using MSAL.NET.
This package contains binaries needed to enable KeyGuard attestation in managed identity proof-of-possession (mTLS PoP) flows using MSAL.NET.
</Description>
<PackageTags>Microsoft Authentication Library Managed Identity MSAL Proof-of-Possession</PackageTags>
<PackageTags>Microsoft Authentication Library Managed Identity MSAL KeyGuard Attestation Proof-of-Possession</PackageTags>
<Product>Microsoft Authentication Library</Product>
</PropertyGroup>

<!-- ─── File inclusions ───────────────────────────────────────────────── -->
<ItemGroup>
<Compile Include="..\Microsoft.Identity.Client\Properties\InternalsVisibleTo.cs"
Link="Properties\InternalsVisibleTo.cs" />
</ItemGroup>

<!-- ─── References ────────────────────────────────────────────────────── -->
<ItemGroup>
<ProjectReference Include="..\Microsoft.Identity.Client\Microsoft.Identity.Client.csproj" />
Expand All @@ -42,6 +36,11 @@
<PackageReference Include="System.Security.Cryptography.Cng" />
</ItemGroup>

<PropertyGroup>
<!-- Temporarily disable PublicAPI analyzer to generate correct signatures -->
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need these?

<NoWarn>$(NoWarn);RS0016;RS0017;RS0036;RS0041</NoWarn>
</PropertyGroup>

<ItemGroup Label="For public api analyzer support">
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Shipped.txt" />
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.ComponentModel;
using System.IO;

namespace Microsoft.Identity.Client.MtlsPop.Attestation
namespace Microsoft.Identity.Client.KeyAttestation
{
internal static class NativeDiagnostics
{
Expand Down Expand Up @@ -38,7 +38,7 @@ internal static string ProbeNativeDll()
return $"Unable to load {NativeDll}: {ex.Message}";
}

// success – unload and return null (meaning no error)
// success – unload and return null (meaning "no error")
WindowsDllLoader.Free(h);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client.MtlsPop.Attestation;
using Microsoft.Win32.SafeHandles;

namespace Microsoft.Identity.Client.MtlsPop
namespace Microsoft.Identity.Client.KeyAttestation
{
/// <summary>
/// Static facade for attesting a KeyGuard/CNG key and getting a JWT back.
/// Key discovery / rotation is the caller's responsibility.
/// </summary>
internal static class PopKeyAttestor
public static class PopKeyAttestor
Copy link
Contributor

Choose a reason for hiding this comment

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

should this be public?

{
/// <summary>
/// Asynchronously attests a KeyGuard/CNG key with the remote attestation service and returns a JWT.
Expand Down
Loading
Loading