diff --git a/Migration/MigrationV3V4/CSharp/ContosoHelpdeskChatBot-V3/ContosoHelpdeskChatBot/packages.config b/Migration/MigrationV3V4/CSharp/ContosoHelpdeskChatBot-V3/ContosoHelpdeskChatBot/packages.config index 2ab2d7e460..3017b6769b 100644 --- a/Migration/MigrationV3V4/CSharp/ContosoHelpdeskChatBot-V3/ContosoHelpdeskChatBot/packages.config +++ b/Migration/MigrationV3V4/CSharp/ContosoHelpdeskChatBot-V3/ContosoHelpdeskChatBot/packages.config @@ -1,4 +1,4 @@ - + @@ -22,7 +22,7 @@ - + diff --git a/README.md b/README.md index fb3122d682..b1361c685c 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Samples are designed to illustrate functionality you'll need to implement to bui |18|OAuth authentication | Bot that demonstrates how to integrate OAuth providers. |[.NET Core][cs#18]|[JavaScript][js#18]|[Python][py#18]|[Java][java#18] |24|MSGraph authentication | Demonstrates bot authentication capabilities of Azure Bot Service. Demonstrates utilizing the Microsoft Graph API to retrieve data about the user.|[.NET Core][cs#24] |[JavaScript][js#24] |[Python][py#24]|[Java][java#24] |46|Teams authentication | Demonstrates how to use authentication for a bot running in Microsoft Teams. | [.NET Core](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-teams-authentication/csharp) | [JavaScript](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-conversation-sso-quickstart/js) |[Python](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-teams-authentication/python)|[Java](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-teams-authentication/java) -|84|Certificate authentication | Demonstrates how to use Certificates to authenticate the bot | |[JavaScript][js#84] | | +|84|Certificate authentication | Demonstrates how to use Certificates to authenticate the bot | [.NET Core][cs#84] |[JavaScript][js#84] | | |85|Subject name/issuer authentication | Demonstrates how to use the subject name/issuer authentication in a bot | [.NET Core][cs#85] | | | ### Custom question answering samples @@ -142,6 +142,7 @@ A [collection of **experimental** samples](./experimental) exist, intended to pr [cs#80]:samples/csharp_dotnetcore/80.skills-simple-bot-to-bot [cs#81]:samples/csharp_dotnetcore/81.skills-skilldialog [cs#82]:samples/csharp_dotnetcore/82.skills-sso-cloudadapter +[cs#84]:samples/csharp_dotnetcore/84.bot-authentication-certificate [cs#85]:samples/csharp_dotnetcore/85.bot-authentication-sni [wa#13]:samples/csharp_webapi/13.core-bot diff --git a/samples/csharp_dotnetcore/01.console-echo/Console-EchoBot.csproj b/samples/csharp_dotnetcore/01.console-echo/Console-EchoBot.csproj index 1cf497cf1e..082d8201b8 100644 --- a/samples/csharp_dotnetcore/01.console-echo/Console-EchoBot.csproj +++ b/samples/csharp_dotnetcore/01.console-echo/Console-EchoBot.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/02.echo-bot/EchoBot.csproj b/samples/csharp_dotnetcore/02.echo-bot/EchoBot.csproj index 307c158c6e..a83c896e67 100644 --- a/samples/csharp_dotnetcore/02.echo-bot/EchoBot.csproj +++ b/samples/csharp_dotnetcore/02.echo-bot/EchoBot.csproj @@ -7,7 +7,7 @@ - + diff --git a/samples/csharp_dotnetcore/03.welcome-user/WelcomeUser.csproj b/samples/csharp_dotnetcore/03.welcome-user/WelcomeUser.csproj index 87a5e80f90..a8bb2c4dc2 100644 --- a/samples/csharp_dotnetcore/03.welcome-user/WelcomeUser.csproj +++ b/samples/csharp_dotnetcore/03.welcome-user/WelcomeUser.csproj @@ -6,7 +6,7 @@ - + diff --git a/samples/csharp_dotnetcore/05.multi-turn-prompt/MultiTurnPromptBot.csproj b/samples/csharp_dotnetcore/05.multi-turn-prompt/MultiTurnPromptBot.csproj index 8483810863..af1501f572 100644 --- a/samples/csharp_dotnetcore/05.multi-turn-prompt/MultiTurnPromptBot.csproj +++ b/samples/csharp_dotnetcore/05.multi-turn-prompt/MultiTurnPromptBot.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/06.using-cards/CardsBot.csproj b/samples/csharp_dotnetcore/06.using-cards/CardsBot.csproj index 8483810863..af1501f572 100644 --- a/samples/csharp_dotnetcore/06.using-cards/CardsBot.csproj +++ b/samples/csharp_dotnetcore/06.using-cards/CardsBot.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/07.using-adaptive-cards/AdaptiveCardsBot.csproj b/samples/csharp_dotnetcore/07.using-adaptive-cards/AdaptiveCardsBot.csproj index ba7e3bfd4f..280242df6b 100644 --- a/samples/csharp_dotnetcore/07.using-adaptive-cards/AdaptiveCardsBot.csproj +++ b/samples/csharp_dotnetcore/07.using-adaptive-cards/AdaptiveCardsBot.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/08.suggested-actions/SuggestedActionsBot.csproj b/samples/csharp_dotnetcore/08.suggested-actions/SuggestedActionsBot.csproj index 559fe30cf5..8f9a881e83 100644 --- a/samples/csharp_dotnetcore/08.suggested-actions/SuggestedActionsBot.csproj +++ b/samples/csharp_dotnetcore/08.suggested-actions/SuggestedActionsBot.csproj @@ -7,7 +7,7 @@ - + diff --git a/samples/csharp_dotnetcore/12.customQABot/CustomQABot.csproj b/samples/csharp_dotnetcore/12.customQABot/CustomQABot.csproj index 31782c0a76..607e97546d 100644 --- a/samples/csharp_dotnetcore/12.customQABot/CustomQABot.csproj +++ b/samples/csharp_dotnetcore/12.customQABot/CustomQABot.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/13.core-bot.tests/CoreBot.Tests.csproj b/samples/csharp_dotnetcore/13.core-bot.tests/CoreBot.Tests.csproj index 979bbe6868..fc1ce8e00d 100644 --- a/samples/csharp_dotnetcore/13.core-bot.tests/CoreBot.Tests.csproj +++ b/samples/csharp_dotnetcore/13.core-bot.tests/CoreBot.Tests.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/13.core-bot/CoreBot.csproj b/samples/csharp_dotnetcore/13.core-bot/CoreBot.csproj index 52b198231a..a4dae84710 100644 --- a/samples/csharp_dotnetcore/13.core-bot/CoreBot.csproj +++ b/samples/csharp_dotnetcore/13.core-bot/CoreBot.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/samples/csharp_dotnetcore/15.handling-attachments/HandlingAttachmentsBot.csproj b/samples/csharp_dotnetcore/15.handling-attachments/HandlingAttachmentsBot.csproj index c7d6e054a8..fb90ee47af 100644 --- a/samples/csharp_dotnetcore/15.handling-attachments/HandlingAttachmentsBot.csproj +++ b/samples/csharp_dotnetcore/15.handling-attachments/HandlingAttachmentsBot.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/16.proactive-messages/ProactiveBot.csproj b/samples/csharp_dotnetcore/16.proactive-messages/ProactiveBot.csproj index 559fe30cf5..8f9a881e83 100644 --- a/samples/csharp_dotnetcore/16.proactive-messages/ProactiveBot.csproj +++ b/samples/csharp_dotnetcore/16.proactive-messages/ProactiveBot.csproj @@ -7,7 +7,7 @@ - + diff --git a/samples/csharp_dotnetcore/17.multilingual-bot/MultiLingualBot.csproj b/samples/csharp_dotnetcore/17.multilingual-bot/MultiLingualBot.csproj index 8516e8de1a..32baeba129 100644 --- a/samples/csharp_dotnetcore/17.multilingual-bot/MultiLingualBot.csproj +++ b/samples/csharp_dotnetcore/17.multilingual-bot/MultiLingualBot.csproj @@ -8,7 +8,7 @@ - + diff --git a/samples/csharp_dotnetcore/18.bot-authentication/AuthenticationBot.csproj b/samples/csharp_dotnetcore/18.bot-authentication/AuthenticationBot.csproj index 8483810863..af1501f572 100644 --- a/samples/csharp_dotnetcore/18.bot-authentication/AuthenticationBot.csproj +++ b/samples/csharp_dotnetcore/18.bot-authentication/AuthenticationBot.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/19.custom-dialogs/Custom-Dialogs.csproj b/samples/csharp_dotnetcore/19.custom-dialogs/Custom-Dialogs.csproj index 8483810863..af1501f572 100644 --- a/samples/csharp_dotnetcore/19.custom-dialogs/Custom-Dialogs.csproj +++ b/samples/csharp_dotnetcore/19.custom-dialogs/Custom-Dialogs.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/21.corebot-app-insights/CoreBot-App-Insights.csproj b/samples/csharp_dotnetcore/21.corebot-app-insights/CoreBot-App-Insights.csproj index c7af562fe0..32045a3d20 100644 --- a/samples/csharp_dotnetcore/21.corebot-app-insights/CoreBot-App-Insights.csproj +++ b/samples/csharp_dotnetcore/21.corebot-app-insights/CoreBot-App-Insights.csproj @@ -15,11 +15,11 @@ - - - - - + + + + + diff --git a/samples/csharp_dotnetcore/23.facebook-events/Facebook-Events-Bot.csproj b/samples/csharp_dotnetcore/23.facebook-events/Facebook-Events-Bot.csproj index 0874689b11..a8a7d1fdc3 100644 --- a/samples/csharp_dotnetcore/23.facebook-events/Facebook-Events-Bot.csproj +++ b/samples/csharp_dotnetcore/23.facebook-events/Facebook-Events-Bot.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/24.bot-authentication-msgraph/BotAuthenticationMSGraph.csproj b/samples/csharp_dotnetcore/24.bot-authentication-msgraph/BotAuthenticationMSGraph.csproj index 221e186043..032be2929a 100644 --- a/samples/csharp_dotnetcore/24.bot-authentication-msgraph/BotAuthenticationMSGraph.csproj +++ b/samples/csharp_dotnetcore/24.bot-authentication-msgraph/BotAuthenticationMSGraph.csproj @@ -8,8 +8,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/40.timex-resolution/Timex-Resolution.csproj b/samples/csharp_dotnetcore/40.timex-resolution/Timex-Resolution.csproj index 73cea730ae..8783a4dd92 100644 --- a/samples/csharp_dotnetcore/40.timex-resolution/Timex-Resolution.csproj +++ b/samples/csharp_dotnetcore/40.timex-resolution/Timex-Resolution.csproj @@ -15,7 +15,7 @@ - + diff --git a/samples/csharp_dotnetcore/42.scaleout/ScaleoutBot.csproj b/samples/csharp_dotnetcore/42.scaleout/ScaleoutBot.csproj index 3ba2e18a3d..98f8acb33c 100644 --- a/samples/csharp_dotnetcore/42.scaleout/ScaleoutBot.csproj +++ b/samples/csharp_dotnetcore/42.scaleout/ScaleoutBot.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/43.complex-dialog/ComplexDialogBot.csproj b/samples/csharp_dotnetcore/43.complex-dialog/ComplexDialogBot.csproj index 7a53f3c744..5ff1ef6ed8 100644 --- a/samples/csharp_dotnetcore/43.complex-dialog/ComplexDialogBot.csproj +++ b/samples/csharp_dotnetcore/43.complex-dialog/ComplexDialogBot.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/44.prompt-users-for-input/PromptUsersForInput.csproj b/samples/csharp_dotnetcore/44.prompt-users-for-input/PromptUsersForInput.csproj index 49548a1ce7..d590781e50 100644 --- a/samples/csharp_dotnetcore/44.prompt-users-for-input/PromptUsersForInput.csproj +++ b/samples/csharp_dotnetcore/44.prompt-users-for-input/PromptUsersForInput.csproj @@ -8,7 +8,7 @@ - + diff --git a/samples/csharp_dotnetcore/45.state-management/Startup.cs b/samples/csharp_dotnetcore/45.state-management/Startup.cs index 7104d8887c..6d31abe4ba 100644 --- a/samples/csharp_dotnetcore/45.state-management/Startup.cs +++ b/samples/csharp_dotnetcore/45.state-management/Startup.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Bot.Builder; -using Microsoft.Bot.Builder.Azure.Blobs; using Microsoft.Bot.Builder.Integration.AspNet.Core; using Microsoft.Bot.Connector.Authentication; using Microsoft.Extensions.DependencyInjection; @@ -28,15 +27,36 @@ public void ConfigureServices(IServiceCollection services) // Create the Bot Adapter with error handling enabled. services.AddSingleton(); + /* JSON SERIALIZER - Uncomment the code in this section to use a JsonSerializer with a custom SerializationBinder configuration. */ + // Note: the AllowedTypesSerializationBinder limits the objects the storage is able to read and write, by providing a list of types used to allow or deny. It can be used to increase security. + + // var jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings + // { + // TypeNameHandling = TypeNameHandling.All, + // MaxDepth = null, + // SerializationBinder = new AllowedTypesSerializationBinder( + // new List + // { + // typeof(Dictionary), + // typeof(ConversationData), + // typeof(UserProfile) + // }) + // }); + + /* JSON SERIALIZER - Uncomment the code in this section to use a JsonSerializer with a custom SerializationBinder configuration. */ + // Create the storage we'll be using for User and Conversation state. // (Memory is great for testing purposes - examples of implementing storage with // Azure Blob Storage or Cosmos DB are below). var storage = new MemoryStorage(); /* AZURE BLOB STORAGE - Uncomment the code in this section to use Azure blob storage */ - + // var storage = new BlobsStorage("", "bot-state"); + // With a custom JSON SERIALIZER, use this instead. + // var storage = new BlobsStorage("", "bot-state", jsonSerializer); + /* END AZURE BLOB STORAGE */ /* COSMOSDB STORAGE - Uncomment the code in this section to use CosmosDB storage */ @@ -48,8 +68,12 @@ public void ConfigureServices(IServiceCollection services) // DatabaseId = "", // ContainerId = "" // }; + // var storage = new CosmosDbPartitionedStorage(cosmosDbStorageOptions); + // With a custom JSON SERIALIZER, use this instead. + // var storage = new CosmosDbPartitionedStorage(cosmosDbStorageOptions, jsonSerializer); + /* END COSMOSDB STORAGE */ // Create the User state passing in the storage layer. diff --git a/samples/csharp_dotnetcore/45.state-management/StateMangementBot.csproj b/samples/csharp_dotnetcore/45.state-management/StateMangementBot.csproj index 88ae08cf55..bcf858e9c6 100644 --- a/samples/csharp_dotnetcore/45.state-management/StateMangementBot.csproj +++ b/samples/csharp_dotnetcore/45.state-management/StateMangementBot.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/samples/csharp_dotnetcore/47.inspection/Inspection.csproj b/samples/csharp_dotnetcore/47.inspection/Inspection.csproj index 307c158c6e..a83c896e67 100644 --- a/samples/csharp_dotnetcore/47.inspection/Inspection.csproj +++ b/samples/csharp_dotnetcore/47.inspection/Inspection.csproj @@ -7,7 +7,7 @@ - + diff --git a/samples/csharp_dotnetcore/48.customQABot-all-features/CustomQABotAllFeatures.csproj b/samples/csharp_dotnetcore/48.customQABot-all-features/CustomQABotAllFeatures.csproj index 4b3fdd288e..f9337e30ee 100644 --- a/samples/csharp_dotnetcore/48.customQABot-all-features/CustomQABotAllFeatures.csproj +++ b/samples/csharp_dotnetcore/48.customQABot-all-features/CustomQABotAllFeatures.csproj @@ -7,9 +7,9 @@ - - - + + + diff --git a/samples/csharp_dotnetcore/80.skills-simple-bot-to-bot/EchoSkillBot/EchoSkillBot.csproj b/samples/csharp_dotnetcore/80.skills-simple-bot-to-bot/EchoSkillBot/EchoSkillBot.csproj index 41ad9c859f..9ecb32563d 100644 --- a/samples/csharp_dotnetcore/80.skills-simple-bot-to-bot/EchoSkillBot/EchoSkillBot.csproj +++ b/samples/csharp_dotnetcore/80.skills-simple-bot-to-bot/EchoSkillBot/EchoSkillBot.csproj @@ -9,7 +9,7 @@ - + diff --git a/samples/csharp_dotnetcore/80.skills-simple-bot-to-bot/SimpleRootBot/SimpleRootBot.csproj b/samples/csharp_dotnetcore/80.skills-simple-bot-to-bot/SimpleRootBot/SimpleRootBot.csproj index bdca1314da..26476b0dff 100644 --- a/samples/csharp_dotnetcore/80.skills-simple-bot-to-bot/SimpleRootBot/SimpleRootBot.csproj +++ b/samples/csharp_dotnetcore/80.skills-simple-bot-to-bot/SimpleRootBot/SimpleRootBot.csproj @@ -9,7 +9,7 @@ - + diff --git a/samples/csharp_dotnetcore/81.skills-skilldialog/DialogRootBot/DialogRootBot.csproj b/samples/csharp_dotnetcore/81.skills-skilldialog/DialogRootBot/DialogRootBot.csproj index 9a8b351149..2fbd27a329 100644 --- a/samples/csharp_dotnetcore/81.skills-skilldialog/DialogRootBot/DialogRootBot.csproj +++ b/samples/csharp_dotnetcore/81.skills-skilldialog/DialogRootBot/DialogRootBot.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/81.skills-skilldialog/DialogSkillBot/DialogSkillBot.csproj b/samples/csharp_dotnetcore/81.skills-skilldialog/DialogSkillBot/DialogSkillBot.csproj index 60a8eb2e89..1a15748557 100644 --- a/samples/csharp_dotnetcore/81.skills-skilldialog/DialogSkillBot/DialogSkillBot.csproj +++ b/samples/csharp_dotnetcore/81.skills-skilldialog/DialogSkillBot/DialogSkillBot.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/samples/csharp_dotnetcore/82.skills-sso-cloudadapter/RootBot/RootBot.csproj b/samples/csharp_dotnetcore/82.skills-sso-cloudadapter/RootBot/RootBot.csproj index e1666a3bab..fbf3d7a859 100644 --- a/samples/csharp_dotnetcore/82.skills-sso-cloudadapter/RootBot/RootBot.csproj +++ b/samples/csharp_dotnetcore/82.skills-sso-cloudadapter/RootBot/RootBot.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/82.skills-sso-cloudadapter/SkillBot/SkillBot.csproj b/samples/csharp_dotnetcore/82.skills-sso-cloudadapter/SkillBot/SkillBot.csproj index 5294f560a8..3eda373e72 100644 --- a/samples/csharp_dotnetcore/82.skills-sso-cloudadapter/SkillBot/SkillBot.csproj +++ b/samples/csharp_dotnetcore/82.skills-sso-cloudadapter/SkillBot/SkillBot.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/AdapterWithErrorHandler.cs b/samples/csharp_dotnetcore/84.bot-authentication-certificate/AdapterWithErrorHandler.cs new file mode 100644 index 0000000000..6761e30a1d --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/AdapterWithErrorHandler.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Integration.AspNet.Core; +using Microsoft.Bot.Builder.TraceExtensions; +using Microsoft.Bot.Connector.Authentication; +using Microsoft.Extensions.Logging; + +namespace Microsoft.BotBuilderSamples +{ + public class AdapterWithErrorHandler : CloudAdapter + { + public AdapterWithErrorHandler(BotFrameworkAuthentication auth, ILogger logger, ConversationState conversationState = default) + : base(auth, logger) + { + OnTurnError = async (turnContext, exception) => + { + // Log any leaked exception from the application. + // NOTE: In production environment, you should consider logging this to + // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how + // to add telemetry capture to your bot. + logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}"); + + // Send a message to the user + await turnContext.SendActivityAsync("The bot encountered an error or bug."); + await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code."); + + if (conversationState != null) + { + try + { + // Delete the conversationState for the current conversation to prevent the + // bot from getting stuck in a error-loop caused by being in a bad state. + // ConversationState should be thought of as similar to "cookie-state" in a Web pages. + await conversationState.DeleteAsync(turnContext); + } + catch (Exception e) + { + logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}"); + } + } + + // Send a trace activity, which will be displayed in the Bot Framework Emulator + await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError"); + }; + } + } +} diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/AuthCertificateBot.csproj b/samples/csharp_dotnetcore/84.bot-authentication-certificate/AuthCertificateBot.csproj new file mode 100644 index 0000000000..b1cd454f0c --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/AuthCertificateBot.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + latest + + + + + + + + + + + + + Always + + + diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Bots/AuthCertificateBot.cs b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Bots/AuthCertificateBot.cs new file mode 100644 index 0000000000..ac8174c883 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Bots/AuthCertificateBot.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Schema; + +namespace Microsoft.BotBuilderSamples +{ + public class AuthCertificateBot : ActivityHandler + { + protected override async Task OnMembersAddedAsync(IList membersAdded, ITurnContext turnContext, CancellationToken cancellationToken) + { + foreach (var member in turnContext.Activity.MembersAdded) + { + if (member.Id != turnContext.Activity.Recipient.Id) + { + await turnContext.SendActivityAsync(MessageFactory.Text("Welcome to Authentication Bot with SSL/TLS Certificate."), cancellationToken); + } + } + } + + protected override async Task OnMessageActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken) + { + var replyText = "Running dialog with bot authenticated"; + await turnContext.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken); + } + } +} diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Bots/DialogBot.cs b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Bots/DialogBot.cs new file mode 100644 index 0000000000..5136835d99 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Bots/DialogBot.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Dialogs; +using Microsoft.Bot.Schema; +using Microsoft.Extensions.Logging; + +namespace Microsoft.BotBuilderSamples +{ + // This IBot implementation can run any type of Dialog. The use of type parameterization is to allows multiple different bots + // to be run at different endpoints within the same project. This can be achieved by defining distinct Controller types + // each with dependency on distinct IBot types, this way ASP Dependency Injection can glue everything together without ambiguity. + // The ConversationState is used by the Dialog system. The UserState isn't, however, it might have been used in a Dialog implementation, + // and the requirement is that all BotState objects are saved at the end of a turn. + public class DialogBot : ActivityHandler where T : Dialog + { + protected readonly BotState ConversationState; + protected readonly Dialog Dialog; + protected readonly ILogger Logger; + protected readonly BotState UserState; + + public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger> logger) + { + ConversationState = conversationState; + UserState = userState; + Dialog = dialog; + Logger = logger; + } + + public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken)) + { + await base.OnTurnAsync(turnContext, cancellationToken); + + // Save any state changes that might have occurred during the turn. + await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken); + await UserState.SaveChangesAsync(turnContext, false, cancellationToken); + } + + protected override async Task OnMessageActivityAsync(ITurnContext turnContext, CancellationToken cancellationToken) + { + Logger.LogInformation("Running dialog with Message Activity."); + + // Run the Dialog with the new message Activity. + await Dialog.RunAsync(turnContext, ConversationState.CreateProperty(nameof(DialogState)), cancellationToken); + } + } +} diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Controllers/BotController.cs b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Controllers/BotController.cs new file mode 100644 index 0000000000..fa4ea81324 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Controllers/BotController.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Integration.AspNet.Core; + +namespace Microsoft.BotBuilderSamples +{ + // This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot + // implementation at runtime. Multiple different IBot implementations running at different endpoints can be + // achieved by specifying a more specific type for the bot constructor argument. + [Route("api/messages")] + [ApiController] + public class BotController : ControllerBase + { + private readonly IBotFrameworkHttpAdapter _adapter; + private readonly IBot _bot; + + public BotController(IBotFrameworkHttpAdapter adapter, IBot bot) + { + _adapter = adapter; + _bot = bot; + } + + [HttpPost] + public async Task PostAsync() + { + // Delegate the processing of the HTTP POST to the adapter. + // The adapter will invoke the bot. + await _adapter.ProcessAsync(Request, Response, _bot); + } + } +} diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-AzureBot-with-rg.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-AzureBot-with-rg.json new file mode 100644 index 0000000000..c2c03ef307 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-AzureBot-with-rg.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "azureBotId": { + "value": "" + }, + "azureBotSku": { + "value": "S1" + }, + "azureBotRegion": { + "value": "global" + }, + "botEndpoint": { + "value": "" + }, + "appType": { + "value": "MultiTenant" + }, + "appId": { + "value": "" + }, + "UMSIName": { + "value": "" + }, + "UMSIResourceGroupName": { + "value": "" + }, + "tenantId": { + "value": "" + } + } +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-BotApp-with-rg.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-BotApp-with-rg.json new file mode 100644 index 0000000000..c4b2909008 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/parameters-for-template-BotApp-with-rg.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "appServiceName": { + "value": "" + }, + "existingAppServicePlanName": { + "value": "" + }, + "existingAppServicePlanLocation": { + "value": "" + }, + "newAppServicePlanName": { + "value": "" + }, + "newAppServicePlanLocation": { + "value": "" + }, + "newAppServicePlanSku": { + "value": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": 1 + } + }, + "appType": { + "value": "MultiTenant" + }, + "appId": { + "value": "" + }, + "appSecret": { + "value": "" + }, + "UMSIName": { + "value": "" + }, + "UMSIResourceGroupName": { + "value": "" + }, + "tenantId": { + "value": "" + } + } +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/readme.md b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/readme.md new file mode 100644 index 0000000000..628f0a9546 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/readme.md @@ -0,0 +1,48 @@ +# Usage +The BotApp must be deployed prior to AzureBot. + +Command line: +- az login +- az deployment group create --resource-group --template-file --parameters @ + +# parameters-for-template-BotApp-with-rg: + +- **appServiceName**:(required) The Name of the Bot App Service. + +- (choose an existingAppServicePlan or create a new AppServicePlan) + - **existingAppServicePlanName**: The name of the App Service Plan. + - **existingAppServicePlanLocation**: The location of the App Service Plan. + - **newAppServicePlanName**: The name of the App Service Plan. + - **newAppServicePlanLocation**: The location of the App Service Plan. + - **newAppServicePlanSku**: The SKU of the App Service Plan. Defaults to Standard values. + +- **appType**: Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. **Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI.** + +- **appId**:(required) Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings. + +- **appSecret**:(required for MultiTenant and SingleTenant) Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. + +- **UMSIName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource used for the Bot's Authentication. + +- **UMSIResourceGroupName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. + +- **tenantId**: The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to . + +MoreInfo: https://docs.microsoft.com/en-us/azure/bot-service/tutorial-provision-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Cnewgroup#create-an-identity-resource + + + +# parameters-for-template-AzureBot-with-rg: + +- **azureBotId**:(required) The globally unique and immutable bot ID. +- **azureBotSku**: The pricing tier of the Bot Service Registration. **Allowed values are: F0, S1(default)**. +- **azureBotRegion**: Specifies the location of the new AzureBot. **Allowed values are: global(default), westeurope**. +- **botEndpoint**: Use to handle client messages, Such as https://.azurewebsites.net/api/messages. + +- **appType**: Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. **Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI.** +- **appId**:(required) Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings. +- **UMSIName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource used for the Bot's Authentication. +- **UMSIResourceGroupName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. +- **tenantId**: The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to . + +MoreInfo: https://docs.microsoft.com/en-us/azure/bot-service/tutorial-provision-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Cnewgroup#create-an-identity-resource \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/template-AzureBot-with-rg.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/template-AzureBot-with-rg.json new file mode 100644 index 0000000000..a8a960066f --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/template-AzureBot-with-rg.json @@ -0,0 +1,121 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "azureBotId": { + "type": "string", + "metadata": { + "description": "The globally unique and immutable bot ID." + } + }, + "azureBotSku": { + "type": "string", + "defaultValue": "S1", + "metadata": { + "description": "The pricing tier of the Bot Service Registration. Allowed values are: F0, S1(default)." + } + }, + "azureBotRegion": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Specifies the location of the new AzureBot. Allowed values are: global(default), westeurope." + } + }, + "botEndpoint": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Use to handle client messages, Such as https://.azurewebsites.net/api/messages." + } + }, + "appType": { + "type": "string", + "defaultValue": "MultiTenant", + "allowedValues": [ + "MultiTenant", + "SingleTenant", + "UserAssignedMSI" + ], + "metadata": { + "description": "Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. Allowed values are: MultiTenant, SingleTenant, UserAssignedMSI. Defaults to \"MultiTenant\"." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "UMSIName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource used for the Bot's Authentication." + } + }, + "UMSIResourceGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource Group used for the Bot's Authentication." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to \"Subscription Tenant ID\"." + } + } + }, + "variables": { + "botEndpoint": "[if(empty(parameters('botEndpoint')), concat('https://', parameters('azureBotId'), '.azurewebsites.net/api/messages'), parameters('botEndpoint'))]", + "tenantId": "[if(empty(parameters('tenantId')), subscription().tenantId, parameters('tenantId'))]", + "msiResourceId": "[if(empty(parameters('UMSIName')), '', concat(subscription().id, '/resourceGroups/', parameters('UMSIResourceGroupName'), '/providers/', 'Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('UMSIName')))]", + "appTypeDef": { + "MultiTenant": { + "tenantId": "", + "msiResourceId": "" + }, + "SingleTenant": { + "tenantId": "[variables('tenantId')]", + "msiResourceId": "" + }, + "UserAssignedMSI": { + "tenantId": "[variables('tenantId')]", + "msiResourceId": "[variables('msiResourceId')]" + } + }, + "appType": { + "tenantId": "[variables('appTypeDef')[parameters('appType')].tenantId]", + "msiResourceId": "[variables('appTypeDef')[parameters('appType')].msiResourceId]" + } + }, + "resources": [ + { + "apiVersion": "2021-05-01-preview", + "type": "Microsoft.BotService/botServices", + "name": "[parameters('azureBotId')]", + "location": "[parameters('azureBotRegion')]", + "kind": "azurebot", + "sku": { + "name": "[parameters('azureBotSku')]" + }, + "properties": { + "displayName": "[parameters('azureBotId')]", + "iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png", + "endpoint": "[variables('botEndpoint')]", + "msaAppId": "[parameters('appId')]", + "msaAppTenantId": "[variables('appType').tenantId]", + "msaAppMSIResourceId": "[variables('appType').msiResourceId]", + "msaAppType": "[parameters('appType')]", + "luisAppIds": [], + "schemaTransformationVersion": "1.3", + "isCmekEnabled": false, + "isIsolated": false + }, + "dependsOn": [] + } + ] +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/template-BotApp-with-rg.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/template-BotApp-with-rg.json new file mode 100644 index 0000000000..ce3bb6322a --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployUseExistResourceGroup/template-BotApp-with-rg.json @@ -0,0 +1,191 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "appServiceName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The globally unique name of the Web App." + } + }, + "existingAppServicePlanName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Name of the existing App Service Plan used to create the Web App for the bot." + } + }, + "existingAppServicePlanLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The location of the App Service Plan." + } + }, + "newAppServicePlanName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The name of the new App Service Plan." + } + }, + "newAppServicePlanLocation": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The location of the App Service Plan." + } + }, + "newAppServicePlanSku": { + "type": "object", + "defaultValue": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": 1 + }, + "metadata": { + "description": "The SKU of the App Service Plan. Defaults to Standard values." + } + }, + "appType": { + "type": "string", + "defaultValue": "MultiTenant", + "allowedValues": [ + "MultiTenant", + "SingleTenant", + "UserAssignedMSI" + ], + "metadata": { + "description": "Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. Allowed values are: MultiTenant, SingleTenant, UserAssignedMSI. Defaults to \"MultiTenant\"." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "appSecret": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Required for MultiTenant and SingleTenant app types. Defaults to \"\"." + } + }, + "UMSIName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource used for the Bot's Authentication. Defaults to \"\"." + } + }, + "UMSIResourceGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. Defaults to \"\"." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to \"Subscription Tenant ID\"." + } + } + }, + "variables": { + "tenantId": "[if(empty(parameters('tenantId')), subscription().tenantId, parameters('tenantId'))]", + "useExistingServicePlan": "[not(empty(parameters('existingAppServicePlanName')))]", + "servicePlanName": "[if(variables('useExistingServicePlan'), parameters('existingAppServicePlanName'), parameters('newAppServicePlanName'))]", + "servicePlanLocation": "[if(variables('useExistingServicePlan'), parameters('existingAppServicePlanLocation'), parameters('newAppServicePlanLocation'))]", + "msiResourceId": "[if(empty(parameters('UMSIName')), '', concat(subscription().id, '/resourceGroups/', parameters('UMSIResourceGroupName'), '/providers/', 'Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('UMSIName')))]", + "appTypeDef": { + "MultiTenant": { + "tenantId": "", + "identity": { "type": "None" } + }, + "SingleTenant": { + "tenantId": "[variables('tenantId')]", + "identity": { "type": "None" } + }, + "UserAssignedMSI": { + "tenantId": "[variables('tenantId')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[variables('msiResourceId')]": {} + } + } + } + }, + "appType": { + "tenantId": "[variables('appTypeDef')[parameters('appType')].tenantId]", + "identity": "[variables('appTypeDef')[parameters('appType')].identity]" + } + }, + "resources": [ + { + "comments": "Create a new App Service Plan if no existing App Service Plan name was passed in.", + "type": "Microsoft.Web/serverfarms", + "condition": "[not(variables('useExistingServicePlan'))]", + "name": "[variables('servicePlanName')]", + "apiVersion": "2018-02-01", + "location": "[parameters('newAppServicePlanLocation')]", + "sku": "[parameters('newAppServicePlanSku')]", + "properties": { + "name": "[variables('servicePlanName')]" + } + }, + { + "comments": "Create a Web App using an App Service Plan", + "type": "Microsoft.Web/sites", + "apiVersion": "2015-08-01", + "location": "[variables('servicePlanLocation')]", + "kind": "app", + "dependsOn": [ + "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]" + ], + "name": "[parameters('appServiceName')]", + "identity": "[variables('appType').identity]", + "properties": { + "name": "[parameters('appServiceName')]", + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('servicePlanName'))]", + "siteConfig": { + "appSettings": [ + { + "name": "WEBSITE_NODE_DEFAULT_VERSION", + "value": "10.14.1" + }, + { + "name": "MicrosoftAppType", + "value": "[parameters('appType')]" + }, + { + "name": "MicrosoftAppId", + "value": "[parameters('appId')]" + }, + { + "name": "MicrosoftAppPassword", + "value": "[parameters('appSecret')]" + }, + { + "name": "MicrosoftAppTenantId", + "value": "[variables('appType').tenantId]" + } + ], + "cors": { + "allowedOrigins": [ + "https://botservice.hosting.portal.azure.net", + "https://hosting.onecloud.azure-test.net/" + ] + }, + "webSocketsEnabled": true + } + } + } + ] +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-AzureBot-new-rg.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-AzureBot-new-rg.json new file mode 100644 index 0000000000..44f169e4d5 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-AzureBot-new-rg.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupName": { + "value": "" + }, + "groupLocation": { + "value": "" + }, + "azureBotId": { + "value": "" + }, + "azureBotSku": { + "value": "S1" + }, + "azureBotRegion": { + "value": "global" + }, + "botEndpoint": { + "value": "" + }, + "appType": { + "value": "MultiTenant" + }, + "appId": { + "value": "" + }, + "UMSIName": { + "value": "" + }, + "UMSIResourceGroupName": { + "value": "" + }, + "tenantId": { + "value": "" + } + } +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-BotApp-new-rg.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-BotApp-new-rg.json new file mode 100644 index 0000000000..8abb03d597 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/parameters-for-template-BotApp-new-rg.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupName": { + "value": "" + }, + "groupLocation": { + "value": "" + }, + "appServiceName": { + "value": "" + }, + "appServicePlanName": { + "value": "" + }, + "appServicePlanLocation": { + "value": "" + }, + "appServicePlanSku": { + "value": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": 1 + } + }, + "appType": { + "value": "MultiTenant" + }, + "appId": { + "value": "" + }, + "appSecret": { + "value": "" + }, + "UMSIName": { + "value": "" + }, + "UMSIResourceGroupName": { + "value": "" + }, + "tenantId": { + "value": "" + } + } +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/readme.md b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/readme.md new file mode 100644 index 0000000000..23bf7a5a51 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/readme.md @@ -0,0 +1,45 @@ +# Usage +The BotApp must be deployed prior to AzureBot. + +Command line: +- az login +- az deployment sub create --template-file --location --parameters @ + +# parameters-for-template-BotApp-new-rg: + +- **groupName**:(required) Specifies the name of the new Resource Group. +- **groupLocation**:(required) Specifies the location of the new Resource Group. + +- **appServiceName**:(required) The location of the App Service Plan. +- **appServicePlanName**:(required) The name of the App Service Plan. +- **appServicePlanLocation**: The location of the App Service Plan. Defaults to use groupLocation. +- **appServicePlanSku**: The SKU of the App Service Plan. Defaults to Standard values. + +- **appType**: Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. **Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI.** +- **appId**:(required) Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings. +- **appSecret**:(required for MultiTenant and SingleTenant) Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. +- **UMSIName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource used for the Bot's Authentication. +- **UMSIResourceGroupName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. +- **tenantId**: The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to . + +MoreInfo: https://docs.microsoft.com/en-us/azure/bot-service/tutorial-provision-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Cnewgroup#create-an-identity-resource + + + +# parameters-for-template-AzureBot-new-rg: + +- **groupName**:(required) Specifies the name of the new Resource Group. +- **groupLocation**:(required) Specifies the location of the new Resource Group. + +- **azureBotId**:(required) The globally unique and immutable bot ID. Also used to configure the displayName of the bot, which is mutable. +- **azureBotSku**: The pricing tier of the Bot Service Registration. **Allowed values are: F0, S1(default)**. +- **azureBotRegion**: Specifies the location of the new AzureBot. **Allowed values are: global(default), westeurope**. +- **botEndpoint**: Use to handle client messages, Such as https://.azurewebsites.net/api/messages. + +- **appType**: Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. **Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI.** +- **appId**:(required) Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings. +- **UMSIName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource used for the Bot's Authentication. +- **UMSIResourceGroupName**:(required for UserAssignedMSI) The User-Assigned Managed Identity Resource Group used for the Bot's Authentication. +- **tenantId**: The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to . + +MoreInfo: https://docs.microsoft.com/en-us/azure/bot-service/tutorial-provision-a-bot?view=azure-bot-service-4.0&tabs=userassigned%2Cnewgroup#create-an-identity-resource \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/template-AzureBot-new-rg.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/template-AzureBot-new-rg.json new file mode 100644 index 0000000000..ae073b7939 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/template-AzureBot-new-rg.json @@ -0,0 +1,160 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupName": { + "type": "string", + "metadata": { + "description": "Specifies the name of the Resource Group." + } + }, + "groupLocation": { + "type": "string", + "metadata": { + "description": "Specifies the location of the Resource Group." + } + }, + "azureBotId": { + "type": "string", + "metadata": { + "description": "The globally unique and immutable bot ID." + } + }, + "azureBotSku": { + "type": "string", + "defaultValue": "S1", + "metadata": { + "description": "The pricing tier of the Bot Service Registration. Acceptable values are F0 and S1." + } + }, + "azureBotRegion": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "" + } + }, + "botEndpoint": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Use to handle client messages, Such as https://.azurewebsites.net/api/messages." + } + }, + "appType": { + "type": "string", + "defaultValue": "MultiTenant", + "allowedValues": [ + "MultiTenant", + "SingleTenant", + "UserAssignedMSI" + ], + "metadata": { + "description": "Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. Allowed values are: MultiTenant, SingleTenant, UserAssignedMSI. Defaults to \"MultiTenant\"." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to \"Subscription Tenant ID\"." + } + }, + "UMSIName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource used for the Bot's Authentication." + } + }, + "UMSIResourceGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource Group used for the Bot's Authentication." + } + } + }, + "variables": { + "botEndpoint": "[if(empty(parameters('botEndpoint')), concat('https://', parameters('azureBotId'), '.azurewebsites.net/api/messages'), parameters('botEndpoint'))]", + "tenantId": "[if(empty(parameters('tenantId')), subscription().tenantId, parameters('tenantId'))]", + "msiResourceId": "[if(empty(parameters('UMSIName')), '', concat(subscription().id, '/resourceGroups/', parameters('UMSIResourceGroupName'), '/providers/', 'Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('UMSIName')))]", + "appTypeDef": { + "MultiTenant": { + "tenantId": "", + "msiResourceId": "" + }, + "SingleTenant": { + "tenantId": "[variables('tenantId')]", + "msiResourceId": "" + }, + "UserAssignedMSI": { + "tenantId": "[variables('tenantId')]", + "msiResourceId": "[variables('msiResourceId')]" + } + }, + "appType": { + "tenantId": "[variables('appTypeDef')[parameters('appType')].tenantId]", + "msiResourceId": "[variables('appTypeDef')[parameters('appType')].msiResourceId]" + } + }, + "resources": [ + { + "name": "[parameters('groupName')]", + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2018-05-01", + "location": "[parameters('groupLocation')]", + "properties": {} + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2018-05-01", + "name": "storageDeployment", + "resourceGroup": "[parameters('groupName')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": {}, + "variables": {}, + "resources": [ + { + "apiVersion": "2021-03-01", + "type": "Microsoft.BotService/botServices", + "name": "[parameters('azureBotId')]", + "location": "[parameters('azureBotRegion')]", + "kind": "azurebot", + "sku": { + "name": "[parameters('azureBotSku')]" + }, + "properties": { + "name": "[parameters('azureBotId')]", + "displayName": "[parameters('azureBotId')]", + "iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png", + "endpoint": "[variables('botEndpoint')]", + "msaAppId": "[parameters('appId')]", + "msaAppTenantId": "[variables('appType').tenantId]", + "msaAppMSIResourceId": "[variables('appType').msiResourceId]", + "msaAppType": "[parameters('appType')]", + "luisAppIds": [], + "schemaTransformationVersion": "1.3", + "isCmekEnabled": false, + "isIsolated": false + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/template-BotApp-new-rg.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/template-BotApp-new-rg.json new file mode 100644 index 0000000000..560bbbc443 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/DeploymentTemplates/DeployWithNewResourceGroup/template-BotApp-new-rg.json @@ -0,0 +1,213 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "groupName": { + "type": "string", + "metadata": { + "description": "Specifies the name of the Resource Group." + } + }, + "groupLocation": { + "type": "string", + "metadata": { + "description": "Specifies the location of the Resource Group." + } + }, + "appServiceName": { + "type": "string", + "metadata": { + "description": "The globally unique name of the Web App." + } + }, + "appServicePlanName": { + "type": "string", + "metadata": { + "description": "The name of the App Service Plan." + } + }, + "appServicePlanLocation": { + "type": "string", + "metadata": { + "description": "The location of the App Service Plan." + } + }, + "appServicePlanSku": { + "type": "object", + "defaultValue": { + "name": "S1", + "tier": "Standard", + "size": "S1", + "family": "S", + "capacity": 1 + }, + "metadata": { + "description": "The SKU of the App Service Plan. Defaults to Standard values." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The Azure AD Tenant ID to use as part of the Bot's Authentication. Only used for SingleTenant and UserAssignedMSI app types. Defaults to \"Subscription Tenant ID\"." + } + }, + "appType": { + "type": "string", + "defaultValue": "MultiTenant", + "allowedValues": [ + "MultiTenant", + "SingleTenant", + "UserAssignedMSI" + ], + "metadata": { + "description": "Type of Bot Authentication. set as MicrosoftAppType in the Web App's Application Settings. Allowed values are: MultiTenant, SingleTenant, UserAssignedMSI. Defaults to \"MultiTenant\"." + } + }, + "appId": { + "type": "string", + "metadata": { + "description": "Active Directory App ID or User-Assigned Managed Identity Client ID, set as MicrosoftAppId in the Web App's Application Settings." + } + }, + "appSecret": { + "type": "string", + "metadata": { + "description": "Active Directory App Password, set as MicrosoftAppPassword in the Web App's Application Settings. Required for MultiTenant and SingleTenant app types." + } + }, + "UMSIName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource used for the Bot's Authentication." + } + }, + "UMSIResourceGroupName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The User-Assigned Managed Identity Resource Group used for the Bot's Authentication." + } + } + }, + "variables": { + "tenantId": "[if(empty(parameters('tenantId')), subscription().tenantId, parameters('tenantId'))]", + "appServicePlanName": "[parameters('appServicePlanName')]", + "resourcesLocation": "[if(empty(parameters('appServicePlanLocation')), parameters('groupLocation'), parameters('appServicePlanLocation'))]", + "appServiceName": "[parameters('appServiceName')]", + "resourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('groupName'))]", + "msiResourceId": "[if(empty(parameters('UMSIName')), '', concat(subscription().id, '/resourceGroups/', parameters('UMSIResourceGroupName'), '/providers/', 'Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('UMSIName')))]", + "appTypeDef": { + "MultiTenant": { + "tenantId": "", + "identity": { "type": "None" } + }, + "SingleTenant": { + "tenantId": "[variables('tenantId')]", + "identity": { "type": "None" } + }, + "UserAssignedMSI": { + "tenantId": "[variables('tenantId')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[variables('msiResourceId')]": {} + } + } + } + }, + "appType": { + "tenantId": "[variables('appTypeDef')[parameters('appType')].tenantId]", + "identity": "[variables('appTypeDef')[parameters('appType')].identity]" + } + }, + "resources": [ + { + "name": "[parameters('groupName')]", + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2018-05-01", + "location": "[parameters('groupLocation')]", + "properties": {} + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2018-05-01", + "name": "storageDeployment", + "resourceGroup": "[parameters('groupName')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups/', parameters('groupName'))]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": {}, + "variables": {}, + "resources": [ + { + "comments": "Create a new App Service Plan", + "type": "Microsoft.Web/serverfarms", + "name": "[variables('appServicePlanName')]", + "apiVersion": "2018-02-01", + "location": "[variables('resourcesLocation')]", + "sku": "[parameters('appServicePlanSku')]", + "properties": { + "name": "[variables('appServicePlanName')]" + } + }, + { + "comments": "Create a Web App using the new App Service Plan", + "type": "Microsoft.Web/sites", + "apiVersion": "2015-08-01", + "location": "[variables('resourcesLocation')]", + "kind": "app", + "dependsOn": [ + "[concat(variables('resourceGroupId'), '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]" + ], + "name": "[variables('appServiceName')]", + "identity": "[variables('appType').identity]", + "properties": { + "name": "[variables('appServiceName')]", + "serverFarmId": "[variables('appServicePlanName')]", + "siteConfig": { + "appSettings": [ + { + "name": "WEBSITE_NODE_DEFAULT_VERSION", + "value": "10.14.1" + }, + { + "name": "MicrosoftAppType", + "value": "[parameters('appType')]" + }, + { + "name": "MicrosoftAppId", + "value": "[parameters('appId')]" + }, + { + "name": "MicrosoftAppPassword", + "value": "[parameters('appSecret')]" + }, + { + "name": "MicrosoftAppTenantId", + "value": "[variables('appType').tenantId]" + } + ], + "cors": { + "allowedOrigins": [ + "https://botservice.hosting.portal.azure.net", + "https://hosting.onecloud.azure-test.net/" + ] + }, + "webSocketsEnabled": true + } + } + } + ], + "outputs": {} + } + } + } + ] +} \ No newline at end of file diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Program.cs b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Program.cs new file mode 100644 index 0000000000..15de094baf --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Program.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Microsoft.BotBuilderSamples +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.ConfigureLogging((logging) => + { + logging.AddDebug(); + logging.AddConsole(); + }); + webBuilder.UseStartup(); + }); + } +} diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Properties/launchSettings.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Properties/launchSettings.json new file mode 100644 index 0000000000..3a137dd606 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:3978/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + ".NET Core": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:3978/" + } + } +} diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/README.md b/samples/csharp_dotnetcore/84.bot-authentication-certificate/README.md new file mode 100644 index 0000000000..1ec0fd1de4 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/README.md @@ -0,0 +1,126 @@ +# Authentication Bot using SSL/TLS certificates + +Bot Framework v4 bot authentication using Certificate + +This bot has been created using [Bot Framework](https://dev.botframework.com/), is shows how to use the bot authentication capabilities of Azure Bot Service. In this sample, we use a local or KeyVault certificate to create the Bot Framework Authentication. + +## Prerequisites + +- [.NET SDK](https://dotnet.microsoft.com/download) version 6.0 + + ```bash + # determine dotnet version + dotnet --version + ``` + +## To try this sample + +- Clone the repository + + ```bash + git clone https://github.com/microsoft/botbuilder-samples.git + ``` + +- Set app settings variables + + - MicrosoftAppType: Type of the App. + + - MicrosoftAppId: App Id of your bot. + + - MicrosoftAppTenantId: Tenant Id to which your bot belongs. + + - KeyVaultName: Name of the KeyVault containing the certificate. + + - CertificateName: Name of the certificate in the KeyVault. + + +- Run the bot from a terminal or from Visual Studio: + + A) From a terminal, navigate to `samples/csharp_dotnetcore/84.bot-authentication-certificate` + + ```bash + # run the bot + dotnet run + ``` + + B) Or from Visual Studio + + - Launch Visual Studio + - File -> Open -> Project/Solution + - Navigate to `samples/csharp_dotnetcore/84.bot-authentication-certificate` folder + - Select `AuthCertificateBot.csproj` file + - Press `F5` to run the project + +## Testing the bot using Bot Framework Emulator + +[Bot Framework Emulator](https://github.com/microsoft/botframework-emulator) is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel. + +- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) + +### Connect to the bot using Bot Framework Emulator + +- Launch Bot Framework Emulator +- File -> Open Bot +- Enter a Bot URL of `http://localhost:3978/api/messages` + +## Interacting with the bot + +This sample uses the bot authentication capabilities of Azure Bot Service, providing features to make it easier to develop a bot that authenticates users using digital security certificates. You just need to provide the certificate data linked to the managed identity and run the bot, then communicate with it to validate its correct authentication. + +## SSL/TLS certificate + +An SSL/TLS certificate is a digital object that allows systems to verify identity and subsequently establish an encrypted network connection with another system using the Secure Sockets Layer/Transport Layer Security (SSL/TLS) protocol. Certificates are issued using a cryptographic system known as public key infrastructure (PKI). PKI allows one party to establish the identity of another through the use of certificates if they both trust a third party, known as a certificate authority. SSL/TLS certificates therefore function as digital identity documents that protect network communications and establish the identity of websites on the Internet as well as resources on private networks. + +## How to create an SSL/TLS certificate + +There are two possible options to create SSL/TSL certificate. Below is a step-by-step description of each one: + +### Using local environment + +1. Run the following command in a local PowerShell + +``` +$cert = New-SelfSignedCertificate -CertStoreLocation "" -Subject "CN=" -KeySpec KeyExchange +``` + +1. Then, type _Manage User Certificates_ in the Windows search bar and hit enter + +2. The certificate will be located in the _user certificates_ folder, under _personal_ directory. + +3. Export the certificate to _pfx_ format including the key(The default location is _system32_ folder). + +4. Go to the certificate location and run the following command to generate a _pem_ file: + +``` +OpenSSL pkcs12 -in .pfx -out c:\.pem –nodes +``` + +5. Upload the generated certificate to the Azure app registration. + +### Using KeyVault + +1. Create a KeyVault resource and assign _the KeyVault Administrator_ role to have permission to create a new certificate. + +2. Under the Certificates section, hit on Generate/Import, complete the form, and create the certificate in PEM format. + +3. Go to the details of the certificate that you created and enable it. + +4. Download the certificate in CER format and then upload it to the Azure app registration. + +## Deploy the bot to Azure + +To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment) for a complete list of deployment instructions. + +## Further reading + +- [Bot Framework Documentation](https://docs.botframework.com) +- [Bot Basics](https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0) +- [Azure Portal](https://portal.azure.com) +- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0) +- [Azure Bot Service Introduction](https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0) +- [Azure Bot Service Documentation](https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0) +- [.NET Core CLI tools](https://docs.microsoft.com/en-us/dotnet/core/tools/?tabs=netcore2x) +- [Azure CLI](https://docs.microsoft.com/cli/azure/?view=azure-cli-latest) +- [Azure Portal](https://portal.azure.com) +- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0) +- [SSL/TLS certificates](https://www.digicert.com/tls-ssl/tls-ssl-certificates) diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Startup.cs b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Startup.cs new file mode 100644 index 0000000000..d142ed94da --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Startup.cs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Identity; +using Azure.Security.KeyVault.Certificates; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Bot.Builder; +using Microsoft.Bot.Builder.Integration.AspNet.Core; +using Microsoft.Bot.Connector.Authentication; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Microsoft.BotBuilderSamples +{ + public class Startup + { + public readonly IConfiguration _configuration; + + public Startup(IConfiguration configuration) + { + _configuration = configuration; + } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddHttpClient().AddControllers().AddNewtonsoftJson(options => + { + options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth; + }); + + // Using KeyVault + // Create a new certificate client using the default credential from Azure.Identity using environment variables previously set, + // including AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID. + var keyVaultUri = $"https://{_configuration["KeyVaultName"]}.vault.azure.net"; + var credential = new DefaultAzureCredential(); + var client = new CertificateClient(new Uri(keyVaultUri), credential); + + //Get certificate in X509Certificate format + var certificateName = _configuration["CertificateName"]; + var certificate = client.DownloadCertificate(certificateName).Value; + + // Using a local certificate + //var certificate = X509Certificate2.CreateFromPemFile(@"{Pem file path}"); + + // Create the ClientCredentialsFactory to user certificate authentication + services.AddSingleton((e) => new CertificateServiceClientCredentialsFactory(certificate, _configuration["MicrosoftAppId"], _configuration["MicrosoftAppTenantId"])); + + // Create the Bot Framework Authentication to be used with the Bot Adapter. + services.AddSingleton(); + + // Create the Bot Adapter with error handling enabled. + services.AddSingleton(); + + // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.) + services.AddSingleton(); + + // Create the User state. (Used in this bot's Dialog implementation.) + services.AddSingleton(); + + // Create the Conversation state. (Used by the Dialog system itself.) + services.AddSingleton(); + + // Create the bot as a transient. In this case the ASP Controller is expecting an IBot. + services.AddTransient(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseDefaultFiles() + .UseStaticFiles() + .UseRouting() + .UseAuthorization() + .UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + + // app.UseHttpsRedirection(); + } + } +} diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/appsettings.json b/samples/csharp_dotnetcore/84.bot-authentication-certificate/appsettings.json new file mode 100644 index 0000000000..59a3940059 --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/appsettings.json @@ -0,0 +1,7 @@ +{ + "MicrosoftAppType": "", + "MicrosoftAppId": "", + "MicrosoftAppTenantId": "", + "KeyVaultName": "", + "CertificateName": "" +} diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/wwwroot/default.htm b/samples/csharp_dotnetcore/84.bot-authentication-certificate/wwwroot/default.htm new file mode 100644 index 0000000000..5f3ef3eada --- /dev/null +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/wwwroot/default.htm @@ -0,0 +1,417 @@ + + + + + + + Bot Authentication Using Certificates Sample + + + + + +
+
+
+
Bot Authentication Using Certificates Sample
+
+
+
+
+
Your bot is ready!
+
You can test your bot in the Bot Framework Emulator
+ by connecting to http://localhost:3978/api/messages.
+ +
Visit Azure + Bot Service to register your bot and add it to
+ various channels. The bot's endpoint URL typically looks + like this:
+
https://your_bots_hostname/api/messages
+
+
+
+
+ +
+ + diff --git a/samples/csharp_dotnetcore/csharp_dotnetcore.sln b/samples/csharp_dotnetcore/csharp_dotnetcore.sln index c1eee46092..fcf8ec1dbb 100644 --- a/samples/csharp_dotnetcore/csharp_dotnetcore.sln +++ b/samples/csharp_dotnetcore/csharp_dotnetcore.sln @@ -82,6 +82,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomQABot", "12.customQAB EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomQABotAllFeatures", "48.customQABot-all-features\CustomQABotAllFeatures.csproj", "{4C855F46-DCA3-4A69-9ED3-3B7491F91CF4}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AuthCertificateBot", "84.bot-authentication-certificate\AuthCertificateBot.csproj", "{FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AuthSNIBot", "85.bot-authentication-sni\AuthSNIBot.csproj", "{95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}" EndProject Global @@ -354,6 +356,14 @@ Global {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Release|Any CPU.Build.0 = Release|Any CPU {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Release|x64.ActiveCfg = Release|Any CPU {95AA9E48-B2A4-40B2-B3D2-DA4B3C1AD652}.Release|x64.Build.0 = Release|Any CPU + {FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}.Debug|x64.ActiveCfg = Debug|Any CPU + {FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}.Debug|x64.Build.0 = Debug|Any CPU + {FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}.Release|Any CPU.Build.0 = Release|Any CPU + {FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}.Release|x64.ActiveCfg = Release|Any CPU + {FA3A48E6-6CBE-4E8B-8CAA-3521511E2725}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/samples/csharp_webapi/13.core-bot/packages.config b/samples/csharp_webapi/13.core-bot/packages.config index 2673d7fd0e..10189caf02 100644 --- a/samples/csharp_webapi/13.core-bot/packages.config +++ b/samples/csharp_webapi/13.core-bot/packages.config @@ -1,4 +1,4 @@ - + @@ -52,11 +52,11 @@ - + - + diff --git a/samples/javascript_es6/01.browser-echo/package.json b/samples/javascript_es6/01.browser-echo/package.json index 84caf04396..17ee0fc282 100644 --- a/samples/javascript_es6/01.browser-echo/package.json +++ b/samples/javascript_es6/01.browser-echo/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@babel/runtime": "^7.1.5", - "botbuilder-core": "~4.17.0", + "botbuilder-core": "~4.19.0", "botframework-directlinejs": "~0.11.2", "botframework-webchat": "4.5.0", "core-js": "^3.0.1" diff --git a/samples/python/17.multilingual-bot/requirements.txt b/samples/python/17.multilingual-bot/requirements.txt index a9f8247181..e92041e9b2 100644 --- a/samples/python/17.multilingual-bot/requirements.txt +++ b/samples/python/17.multilingual-bot/requirements.txt @@ -1,2 +1,2 @@ -requests==2.23.0 +requests==2.31.0 botbuilder-integration-aiohttp>=4.14.0 diff --git a/samples/python/21.corebot-app-insights/requirements.txt b/samples/python/21.corebot-app-insights/requirements.txt index a67ea476b5..f1db12387c 100644 --- a/samples/python/21.corebot-app-insights/requirements.txt +++ b/samples/python/21.corebot-app-insights/requirements.txt @@ -1,5 +1,5 @@ asyncio>=3.4.3 -requests==2.23.0 +requests==2.31.0 botbuilder-core>=4.14.0 botframework-connector>=4.14.0 botbuilder-schema>=4.14.0 diff --git a/samples/python/44.prompt-for-user-input/requirements.txt b/samples/python/44.prompt-for-user-input/requirements.txt index c6afafcfd8..520df586d5 100644 --- a/samples/python/44.prompt-for-user-input/requirements.txt +++ b/samples/python/44.prompt-for-user-input/requirements.txt @@ -1,2 +1,12 @@ botbuilder-integration-aiohttp>=4.14.0 recognizers-text>=1.0.2a1 +recognizers_date_time +recognizers_number +botbuilder-core +aiohttp +emoji +botbuilder-schema +botframework-connector +botbuilder-dialogs +botbuilder-azure +botbuilder