Skip to content
Draft
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
6 changes: 5 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,15 @@
<PackageVersion Include="Xamarin.AndroidX.Browser" Version="1.4.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<!-- Analyzers and dev packages -->
<!-- Analyzers, dev packages and Lab -->
<PackageVersion Include="Azure.Identity" Version="1.15.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.8" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.8" />
<PackageVersion Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.12.19" PrivateAssets="All" />
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0" PrivateAssets="All" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4" PrivateAssets="All" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" />
</ItemGroup>
<ItemGroup>
<!-- Packages for the tests -->
Expand Down
90 changes: 90 additions & 0 deletions LibsAndSamples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ 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.Labs", "src\client\Microsoft.Identity.Client.Labs\Microsoft.Identity.Client.Labs.csproj", "{0175FBD0-A14C-4742-803A-CCE71B4FA566}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Identity.Client.Labs.Tests", "tests\Microsoft.Identity.Client.Labs.Tests\Microsoft.Identity.Client.Labs.Tests.csproj", "{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug + MobileApps|Any CPU = Debug + MobileApps|Any CPU
Expand Down Expand Up @@ -1907,6 +1911,90 @@ 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
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|Any CPU.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|Any CPU.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|ARM.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|ARM.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|ARM64.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|ARM64.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|iPhone.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|iPhone.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|iPhoneSimulator.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|x64.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|x64.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|x86.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug + MobileApps|x86.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|ARM.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|ARM.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|ARM64.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|iPhone.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|x64.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|x64.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|x86.ActiveCfg = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Debug|x86.Build.0 = Debug|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|Any CPU.Build.0 = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|ARM.ActiveCfg = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|ARM.Build.0 = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|ARM64.ActiveCfg = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|ARM64.Build.0 = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|iPhone.ActiveCfg = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|iPhone.Build.0 = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|x64.ActiveCfg = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|x64.Build.0 = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|x86.ActiveCfg = Release|Any CPU
{0175FBD0-A14C-4742-803A-CCE71B4FA566}.Release|x86.Build.0 = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|Any CPU.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|Any CPU.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|ARM.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|ARM.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|ARM64.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|ARM64.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|iPhone.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|iPhone.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|iPhoneSimulator.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|x64.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|x64.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|x86.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug + MobileApps|x86.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|ARM.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|ARM.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|ARM64.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|iPhone.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|x64.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|x64.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|x86.ActiveCfg = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Debug|x86.Build.0 = Debug|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|Any CPU.Build.0 = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|ARM.ActiveCfg = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|ARM.Build.0 = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|ARM64.ActiveCfg = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|ARM64.Build.0 = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|iPhone.ActiveCfg = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|iPhone.Build.0 = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|x64.ActiveCfg = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|x64.Build.0 = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|x86.ActiveCfg = Release|Any CPU
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1963,6 +2051,8 @@ 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}
{0175FBD0-A14C-4742-803A-CCE71B4FA566} = {1A37FD75-94E9-4D6F-953A-0DABBD7B49E9}
{FD5E59AC-D6D3-18C6-B50A-DE15C654C942} = {9B0B5396-4D95-4C15-82ED-DC22B5A3123F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {020399A9-DC27-4B82-9CAA-EF488665AC27}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.Identity.Client.Labs
{
/// <summary>
/// Declares the Key Vault secret names for an application's credentials.
/// Each property is a secret <em>name</em> (not the secret value).
/// </summary>
public sealed class AppSecretKeys
{
/// <summary>
/// Initializes a new instance of the <see cref="AppSecretKeys"/> class.
/// For optional secrets, pass an empty string (<c>""</c>) to indicate "not configured".
/// </summary>
/// <param name="clientIdSecret">Key Vault secret name that stores the application's client ID.</param>
/// <param name="clientSecretSecret">Optional Key Vault secret name that stores the application's client secret. Use <c>""</c> if not used.</param>
/// <param name="pfxSecret">Optional Key Vault secret name that stores a Base64-encoded PFX certificate. Use <c>""</c> if not used.</param>
/// <param name="pfxPasswordSecret">Optional Key Vault secret name that stores the password for the PFX. Use <c>""</c> if not used.</param>
public AppSecretKeys(
string clientIdSecret,
string clientSecretSecret = "",
string pfxSecret = "",
string pfxPasswordSecret = "")
{
ClientIdSecret = clientIdSecret;
ClientSecretSecret = clientSecretSecret ?? string.Empty;
PfxSecret = pfxSecret ?? string.Empty;
PfxPasswordSecret = pfxPasswordSecret ?? string.Empty;
}

/// <summary>
/// Gets the Key Vault secret name that stores the application's client ID.
/// </summary>
public string ClientIdSecret { get; }

/// <summary>
/// Gets the Key Vault secret name that stores the application's client secret.
/// Empty string indicates "not configured".
/// </summary>
public string ClientSecretSecret { get; }

/// <summary>
/// Gets the Key Vault secret name that stores a Base64-encoded PFX certificate.
/// Empty string indicates "not configured".
/// </summary>
public string PfxSecret { get; }

/// <summary>
/// Gets the Key Vault secret name that stores the password for the PFX certificate.
/// Empty string indicates "not configured".
/// </summary>
public string PfxPasswordSecret { get; }
}
}
134 changes: 134 additions & 0 deletions src/client/Microsoft.Identity.Client.Labs/Abstractions/Enums.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.Identity.Client.Labs
{
/// <summary>
/// Represents the authentication style used by a test user.
/// </summary>
public enum AuthType
Copy link
Member

Choose a reason for hiding this comment

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

We should treat the lab API as a public API, since this is how other SDKs consume it. Do we really need to increase the public surface ?

{
/// <summary>
/// A basic username/password account with no federation or multi-factor authentication (MFA).
/// </summary>
Basic,

/// <summary>
/// A federated account (for example, via ADFS, Ping, or another identity provider).
/// </summary>
Federated,

/// <summary>
/// An account that requires multi-factor authentication (MFA).
/// </summary>
Mfa,

/// <summary>
/// A business-to-business (B2B) guest account invited into the tenant.
/// </summary>
Guest
}

/// <summary>
/// Identifies the cloud or sovereign environment where identities and applications are hosted.
/// </summary>
public enum CloudType
{
/// <summary>
/// Azure Public (global) cloud.
/// </summary>
Public,

/// <summary>
/// Azure Government (GCC/GCC High) cloud.
/// </summary>
Gcc,

/// <summary>
/// Azure Government Department of Defense (DoD) environment.
/// </summary>
Dod,

/// <summary>
/// Azure China cloud (operated by 21Vianet).
/// </summary>
China,

/// <summary>
/// Microsoft Cloud for Germany / Azure Germany.
/// </summary>
Germany,

/// <summary>
/// Integration or pre‑production environment used for testing.
/// </summary>
Canary
}

/// <summary>
/// Names the functional test scenario or user pool.
/// </summary>
public enum Scenario
{
/// <summary>
/// Basic or smoke-test scenarios.
/// </summary>
Basic,

/// <summary>
/// On‑Behalf‑Of (OBO) flow scenarios.
/// </summary>
Obo,

/// <summary>
/// Confidential Client Application (CCA) scenarios.
/// </summary>
Cca,

/// <summary>
/// Device Code flow scenarios.
/// </summary>
DeviceCode,

/// <summary>
/// Resource Owner Password Credentials (ROPC) flow scenarios.
/// </summary>
Ropc,

/// <summary>
/// Daemon (application‑only) scenarios without user interaction.
/// </summary>
Daemon
}

/// <summary>
/// Specifies the type of application whose credentials should be resolved.
/// </summary>
public enum AppKind
{
/// <summary>
/// A public client application (desktop, mobile, or SPA) that does not use a client secret.
/// </summary>
PublicClient,

/// <summary>
/// A confidential client application (web app/service) that authenticates with a client secret or certificate.
/// </summary>
ConfidentialClient,

/// <summary>
/// A headless/background application that runs without user interaction.
/// </summary>
Daemon,

/// <summary>
/// A protected Web API (resource) that validates tokens issued to clients.
/// </summary>
WebApi,

/// <summary>
/// A web application (confidential client) that signs in users and can call downstream APIs.
/// </summary>
WebApp
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;

namespace Microsoft.Identity.Client.Labs
{
/// <summary>
/// Provides a mapping between a user tuple
/// (<see cref="AuthType"/>, <see cref="CloudType"/>, <see cref="Scenario"/>) and the
/// Key Vault secret name that stores the corresponding username.
/// </summary>
public interface IAccountMapProvider
{
/// <summary>
/// Gets a map of tuples to username secret names. The value for each key must be a Key Vault
/// secret name whose value is the username to use for the tuple.
/// </summary>
/// <returns>
/// A read-only dictionary keyed by <c>(authType, cloudType, scenario)</c> whose values are
/// the Key Vault secret names containing usernames.
/// </returns>
IReadOnlyDictionary<(AuthType auth, CloudType cloud, Scenario scenario), string> GetUsernameMap();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Microsoft.Identity.Client.Labs
{
/// <summary>
/// Provides a mapping between an application tuple
/// (<see cref="CloudType"/>, <see cref="Scenario"/>, <see cref="AppKind"/>) and the
/// Key Vault secret names that store its client ID and credentials.
/// </summary>
public interface IAppMapProvider
{
/// <summary>
/// Gets a map of tuples to application secret-name sets.
/// </summary>
/// <returns>
/// A read-only dictionary keyed by <c>(cloudType, scenario, appKind)</c> whose values
/// describe which Key Vault secret names hold each application credential.
/// </returns>
IReadOnlyDictionary<(CloudType cloud, Scenario scenario, AppKind kind), AppSecretKeys> GetAppMap();
}
}
Loading
Loading