microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
samples/migration-bot

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

core/src/Microsoft.Teams.Bot.Core/Hosting/MsalConfigurationExtensions.cs

157lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using Microsoft.Extensions.Configuration;
5using Microsoft.Extensions.DependencyInjection;
6using Microsoft.Extensions.Logging;
7using Microsoft.Extensions.Options;
8using Microsoft.Identity.Abstractions;
9using Microsoft.Identity.Web;
10
11namespace Microsoft.Teams.Bot.Core.Hosting;
12
13/// <summary>
14/// Provides extension methods for configuring MSAL (Microsoft Authentication Library) with different credential types.
15/// </summary>
16internal static class MsalConfigurationExtensions
17{
18 internal const string MsalConfigKey = "AzureAd";
19
20 /// <summary>
21 /// Configures MSAL authentication based on the provided BotConfig.
22 /// </summary>
23 /// <param name="services">The service collection to configure.</param>
24 /// <param name="botConfig">The bot configuration containing authentication settings.</param>
25 /// <param name="logger">Logger for configuration messages.</param>
26 /// <returns>True if MSAL was configured, false if ClientId is not present.</returns>
27 internal static bool ConfigureMSAL(this IServiceCollection services, BotConfig botConfig, ILogger logger)
28 {
29 ArgumentNullException.ThrowIfNull(botConfig);
30
31 if (string.IsNullOrWhiteSpace(botConfig.ClientId))
32 {
33 // Don't configure MSAL if ClientId is not present
34 return false;
35 }
36 else if (botConfig.MsalConfigurationSection != null)
37 {
38 services.ConfigureMSALFromConfig(botConfig.MsalConfigurationSection);
39 }
40 else
41 {
42 services.ConfigureMSALFromBotConfig(botConfig, logger);
43 }
44
45 return true;
46 }
47
48 private static IServiceCollection ConfigureMSALFromConfig(this IServiceCollection services, IConfigurationSection msalConfigSection)
49 {
50 ArgumentNullException.ThrowIfNull(msalConfigSection);
51 services.Configure<MicrosoftIdentityApplicationOptions>(MsalConfigKey, msalConfigSection);
52 return services;
53 }
54
55 private static IServiceCollection ConfigureMSALWithSecret(this IServiceCollection services, string tenantId, string clientId, string clientSecret)
56 {
57 ArgumentException.ThrowIfNullOrWhiteSpace(tenantId);
58 ArgumentException.ThrowIfNullOrWhiteSpace(clientId);
59 ArgumentException.ThrowIfNullOrWhiteSpace(clientSecret);
60
61 services.Configure<MicrosoftIdentityApplicationOptions>(MsalConfigKey, options =>
62 {
63 options.Instance = "https://login.microsoftonline.com/";
64 options.TenantId = tenantId;
65 options.ClientId = clientId;
66 options.ClientCredentials = [
67 new CredentialDescription()
68 {
69 SourceType = CredentialSource.ClientSecret,
70 ClientSecret = clientSecret
71 }
72 ];
73 });
74 return services;
75 }
76
77 private static IServiceCollection ConfigureMSALWithFIC(this IServiceCollection services, string tenantId, string clientId, string? ficClientId)
78 {
79 ArgumentException.ThrowIfNullOrWhiteSpace(tenantId);
80 ArgumentException.ThrowIfNullOrWhiteSpace(clientId);
81
82 CredentialDescription ficCredential = new()
83 {
84 SourceType = CredentialSource.SignedAssertionFromManagedIdentity,
85 };
86 if (!string.IsNullOrEmpty(ficClientId) && !IsSystemAssignedManagedIdentity(ficClientId))
87 {
88 ficCredential.ManagedIdentityClientId = ficClientId;
89 }
90
91 services.Configure<MicrosoftIdentityApplicationOptions>(MsalConfigKey, options =>
92 {
93 options.Instance = "https://login.microsoftonline.com/";
94 options.TenantId = tenantId;
95 options.ClientId = clientId;
96 options.ClientCredentials = [
97 ficCredential
98 ];
99 });
100 return services;
101 }
102
103 private static IServiceCollection ConfigureMSALWithUMI(this IServiceCollection services, string tenantId, string clientId, string? managedIdentityClientId = null)
104 {
105 ArgumentNullException.ThrowIfNullOrWhiteSpace(tenantId);
106 ArgumentNullException.ThrowIfNullOrWhiteSpace(clientId);
107
108 // Register ManagedIdentityOptions for BotAuthenticationHandler to use
109 bool isSystemAssigned = IsSystemAssignedManagedIdentity(managedIdentityClientId);
110 string? umiClientId = isSystemAssigned ? null : (managedIdentityClientId ?? clientId);
111
112 services.Configure<ManagedIdentityOptions>(options =>
113 {
114 options.UserAssignedClientId = umiClientId;
115 });
116
117 services.Configure<MicrosoftIdentityApplicationOptions>(MsalConfigKey, options =>
118 {
119 options.Instance = "https://login.microsoftonline.com/";
120 options.TenantId = tenantId;
121 options.ClientId = clientId;
122 });
123 return services;
124 }
125
126 private static IServiceCollection ConfigureMSALFromBotConfig(this IServiceCollection services, BotConfig botConfig, ILogger logger)
127 {
128 ArgumentNullException.ThrowIfNull(botConfig);
129 if (!string.IsNullOrEmpty(botConfig.ClientSecret))
130 {
131 _logUsingClientSecret(logger, null);
132 services.ConfigureMSALWithSecret(botConfig.TenantId, botConfig.ClientId, botConfig.ClientSecret);
133 }
134 else if (string.IsNullOrEmpty(botConfig.FicClientId) || botConfig.FicClientId == botConfig.ClientId)
135 {
136 _logUsingUMI(logger, null);
137 services.ConfigureMSALWithUMI(botConfig.TenantId, botConfig.ClientId, botConfig.FicClientId);
138 }
139 else
140 {
141 bool isSystemAssigned = IsSystemAssignedManagedIdentity(botConfig.FicClientId);
142 _logUsingFIC(logger, isSystemAssigned ? "System-Assigned" : "User-Assigned", null);
143 services.ConfigureMSALWithFIC(botConfig.TenantId, botConfig.ClientId, botConfig.FicClientId);
144 }
145 return services;
146 }
147
148 private static bool IsSystemAssignedManagedIdentity(string? clientId)
149 => string.Equals(clientId, BotConfig.SystemManagedIdentityIdentifier, StringComparison.OrdinalIgnoreCase);
150
151 private static readonly Action<ILogger, Exception?> _logUsingClientSecret =
152 LoggerMessage.Define(LogLevel.Debug, new(1), "Configuring authentication with client secret");
153 private static readonly Action<ILogger, Exception?> _logUsingUMI =
154 LoggerMessage.Define(LogLevel.Debug, new(2), "Configuring authentication with User-Assigned Managed Identity");
155 private static readonly Action<ILogger, string, Exception?> _logUsingFIC =
156 LoggerMessage.Define<string>(LogLevel.Debug, new(3), "Configuring authentication with Federated Identity Credential (Managed Identity) with {IdentityType} Managed Identity");
157}
158