From 381146a6969d10f8d33fa1087e43deca88a326c6 Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Tue, 29 Jun 2021 15:27:09 -0700 Subject: [PATCH 1/3] Enable SendMessageToTeamsChannel with either BotFrameworkAdapter or CloudAdapter --- .../Actions/SendMessageToTeamsChannel.cs | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs b/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs index 5aa027bba1..81d0ada9b5 100644 --- a/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs +++ b/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs @@ -119,20 +119,38 @@ public SendMessageToTeamsChannel([CallerFilePath] string callerPath = "", [Calle teamsChannelId = dc.Context.Activity.TeamsGetChannelId(); } - // Retrieve the bot appid from TurnState's ClaimsIdentity - string appId; - if (dc.Context.TurnState.Get(BotAdapter.BotIdentityKey) is ClaimsIdentity botIdentity) + Tuple result; + + // Check for legacy adapter + if (dc.Context.Adapter is BotFrameworkAdapter botFrameworkAdapter) { - appId = JwtTokenValidation.GetAppIdFromClaims(botIdentity.Claims); + // TeamsInfo.SendMessageToTeamsChannelAsync requires AppCredentials + var credentials = dc.Context.TurnState.Get()?.Credentials as MicrosoftAppCredentials; + if (credentials == null) + { + throw new InvalidOperationException($"Missing credentials as {nameof(MicrosoftAppCredentials)} in {nameof(IConnectorClient)} from TurnState"); + } + + // The result comes back as a tuple, which is used to set the two properties (if present). + result = await TeamsInfo.SendMessageToTeamsChannelAsync(dc.Context, activity, teamsChannelId, credentials, cancellationToken: cancellationToken).ConfigureAwait(false); } else { - throw new InvalidOperationException($"Missing {BotAdapter.BotIdentityKey} in {nameof(ITurnContext)} TurnState"); + // Retrieve the bot appid from TurnState's ClaimsIdentity + string appId; + if (dc.Context.TurnState.Get(BotAdapter.BotIdentityKey) is ClaimsIdentity botIdentity) + { + appId = JwtTokenValidation.GetAppIdFromClaims(botIdentity.Claims); + } + else + { + throw new InvalidOperationException($"Missing {BotAdapter.BotIdentityKey} in {nameof(ITurnContext)} TurnState"); + } + + // The result comes back as a tuple, which is used to set the two properties (if present). + result = await TeamsInfo.SendMessageToTeamsChannelAsync(dc.Context, activity, teamsChannelId, appId, cancellationToken: cancellationToken).ConfigureAwait(false); } - // The result comes back as a tuple, which is used to set the two properties (if present). - var result = await TeamsInfo.SendMessageToTeamsChannelAsync(dc.Context, activity, teamsChannelId, appId, cancellationToken: cancellationToken).ConfigureAwait(false); - if (ConversationReferenceProperty != null) { dc.State.SetValue(ConversationReferenceProperty.GetValue(dc.State), result.Item1); From 7961bbf9dfda965f2bef6d3771f18463c54ac3ae Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Wed, 30 Jun 2021 10:16:21 -0700 Subject: [PATCH 2/3] Get appId from claims --- .../dotnet/Actions/SendMessageToTeamsChannel.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs b/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs index 81d0ada9b5..2385367342 100644 --- a/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs +++ b/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs @@ -2,6 +2,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. using System; +using System.Linq; using System.Runtime.CompilerServices; using System.Security.Claims; using System.Threading; @@ -140,11 +141,21 @@ public SendMessageToTeamsChannel([CallerFilePath] string callerPath = "", [Calle string appId; if (dc.Context.TurnState.Get(BotAdapter.BotIdentityKey) is ClaimsIdentity botIdentity) { + // Apparently 'version' is sometimes empty, which will result in no id returned from GetAppIdFromClaims appId = JwtTokenValidation.GetAppIdFromClaims(botIdentity.Claims); + if (string.IsNullOrEmpty(appId)) + { + appId = botIdentity.Claims.FirstOrDefault(claim => claim.Type == AuthenticationConstants.AudienceClaim)?.Value; + } + + if (string.IsNullOrEmpty(appId)) + { + throw new InvalidOperationException($"Missing AppIdClaim in ClaimsIdentity."); + } } else { - throw new InvalidOperationException($"Missing {BotAdapter.BotIdentityKey} in {nameof(ITurnContext)} TurnState"); + throw new InvalidOperationException($"Missing {BotAdapter.BotIdentityKey} in {nameof(ITurnContext)} TurnState."); } // The result comes back as a tuple, which is used to set the two properties (if present). From b6f34aaba2f35976821cf6926677e3bb1bf17ec2 Mon Sep 17 00:00:00 2001 From: Eric Dahlvang Date: Wed, 30 Jun 2021 14:11:02 -0700 Subject: [PATCH 3/3] Throw if adapter is not a known type to support SendMessageToTeamsChannel --- .../Teams/dotnet/Actions/SendMessageToTeamsChannel.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs b/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs index 2385367342..9f65d59452 100644 --- a/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs +++ b/packages/Teams/dotnet/Actions/SendMessageToTeamsChannel.cs @@ -123,7 +123,7 @@ public SendMessageToTeamsChannel([CallerFilePath] string callerPath = "", [Calle Tuple result; // Check for legacy adapter - if (dc.Context.Adapter is BotFrameworkAdapter botFrameworkAdapter) + if (dc.Context.Adapter is BotFrameworkAdapter) { // TeamsInfo.SendMessageToTeamsChannelAsync requires AppCredentials var credentials = dc.Context.TurnState.Get()?.Credentials as MicrosoftAppCredentials; @@ -134,8 +134,8 @@ public SendMessageToTeamsChannel([CallerFilePath] string callerPath = "", [Calle // The result comes back as a tuple, which is used to set the two properties (if present). result = await TeamsInfo.SendMessageToTeamsChannelAsync(dc.Context, activity, teamsChannelId, credentials, cancellationToken: cancellationToken).ConfigureAwait(false); - } - else + } + else if (dc.Context.Adapter is CloudAdapterBase) { // Retrieve the bot appid from TurnState's ClaimsIdentity string appId; @@ -161,6 +161,10 @@ public SendMessageToTeamsChannel([CallerFilePath] string callerPath = "", [Calle // The result comes back as a tuple, which is used to set the two properties (if present). result = await TeamsInfo.SendMessageToTeamsChannelAsync(dc.Context, activity, teamsChannelId, appId, cancellationToken: cancellationToken).ConfigureAwait(false); } + else + { + throw new InvalidOperationException($"The adapter does not support {nameof(SendMessageToTeamsChannel)}."); + } if (ConversationReferenceProperty != null) {