microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
next/core-claude-agents

Branches

Tags

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

Clone

HTTPS

Download ZIP

core/samples/PABot/PACustomAuthHandler.cs

76lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Net.Http.Headers;
5using Microsoft.Extensions.Options;
6using Microsoft.Identity.Abstractions;
7using Microsoft.Identity.Web;
8using Microsoft.Teams.Bot.Core.Schema;
9
10namespace PABot
11{
12 internal class PACustomAuthHandler(
13 IAuthorizationHeaderProvider authorizationHeaderProvider,
14 IRoutedTokenAcquisitionService routedTokenService,
15 ILogger<PACustomAuthHandler> logger,
16 string botScope,
17 string? agenticScope = null,
18 IOptions<ManagedIdentityOptions>? managedIdentityOptions = null) : DelegatingHandler
19 {
20 private readonly IAuthorizationHeaderProvider _authorizationHeaderProvider = authorizationHeaderProvider ?? throw new ArgumentNullException(nameof(authorizationHeaderProvider));
21 private readonly IRoutedTokenAcquisitionService _routedTokenService = routedTokenService ?? throw new ArgumentNullException(nameof(routedTokenService));
22 private readonly ILogger<PACustomAuthHandler> _logger = logger ?? throw new ArgumentNullException(nameof(logger));
23 private readonly string _botScope = botScope ?? throw new ArgumentNullException(nameof(botScope));
24 private readonly string _agenticScope = agenticScope ?? botScope; // Default to bot scope if not specified
25 private readonly IOptions<ManagedIdentityOptions>? _managedIdentityOptions = managedIdentityOptions;
26
27 /// <summary>
28 /// Key used to store the agentic identity in HttpRequestMessage options.
29 /// When set, agentic application credentials will be used instead of bot credentials.
30 /// </summary>
31 public static readonly HttpRequestOptionsKey<AgenticIdentity?> AgenticIdentityKey = new("AgenticIdentity");
32
33 /// <inheritdoc/>
34 protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
35 {
36 request.Options.TryGetValue(AgenticIdentityKey, out AgenticIdentity? agenticIdentity);
37
38 string token = await GetAuthorizationHeaderAsync(agenticIdentity, cancellationToken).ConfigureAwait(false);
39
40 string tokenValue = token.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)
41 ? token["Bearer ".Length..]
42 : token;
43
44 request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenValue);
45
46 return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
47 }
48
49 /// <summary>
50 /// Gets an authorization header for API calls.
51 /// Routes to either bot credentials or agentic application credentials based on the presence of AgenticIdentity.
52 /// </summary>
53 /// <param name="agenticIdentity">Optional agentic identity. When provided, agentic application credentials are used.</param>
54 /// <param name="cancellationToken">Cancellation token.</param>
55 /// <returns>The authorization header value.</returns>
56 private async Task<string> GetAuthorizationHeaderAsync(AgenticIdentity? agenticIdentity, CancellationToken cancellationToken)
57 {
58 // If agentic identity is provided, use agentic application credentials with agentic scope
59 if (agenticIdentity is not null &&
60 !string.IsNullOrEmpty(agenticIdentity.AgenticAppId) &&
61 !string.IsNullOrEmpty(agenticIdentity.AgenticUserId))
62 {
63 _logger.LogInformation("Acquiring token using agentic credentials for scope '{Scope}' with AppId '{AppId}' and UserId '{UserId}'.",
64 _agenticScope,
65 agenticIdentity.AgenticAppId,
66 agenticIdentity.AgenticUserId);
67
68 return await _routedTokenService.AcquireTokenForAgenticAsync(agenticIdentity, _agenticScope, cancellationToken).ConfigureAwait(false);
69 }
70
71 // Otherwise, use bot credentials with bot scope
72 _logger.LogInformation("Acquiring token using bot credentials for scope: {Scope}", _botScope);
73 return await _routedTokenService.AcquireTokenForBotAsync(_botScope, cancellationToken).ConfigureAwait(false);
74 }
75 }
76}