Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
38dbae3
CSR Metadata request acts as a probe for ImdsV2 (#5359)
Robbie-Microsoft Aug 4, 2025
4b2453d
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Aug 5, 2025
faa28bc
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Aug 6, 2025
7bc1735
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Aug 6, 2025
024e7b4
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Aug 22, 2025
8c03bb3
Imdsv2: Generate CSR and execute CSR request (#5427)
Robbie-Microsoft Aug 27, 2025
24f599a
Minor adjustments
Robbie-Microsoft Aug 27, 2025
b75e879
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Aug 27, 2025
ea15d19
private -> public, for unit tests
Robbie-Microsoft Aug 27, 2025
2ce7e1b
ImdsV2: Implemented downlevel polyfill for CertificateRequest (#5454)
Robbie-Microsoft Aug 29, 2025
fdf2038
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Aug 29, 2025
ddc2117
ImdsV2: Acquire Entra Token Over mTLS (#5431)
Robbie-Microsoft Aug 29, 2025
d0b0edf
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Sep 5, 2025
5825f50
ImdsV2: Miscellanious Updates Discovered by Manual Testing (#5477)
Robbie-Microsoft Sep 13, 2025
15bbfc1
ImdsV2: Added Additional Headers to the Entra Token Request (#5459)
Robbie-Microsoft Sep 15, 2025
d41a874
MSIV2: net8.0 Unit Test Fixes (#5480)
Robbie-Microsoft Sep 17, 2025
8c4c255
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Sep 17, 2025
2518f1b
MSI V2 - Adding Attestation package for mTLS POP MSI flows (#5483)
gladjohn Sep 18, 2025
e06b4b0
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Sep 19, 2025
8099d17
Fixed broken unit test + created helper function for code re-use
Robbie-Microsoft Sep 19, 2025
774e01e
MSI V2 client side keys (#5448)
gladjohn Sep 19, 2025
0897cce
ImdsV2: Integrated .WithMtlsProofOfPossession (#5490)
Robbie-Microsoft Sep 19, 2025
717e59e
[MSI v2] - Pass the actual resource to IMDS (#5497)
gladjohn Sep 23, 2025
d180eb1
ImdsV2: Entra Request: "expires_in" is now lumped into "expires_on" (…
Robbie-Microsoft Sep 24, 2025
42587b5
ImdsV2: WithExtraQueryParameters (#5492)
Robbie-Microsoft Sep 25, 2025
693e917
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Sep 25, 2025
c2eddde
Add ResetStateForTest API for test (#5489)
bgavrilMS Sep 26, 2025
087130e
undid commit where code was supopsed to be stashed
Robbie-Microsoft Sep 26, 2025
89ff42a
[MSI v2] - Enable attestation in pop flows (#5496)
gladjohn Sep 29, 2025
8464e83
ImdsV2: .WithMtlsProofOfPossession Will Throw on NET462 for Managed I…
Robbie-Microsoft Oct 2, 2025
c706896
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Oct 2, 2025
1ae351b
IMDSv2: Fixed Broken Unit Test (#5516)
Robbie-Microsoft Oct 3, 2025
1c399c3
ImdsV2: Throw on MTLS when OS is not Windows (#5520)
Robbie-Microsoft Oct 7, 2025
732c9d6
ImdsV2: Added Caching for the IMDS Endpoint Env Variable + Improved U…
Robbie-Microsoft Oct 7, 2025
2fc14f7
Merge branch 'main' into rginsburg/msiv2_feature_branch
Robbie-Microsoft Oct 7, 2025
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
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
<PackageVersion Include="System.ComponentModel.TypeConverter" Version="4.3.0" />
<!-- Should match Azure Functions runtime: https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/4456 -->
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="6.0.1" />
<PackageVersion Include="System.Formats.Asn1" Version="9.0.8" />
<PackageVersion Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageVersion Include="System.Net.NameResolution" Version="4.3.0" />
<PackageVersion Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
<PackageVersion Include="System.Runtime.Serialization.Json" Version="4.3.0" />
<PackageVersion Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
<PackageVersion Include="System.Security.Cryptography.Cng" Version="5.0.0" PrivateAssets="All" />
<PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="4.5.0" />
<PackageVersion Include="System.Security.SecureString" Version="4.3.0" />
<PackageVersion Include="System.ServiceModel.Http" Version="4.5.3" />
Expand Down Expand Up @@ -73,7 +75,6 @@
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="6.35.0" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Reflection.TypeExtensions" Version="4.7.0" />
<PackageVersion Include="System.Security.Cryptography.Cng" Version="5.0.0" />
<PackageVersion Include="System.Text.Json" Version="6.0.10" />
<PackageVersion Include="System.Threading" Version="4.3.0" />
<PackageVersion Include="System.Threading.Tasks" Version="4.3.0" />
Expand All @@ -82,6 +83,5 @@
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
<PackageVersion Include="System.Windows.Forms" Version="4.0.0" />
<PackageVersion Include="CommandLineParser" Version="2.8.0" />
<PackageVersion Include="System.Formats.Asn1" Version="9.0.0" />
</ItemGroup>
</Project>
45 changes: 45 additions & 0 deletions LibsAndSamples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ 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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug + MobileApps|Any CPU = Debug + MobileApps|Any CPU
Expand Down Expand Up @@ -1987,6 +1989,48 @@ 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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -2045,6 +2089,7 @@ 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}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {020399A9-DC27-4B82-9CAA-EF488665AC27}
Expand Down
7 changes: 7 additions & 0 deletions build/template-pack-and-sign-all-nugets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ steps:
ProjectRootPath: '$(Build.SourcesDirectory)\$(MsalSourceDir)src\client'
AssemblyName: 'Microsoft.Identity.Client.Extensions.Msal'

# Sign binary and pack Microsoft.Identity.Client.MtlsPop
- template: template-pack-and-sign-nuget.yaml
parameters:
BuildConfiguration: ${{ parameters.BuildConfiguration }}
ProjectRootPath: '$(Build.SourcesDirectory)\$(MsalSourceDir)src\client'
AssemblyName: 'Microsoft.Identity.Client.MtlsPop'

# Copy all packages out to staging
- task: CopyFiles@2
displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)\packages'
Expand Down
2 changes: 1 addition & 1 deletion build/template-run-mi-e2e-azurearc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ steps:
codeCoverageEnabled: false
failOnMinTestsNotRun: true
minimumExpectedTests: '1'
testFiltercriteria: 'TestCategory=MI_E2E_AzureArc'
testFiltercriteria: '(TestCategory=MI_E2E_AzureArc|TestCategory=MI_E2E_KeyAcquisition_KeyGuard)'
2 changes: 1 addition & 1 deletion build/template-run-mi-e2e-imds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ steps:
runInParallel: false
failOnMinTestsNotRun: true
minimumExpectedTests: '1'
testFiltercriteria: 'TestCategory=MI_E2E_Imds'
testFiltercriteria: '(TestCategory=MI_E2E_Imds|TestCategory=MI_E2E_KeyAcquisition_Hardware)'
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// 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
{
/// <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
{
private bool _initialized;

/// <summary>
/// AttestationClient constructor. Pro-actively verifies the native DLL.
/// </summary>
/// <exception cref="InvalidOperationException"></exception>
public AttestationClient()
{
/* step 0 ── ensure the resolver probes all valid locations
(env override → app base → System32/SysWOW64 → PATH) */
NativeDllResolver.EnsureLoaded();

/* step 1 ── optional proactive verification (non-fatal)
Keep the probe for diagnostics, but do NOT throw here; if the DLL
is truly unavailable/mismatched, InitAttestationLib will fail. */
string dllError = NativeDiagnostics.ProbeNativeDll();
// intentionally not throwing on dllError to avoid path-specific false negatives

/* step 2 ── load & initialize (logger is required by native lib) */
var info = new AttestationClientLib.AttestationLogInfo
{
Log = AttestationLogger.ConsoleLogger, // minimal rooted delegate; works on netstandard2.0 & net8.0
Ctx = IntPtr.Zero
};

_initialized = AttestationClientLib.InitAttestationLib(ref info) == 0;
if (!_initialized)
throw new InvalidOperationException("Failed to initialize AttestationClientLib.");
}

/// <summary>
/// Calls the native <c>AttestKeyGuardImportKey</c> and returns a structured result.
/// </summary>
public AttestationResult Attest(string endpoint,
SafeNCryptKeyHandle keyHandle,
string clientId)
{
if (!_initialized)
return new(AttestationStatus.NotInitialized, null, -1,
"Native library not initialized.");

IntPtr buf = IntPtr.Zero;
bool addRef = false;

try
{
keyHandle.DangerousAddRef(ref addRef);

int rc = AttestationClientLib.AttestKeyGuardImportKey(
endpoint, null, null, keyHandle, out buf, clientId);

if (rc != 0)
return new(AttestationStatus.NativeError, null, rc, null);

if (buf == IntPtr.Zero)
return new(AttestationStatus.TokenEmpty, null, 0,
"rc==0 but token buffer was null.");

string jwt = Marshal.PtrToStringAnsi(buf)!;
return new(AttestationStatus.Success, jwt, 0, null);
}
catch (DllNotFoundException ex)
{
return new(AttestationStatus.Exception, null, -1,
$"Native DLL not found: {ex.Message}");
}
catch (BadImageFormatException ex)
{
return new(AttestationStatus.Exception, null, -1,
$"Architecture mismatch (x86/x64) or corrupted DLL: {ex.Message}");
}
catch (SEHException ex)
{
return new(AttestationStatus.Exception, null, -1,
$"Native library raised SEHException: {ex.Message}");
}
catch (Exception ex)
{
return new(AttestationStatus.Exception, null, -1, ex.Message);
}
finally
{
if (buf != IntPtr.Zero)
AttestationClientLib.FreeAttestationToken(buf);
if (addRef)
keyHandle.DangerousRelease();
}
}

/// <summary>
/// Disposes the client, releasing any resources and un-initializing the native library.
/// </summary>
public void Dispose()
{
if (_initialized)
{
AttestationClientLib.UninitAttestationLib();
_initialized = false;
}
GC.SuppressFinalize(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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
{
internal static class AttestationClientLib
{
internal enum LogLevel { Error, Warn, Info, Debug }

internal delegate void LogFunc(
IntPtr ctx, string tag, LogLevel lvl, string func, int line, string msg);

[StructLayout(LayoutKind.Sequential)]
internal struct AttestationLogInfo
{
public LogFunc Log;
public IntPtr Ctx;
}

[DllImport("AttestationClientLib.dll", CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
internal static extern int InitAttestationLib(ref AttestationLogInfo info);

[DllImport("AttestationClientLib.dll", CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi)]
internal static extern int AttestKeyGuardImportKey(
string endpoint,
string authToken,
string clientPayload,
SafeNCryptKeyHandle keyHandle,
out IntPtr token,
string clientId);

[DllImport("AttestationClientLib.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void FreeAttestationToken(IntPtr token);

[DllImport("AttestationClientLib.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void UninitAttestationLib();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 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
{
internal static class AttestationErrors
{
internal static string Describe(AttestationResultErrorCode rc) => rc switch
{
AttestationResultErrorCode.ERRORCURLINITIALIZATION
=> "libcurl failed to initialize (DLL missing or version mismatch).",
AttestationResultErrorCode.ERRORHTTPREQUESTFAILED
=> "Could not reach the attestation service (network / proxy?).",
AttestationResultErrorCode.ERRORATTESTATIONFAILED
=> "The enclave rejected the evidence (key type / PCR policy).",
AttestationResultErrorCode.ERRORJWTDECRYPTIONFAILED
=> "The JWT returned by the service could not be decrypted.",
AttestationResultErrorCode.ERRORLOGGERINITIALIZATION
=> "Native logger setup failed (rare).",
_ => rc.ToString() // default: enum name
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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
{
internal static class AttestationLogger
{
/// <summary>
/// Attestation Logger
/// </summary>
internal static readonly AttestationClientLib.LogFunc ConsoleLogger = (ctx, tag, lvl, func, line, msg) =>
{
try
{
string sTag = ToText(tag);
string sFunc = ToText(func);
string sMsg = ToText(msg);

var lineText = $"[MtlsPop][{lvl}] {sTag} {sFunc}:{line} {sMsg}";

// Default: Trace (respects listeners; safe for all app types)
Trace.WriteLine(lineText);

// Opt-in console mirroring for local debugging
if (Environment.GetEnvironmentVariable("MSAL_MTLSPOP_LOG_TO_CONSOLE") == "1")
{
Console.WriteLine(lineText);
}
}
catch
{
}
};

// Converts either string or IntPtr (char*) to text. Works with any LogFunc variant.
private static string ToText(object value)
{
if (value is IntPtr p && p != IntPtr.Zero)
{
try
{ return Marshal.PtrToStringAnsi(p) ?? string.Empty; }
catch { return string.Empty; }
}
return value?.ToString() ?? string.Empty;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.Identity.Client.MtlsPop.Attestation
{
/// <summary>
/// AttestationResult is the result of an attestation operation.
/// </summary>
/// <param name="Status"></param>
/// <param name="Jwt"></param>
/// <param name="NativeErrorCode"></param>
/// <param name="ErrorMessage"></param>
internal sealed record AttestationResult(
AttestationStatus Status,
string Jwt,
int NativeErrorCode,
string ErrorMessage);
}
Loading
Loading