microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
next/core

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

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