diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/AuthCertificateBot.csproj b/samples/csharp_dotnetcore/84.bot-authentication-certificate/AuthCertificateBot.csproj index b27dce8076..28b9d77c5f 100644 --- a/samples/csharp_dotnetcore/84.bot-authentication-certificate/AuthCertificateBot.csproj +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/AuthCertificateBot.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/BotConversation.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/BotConversation.png new file mode 100644 index 0000000000..975fc2b972 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/BotConversation.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CertificateDetails.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CertificateDetails.png new file mode 100644 index 0000000000..12b024f1c6 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CertificateDetails.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CertificateReading.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CertificateReading.png new file mode 100644 index 0000000000..7abf67ea47 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CertificateReading.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CreateCertificate.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CreateCertificate.png new file mode 100644 index 0000000000..0df798126a Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/CreateCertificate.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/DownloadCertificate.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/DownloadCertificate.png new file mode 100644 index 0000000000..23838f244b Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/DownloadCertificate.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/GenerateCertificate.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/GenerateCertificate.png new file mode 100644 index 0000000000..5dc4cd5396 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/GenerateCertificate.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/RemoveKeys.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/RemoveKeys.png new file mode 100644 index 0000000000..383edc7c85 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/RemoveKeys.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/UploadCerCertificate.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/UploadCerCertificate.png new file mode 100644 index 0000000000..e1081c77f5 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/KeyVault/UploadCerCertificate.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateDirectory.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateDirectory.png new file mode 100644 index 0000000000..c8581bc464 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateDirectory.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateExportSteps1.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateExportSteps1.png new file mode 100644 index 0000000000..377933eb84 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateExportSteps1.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateExportSteps2.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateExportSteps2.png new file mode 100644 index 0000000000..72648d06a5 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateExportSteps2.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateReading.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateReading.png new file mode 100644 index 0000000000..3777fa8caa Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateReading.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateSearch.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateSearch.png new file mode 100644 index 0000000000..af9f811667 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateSearch.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateUpload.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateUpload.png new file mode 100644 index 0000000000..19ee9215f5 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/CertificateUpload.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/GlobalCertificateCommand.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/GlobalCertificateCommand.png new file mode 100644 index 0000000000..00aecf0ebf Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/GlobalCertificateCommand.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/PemCommandNoKey.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/PemCommandNoKey.png new file mode 100644 index 0000000000..09c94b63e7 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/PemCommandNoKey.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/PemCommandWithKey.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/PemCommandWithKey.png new file mode 100644 index 0000000000..94f64f6909 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/PemCommandWithKey.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/UserCertificateCommand.png b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/UserCertificateCommand.png new file mode 100644 index 0000000000..5adc0fa174 Binary files /dev/null and b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Images/Local/UserCertificateCommand.png differ diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/README.md b/samples/csharp_dotnetcore/84.bot-authentication-certificate/README.md index 1ec0fd1de4..090923d426 100644 --- a/samples/csharp_dotnetcore/84.bot-authentication-certificate/README.md +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/README.md @@ -1,111 +1,189 @@ -# Authentication Bot using SSL/TLS certificates +[#LocalEnv]:#using-local-environment +[#KeyVaultEnv]:#using-keyvault +[#TrySample]:#to-try-this-sample + +# 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. +This bot has been created using [Bot Framework](https://dev.botframework.com/), it shows how to use the bot authentication capabilities of Azure Bot Service. -## 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 +In this guide, we'll explain how to create and consume a certificate in Bot Framework with the following options: +1. [Local environment][#LocalEnv] +2. [KeyVault][#KeyVaultEnv] - - MicrosoftAppType: Type of the App. - - - MicrosoftAppId: App Id of your bot. - - - MicrosoftAppTenantId: Tenant Id to which your bot belongs. +## Interacting with the bot - - KeyVaultName: Name of the KeyVault containing the certificate. +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. - - CertificateName: Name of the certificate in the KeyVault. +## 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. -- Run the bot from a terminal or from Visual Studio: +## Prerequisites - A) From a terminal, navigate to `samples/csharp_dotnetcore/84.bot-authentication-certificate` +- [Ngrok](https://ngrok.com/) latest version. +- [.NET SDK](https://dotnet.microsoft.com/download) version 8.0 ```bash - # run the bot - dotnet run + # determine dotnet version + dotnet --version ``` - 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 +## To try this sample -[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. + - Setup ngrok + 1. Follow this [guide](https://ngrok.com/docs/getting-started/?os=windows) to install and configure ngrok in your environment. + 2. Run ngrok with the following command. + ```bash + ngrok http --host-header=rewrite 3978 + ``` -- Install the latest Bot Framework Emulator from [here](https://github.com/Microsoft/BotFramework-Emulator/releases) + - Setup a Bot + 1. Register a bot with Azure Bot Service, following the instructions [here](https://docs.microsoft.com/azure/bot-service/bot-service-quickstart-registration?view=azure-bot-service-3.0). + 2. After registering the bot, use `/api/messages` as the messaging endpoint. + > NOTE: make sure to take note of the Microsoft App Id as we'll need this for later. -### Connect to the bot using Bot Framework Emulator + - Clone the repository + ```bash + git clone https://github.com/microsoft/botbuilder-samples.git + ``` -- Launch Bot Framework Emulator -- File -> Open Bot -- Enter a Bot URL of `http://localhost:3978/api/messages` -## Interacting with the bot +Create and configure the SSL/TSL certificate. In this sample we use two possible options to create and set an SSL/TSL certificate. Below is a step-by-step description of each one: -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. +### Using local environment + 1. Configure the following app settings variables: + - MicrosoftAppId: App Id of your bot (gathered from the [Setup a Bot][#TrySample] step). + - MicrosoftAppType: Type of the App (optional for MultiTenant apps). + - MicrosoftAppTenantId: Tenant Id to which your bot belongs (optional for MultiTenant apps). + + 2. Intall and configure [OpenSSL](https://www.openssl.org/source/) with the latest version. + - Download the latest version source and add the folder to the [environment variables](https://www.java.com/en/download/help/path.html) path. + ```bash + setx path "%path%; + + e.g: + setx path "%path%;C:\Program Files\openssl-3.3.0" + ``` + + 3. Run the following command in PowerShell + - For **global environment certificate** execute the following command with **admin privileges**: + ```powershell + $cert = New-SelfSignedCertificate -CertStoreLocation "." -Subject "CN=" -KeySpec KeyExchange + ``` + e.g: + ![Global Certificate Command](Images/Local/GlobalCertificateCommand.png) + + - For **current user certificate** execute: + ```powershell + $cert = New-SelfSignedCertificate -CertStoreLocation "Cert:\CurrentUser\My" -Subject "CN=" -KeySpec KeyExchange + ``` + e.g: + ![User Certificate Command](Images/Local/UserCertificateCommand.png) + + 4. Then, type _Manage computer certificates (global environment certificate)_ or _Manage User Certificates (current user certificate)_ in the Windows search bar and hit enter. + + ![User Certificate Search](Images/Local/CertificateSearch.png) + + 5. The certificate will be located in the _user certificates_ folder, under _personal_ directory. + + ![Certificate Directory](Images/Local/CertificateDirectory.png) + + 6. Export the certificate to _pfx_ format including the key. + + ![Certificate Export Steps](Images/Local/CertificateExportSteps1.png) + ![Certificate Export Steps](Images/Local/CertificateExportSteps2.png) + + 7. Go to the certificate location and run the following command to generate a _pem_ file (the command will ask for the password generated in the previous step): + ```powershell + OpenSSL pkcs12 -in .\.pfx -out .pem –nodes -nokeys + ``` + e.g: + ![Pem File Command No Key](Images/Local/PemCommandNoKey.png) + + 8. Upload the generated certificate to the Azure app registration. + + ![Certificate Upload](Images/Local/CertificateUpload.png) + + 9. To read the certificate in the bot, the _pem_ file must include the key, then go to the certificate location and run the following command to generate a _pem_ file with key: + ```powershell + OpenSSL pkcs12 -in .\.pfx -out .pem –nodes + ``` + e.g: + ![Pem Command With Key](Images/Local/PemCommandWithKey.png) + + 10. In the sample code, go to the [Startup](Startup.cs) class and uncomment the line of code that reads the local certificate and write the name of the certificate in _pem_ format inside the _CreateFromPemFile_ method. + Be sure to comment out or remove the lines of code that use Azure KeyVault to avoid errors. + > NOTE: Here the value of `MicrosoftAppId` and `MicrosoftAppTenantId` are needed to generate the credentials. + + ![Certificate Reading](Images/Local/CertificateReading.png) -## SSL/TLS certificate +### Using KeyVault + 1. This option requires the following app settings variables: + - KeyVaultName: Name of the KeyVault containing the certificate. + - CertificateName: Name of the certificate in the KeyVault. + - MicrosoftAppId: App Id of your bot (gathered from the [Setup a Bot][#TrySample] step). + - MicrosoftAppType: Type of the App (optional for MultiTenant apps). + - MicrosoftAppTenantId: Tenant Id to which your bot belongs (optional for MultiTenant apps). -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. + 3. Create a [KeyVault](https://learn.microsoft.com/en-us/azure/key-vault/general/quick-create-portal) resource. + + 4. Assign KeyVault [permissions](https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli) to the current user if needed to create a new certificate. -## How to create an SSL/TLS certificate + 5. Under the Certificates section, hit on Generate/Import, complete the form, and create the certificate in _pem_ format. + ![Generate Certificate](Images/KeyVault/GenerateCertificate.png) + ![Create Certificate](Images/KeyVault/CreateCertificate.png) -There are two possible options to create SSL/TSL certificate. Below is a step-by-step description of each one: + 6. Go to the details of the certificate and download it in _CER_ format to avoid the export of the private key. -### Using local environment + ![Certificate Details](Images/KeyVault/CertificateDetails.png) + ![Download Certificate](Images/KeyVault/DownloadCertificate.png) -1. Run the following command in a local PowerShell + > NOTE: If you used _pkcs_ format in the creation step and downloaded it in _PFX_ format, install OpenSSL and follow the step 6 of the previous [section](#using-local-environment) to convert it to _pem_ format without keys. -``` -$cert = New-SelfSignedCertificate -CertStoreLocation "" -Subject "CN=" -KeySpec KeyExchange -``` + > NOTE: If you downloaded it in _PEM_ format, it will be neccesary to remove the private key by executing the following command: + ``` + OpenSSL pkcs12 -in .\.pem -export -out .\.pem -nokeys + ``` + e.g: + ![Remove Keys](Images/KeyVault/RemoveKeys.png) -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. + 7. Upload the certificate to the Azure app registration. + ![Upload Cer Certificate](Images/KeyVault/UploadCerCertificate.png) -3. Export the certificate to _pfx_ format including the key(The default location is _system32_ folder). + 8. In the sample code, go to the [Startup](Startup.cs) class and uncomment the line of code that reads the keyvault certificate and verify that the keyvault credentials are completed in the [appsettings](appsettings.json) file. + Be sure to comment out or remove the lines of code that use local certificate to avoid errors. + > NOTE: Here the value of `MicrosoftAppId` and `MicrosoftAppTenantId` are also needed to generate the credentials. -4. Go to the certificate location and run the following command to generate a _pem_ file: + ![Certificate Reading](Images/KeyVault/CertificateReading.png) -``` -OpenSSL pkcs12 -in .pfx -out c:\.pem –nodes -``` + 9. In the current sample context, log into Azure to obtain the default credentials by executing the following command. + ```powershell + az login + ``` -5. Upload the generated certificate to the Azure app registration. +### Run the bot from a terminal or from Visual Studio: + - From a terminal, navigate to `samples/csharp_dotnetcore/84.bot-authentication-certificate` and execute: + ```bash + # run the bot + dotnet run + ``` -### Using KeyVault + - 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 -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. +## Testing the bot using Azure Bot -3. Go to the details of the certificate that you created and enable it. +Go to the Azure bot resource created previously, select the _Test in Web Chat_ option under the _Settings_ section and start talking to the bot. -4. Download the certificate in CER format and then upload it to the Azure app registration. +![Bot Conversation](Images/BotConversation.png) ## Deploy the bot to Azure diff --git a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Startup.cs b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Startup.cs index 4830af6798..a20557127c 100644 --- a/samples/csharp_dotnetcore/84.bot-authentication-certificate/Startup.cs +++ b/samples/csharp_dotnetcore/84.bot-authentication-certificate/Startup.cs @@ -4,6 +4,7 @@ using System; using Azure.Identity; using Azure.Security.KeyVault.Certificates; +using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Bot.Builder; @@ -32,18 +33,18 @@ public void ConfigureServices(IServiceCollection services) options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth; }); - // Using KeyVault + //// 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 + //Get certificate in X509Certificate format var certificateName = _configuration["CertificateName"]; - var certificate = client.DownloadCertificate(certificateName).Value; + var certificate = client.DownloadCertificate(certificateName).Value; - // Using a local certificate + //// Using a local certificate //var certificate = X509Certificate2.CreateFromPemFile(@"{Pem file path}"); // Create the ClientCredentialsFactory to user certificate authentication diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/AuthSNIBot.csproj b/samples/csharp_dotnetcore/85.bot-authentication-sni/AuthSNIBot.csproj index d3e9ce08cc..8998ff6b73 100644 --- a/samples/csharp_dotnetcore/85.bot-authentication-sni/AuthSNIBot.csproj +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/AuthSNIBot.csproj @@ -7,7 +7,7 @@ - + diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthSNIBot.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthSNIBot.cs index 9bf8146852..df38fff405 100644 --- a/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthSNIBot.cs +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Bots/AuthSNIBot.cs @@ -19,14 +19,14 @@ protected override async Task OnMessageActivityAsync(ITurnContext membersAdded, ITurnContext turnContext, CancellationToken cancellationToken) { - var welcomeText = "Hello and welcome!"; - foreach (var member in membersAdded) + var welcomeText = "Welcome to the Bot with Subject Name/Issuer Authentication."; + foreach (var member in turnContext.Activity.MembersAdded) { if (member.Id != turnContext.Activity.Recipient.Id) { await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken); } } - } + } } } diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/BotConversation.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/BotConversation.png new file mode 100644 index 0000000000..975fc2b972 Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/BotConversation.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/CertificateDetails.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/CertificateDetails.png new file mode 100644 index 0000000000..12b024f1c6 Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/CertificateDetails.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/CertificateReading.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/CertificateReading.png new file mode 100644 index 0000000000..3c69b5af7f Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/CertificateReading.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/DownloadCertificate.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/DownloadCertificate.png new file mode 100644 index 0000000000..23838f244b Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/DownloadCertificate.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/GenerateImportCertificate.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/GenerateImportCertificate.png new file mode 100644 index 0000000000..5dc4cd5396 Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/GenerateImportCertificate.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/ImportCertificate.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/ImportCertificate.png new file mode 100644 index 0000000000..c27719fb71 Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/ImportCertificate.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/UploadCerCertificate.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/UploadCerCertificate.png new file mode 100644 index 0000000000..29942d8511 Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/KeyVault/UploadCerCertificate.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/CertificateReading.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/CertificateReading.png new file mode 100644 index 0000000000..e609226789 Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/CertificateReading.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/CertificateUpload.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/CertificateUpload.png new file mode 100644 index 0000000000..25cb24890e Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/CertificateUpload.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemCommandNoKey.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemCommandNoKey.png new file mode 100644 index 0000000000..f2008e54a3 Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemCommandNoKey.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemCommandWithKey.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemCommandWithKey.png new file mode 100644 index 0000000000..d700acddbe Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemCommandWithKey.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemExportNoKey.png b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemExportNoKey.png new file mode 100644 index 0000000000..89d2990dc7 Binary files /dev/null and b/samples/csharp_dotnetcore/85.bot-authentication-sni/Images/Local/PemExportNoKey.png differ diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/README.md b/samples/csharp_dotnetcore/85.bot-authentication-sni/README.md index 3055589b05..a4f00a1241 100644 --- a/samples/csharp_dotnetcore/85.bot-authentication-sni/README.md +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/README.md @@ -1,12 +1,35 @@ -# Authentication Bot using Subject Name/Issuer +[#LocalEnv]:#using-local-environment +[#KeyVaultEnv]:#using-keyvault +[#TrySample]:#to-try-this-sample + +# Authentication Bot using Subject Name/Issuer Bot Framework v4 bot authentication using Subject Name/Issuer -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 and the MSAL Subject Name/Issuer configuration to create the Bot Framework Authentication. +This bot has been created using Bot Framework, it shows how to use the bot authentication capabilities of Azure Bot Service. In this sample, we use a local or KeyVault certificate and the MSAL Subject Name/Issuer configuration to create the Bot Framework Authentication. +> [!IMPORTANT] +> Microsoft's first-party resources are required to test this sample. + +In this guide, we'll explain how to consume a certificate in Bot Framework with the following options: +1. [Local environment][#LocalEnv] +2. [KeyVault][#KeyVaultEnv] + +## 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. + +## Subject Name and Issuer (SNI) Authentication + +Certificate Subject Name and Issuer (SNI) based authentication is currently available only for Microsoft internal (first-party) applications. External (third-party) apps cannot use SNI because SNI is based on the assumption that the certificate issuer is the same as the tenant owner. This can be guaranteed for some first-party tenants, but not for third-party. So there are no plans to bring SNI to third-party apps. For more details about this feature and code examples see this [SNI issue](https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/60) and a [wiki page](https://aadwiki.windows-int.net/index.php?title=Subject_Name_and_Issuer_Authentication). ## Prerequisites -- [.NET SDK](https://dotnet.microsoft.com/download) version 6.0 +- [Ngrok](https://ngrok.com/) latest version. +- [.NET SDK](https://dotnet.microsoft.com/download) version 8.0 ```bash # determine dotnet version @@ -15,62 +38,155 @@ This bot has been created using [Bot Framework](https://dev.botframework.com/), ## To try this sample +- Setup ngrok + 1. Follow this [guide](https://ngrok.com/docs/getting-started/?os=windows) to install and configure ngrok in your environment. + 2. Run ngrok with the following command. + ```bash + ngrok http --host-header=rewrite 3978 + ``` + +- Setup a Bot +> [!NOTE] +> The app registration used here can be Single or Multi tenant. + +1. Register a bot with Azure Bot Service, following the instructions [here](https://docs.microsoft.com/azure/bot-service/bot-service-quickstart-registration?view=azure-bot-service-3.0). +2. After registering the bot, use `/api/messages` as the messaging endpoint. + > NOTE: make sure to take note of the Microsoft App Id as we'll need this for later. - Clone the repository - ```bash git clone https://github.com/microsoft/botbuilder-samples.git ``` -- Open from Visual Studio - - Launch Visual Studio - - File -> Open -> Project/Solution - - Navigate to `samples/csharp_dotnetcore/85.bot-authentication-sni` folder - - Select `AuthSNIBot.csproj` file - -- Create an SSL/TLS certificate 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 and record the subject name +- Setup the app registration -- Create Azure App and Bot - - Create App Registration - - This can be either Single or Multi tenant - - Record the Application ID - - Add this to the Manifest + Go to the app registration used by the azure bot and add the following configuration to the manifest: + "trustedCertificateSubjects": [ { "authorityId": "00000000-0000-0000-0000-000000000001", - + "subjectName": "certificate_subject_name", - + "revokedCertificateIdentifiers": [] } ] - - Create an Azure Bot in the desired resource group. Use the App Registration from the previous step. -- Set appsettings.json variables +- Configure the SSL/TSL certificate. This sample requires an existing certificate issued by an integrated CA. We have two options to configure it in the bot. Below is a step-by-step description of each one: + + ### Using local environment + 1. Configure the following app settings variables: + - MicrosoftAppId: App Id of your bot (gathered from the [Setup a Bot][#TrySample] step). + - MicrosoftAppType: Type of the App (optional for MultiTenant apps). + - MicrosoftAppTenantId: Tenant Id to which your bot belongs (optional for MultiTenant apps). + + 2. Intall and configure [OpenSSL](https://www.openssl.org/source/) with the latest version + - Download the latest version source and add the folder to the [environment variables](https://www.java.com/en/download/help/path.html) path. + ```bash + setx path "%path%; + e.g + setx path "%path%;C:\Program Files\openssl-3.3.0" + ``` + + 3. Generate a _pem_ file without key: + - If your certificate is in _pfx_ format execute the following command: + ```powershell + OpenSSL pkcs12 -in .\.pfx -out .pem –nodes -nokeys + ``` + e.g: + ![Pem File Command No Key](Images/Local/PemCommandNoKey.png) + + - If your certificate is in _pem_ format and includes the key, execute the following command to remove the key: + ```powershell + OpenSSL pkcs12 -in .\.pem -export -out .\.pem -nokeys + ``` + e.g: + ![Pem Export No Key](Images/Local/PemExportNoKey.png) + + 4. Upload the generated certificate to the Azure app registration. + + ![Certificate Upload](Images/Local/CertificateUpload.png) + + 5. To read the certificate in the bot, the _pem_ file must include the key, then if your certificate is in _pfx_ format go to the certificate location and run the following command to generate a _pem_ file with key: + + ```powershell + OpenSSL pkcs12 -in .\.pfx -out .pem –nodes + ``` + e.g + ![Pem Command With Key](Images/Local/PemCommandWithKey.png) + + 6. In the sample code, go to the [Startup](Startup.cs) class and uncomment the line of code that reads the local certificate and write the name of the certificate in _pem_ format inside the _CreateFromPemFile_ method. + Be sure to comment out or remove the lines of code that use Azure KeyVault to avoid errors. + Keep in mind that the SNI authentication works with the sendX5C flag, keep its value in _true_. + + > NOTE: Here the values of `MicrosoftAppId` and `MicrosoftTenantId` are needed to generate the credentials. - - MicrosoftAppType: {SingTenant | MultiTenant} + ![Certificate Reading](Images/Local/CertificateReading.png) - - MicrosoftAppId: {appId} + ### Using KeyVault + 1. This option requires the following app settings variables: + - KeyVaultName: Name of the KeyVault containing the certificate. + - CertificateName: Name of the certificate in the KeyVault. + - MicrosoftAppId: App Id of your bot (gathered from the [Setup a Bot][#TrySample] step). + - MicrosoftAppType: Type of the App (optional for MultiTenant apps). + - MicrosoftAppTenantId: Tenant Id to which your bot belongs (optional for MultiTenant apps). - - MicrosoftAppTenantId: {tenantId} + 2. Import the certificate under the Certificates section, hit on Generate/Import, complete the form, and upload the certificate. - - KeyVaultName: Name of the KeyVault containing the certificate. + ![Generate Import Certificate](Images/KeyVault/GenerateImportCertificate.png) + ![Import Certificate](Images/KeyVault/ImportCertificate.png) - - CertificateName: Name of the certificate in the KeyVault. + 3. Go to the details of the certificate and download it in _CER_ format to avoid the export of the private key. -- Run the bot from Visual Studio: + ![Certificate Details](Images/KeyVault/CertificateDetails.png) + ![Download Certificate](Images/KeyVault/DownloadCertificate.png) -## Interacting with the bot + >NOTE: If you downloaded it in _PFX/PEM_ format, it will be neccesary to remove the private key by executing one the following commands: + ```powershell + OpenSSL pkcs12 -in .\.pfx -out .pem –nodes -nokeys + OpenSSL pkcs12 -in .\.pem -export -out .\.pem -nokeys + ``` + e.g: + ![Pem File Command No Key](Images/Local/PemCommandNoKey.png) + ![Pem Export No Key](Images/Local/PemExportNoKey.png) -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. + 4. Upload the certificate to the Azure app registration. -## SSL/TLS certificate + ![Upload Cer Certificate](Images/KeyVault/UploadCerCertificate.png) -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. + 5. In the sample code, go to the [Startup](Startup.cs) class and uncomment the line of code that reads the keyvault certificate and verify that the keyvault credentials are completed in the [appsettings](appsettings.json) file. + Be sure to comment out or remove the lines of code that use local certificate to avoid errors. + Keep in mind that the SNI authentication works with the sendX5C flag, keep its value in _true_. + > NOTE: Here the values of `MicrosoftAppId` and `MicrosoftTenantId` are also needed to generate the credentials. + + ![Certificate Reading](Images/KeyVault/CertificateReading.png) + + 6. In the current sample context, log into Azure to obtain the default credentials by executing the following command. + ```powershell + az login + ``` + +### Run the bot from a terminal or from Visual Studio: + + - From a terminal, navigate to `samples/csharp_dotnetcore/85.bot-authentication-sn` + + ```bash + # run the bot + dotnet run + ``` + + - Or from Visual Studio + + - Launch Visual Studio + - File -> Open -> Project/Solution + - Navigate to `samples/csharp_dotnetcore/85.bot-authentication-sn` folder + - Select `AuthSNIBot.csproj` file + - Press `F5` to run the project + +## Testing the bot using Azure Bot + +Go to the Azure bot resource created previously, select the _Test in Web Chat_ option under the _Settings_ section and start talking to the bot. + +![Bot Conversation](Images/BotConversation.png) ## Deploy the bot to Azure @@ -89,3 +205,4 @@ To learn more about deploying a bot to Azure, see [Deploy your bot to Azure](htt - [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) +- [Subject Name and Issuer (SNI) Authentication](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Subject-Name-and-Issuer-(SNI)-Authentication) diff --git a/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs b/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs index 1a183b00ae..d8853a6c9c 100644 --- a/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs +++ b/samples/csharp_dotnetcore/85.bot-authentication-sni/Startup.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Security.Cryptography.X509Certificates; using Azure.Identity; using Azure.Security.KeyVault.Certificates; using Microsoft.AspNetCore.Builder; @@ -33,7 +34,6 @@ public void ConfigureServices(IServiceCollection services) options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth; }); - // // NOTE // @@ -41,7 +41,7 @@ public void ConfigureServices(IServiceCollection services) // functionality is rolled into BF SDK. // - // Set sendX5C value to true to use SNI authentication. + //Set sendX5C value to true to use SNI auhtentication. var sendX5C = true; // Using KeyVault. @@ -55,6 +55,9 @@ public void ConfigureServices(IServiceCollection services) var certificateName = _configuration["CertificateName"]; var certificate = client.DownloadCertificate(certificateName).Value; + // Using a local certificate. + //var certificate = X509Certificate2.CreateFromPemFile(@"{Pem file path}"); + // Register CertificateServiceClientCredentialsFactory services.AddSingleton( new CertificateServiceClientCredentialsFactory(certificate, _configuration["MicrosoftAppId"], _configuration["MicrosoftAppTenantId"], null, null, sendX5C));