Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
Cert Auth with Bot App
  • Loading branch information
freistli committed Sep 23, 2022
1 parent 41c533f commit 8213473
Show file tree
Hide file tree
Showing 25 changed files with 5,310 additions and 0 deletions.
40 changes: 40 additions & 0 deletions MyBotFrameworkAuthentication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const {
CloudAdapter,
ConversationState,
MemoryStorage,
UserState,
ConfigurationBotFrameworkAuthentication
} = require('botbuilder');

class MyBotFrameworkAuthentication extends ConfigurationBotFrameworkAuthentication
{

/**
* Authenticate Bot Framework Protocol requests to Skills.
*
* @param authHeader The http auth header received in the skill request.
* @returns {Promise<ClaimsIdentity>} A [ClaimsIdentity](xref:botframework-connector.ClaimsIdentity).
*/
authenticateChannelRequest(authHeader) {
const result = super.authenticateChannelRequest(authHeader);
return result;
}

/**
* Validate Bot Framework Protocol requests.
*
* @param activity The inbound Activity.
* @param authHeader The HTTP auth header.
* @returns {Promise<AuthenticateRequestResult>} An [AuthenticateRequestResult](xref:botframework-connector.AuthenticateRequestResult).
*/
authenticateRequest(activity, authHeader) {

return super.authenticateRequest(activity,authHeader).then(function(data){
const claimIdentity = data.claimsIdentity;
return data;
} );
}

}

module.exports.MyBotFrameworkAuthentication = MyBotFrameworkAuthentication;
60 changes: 60 additions & 0 deletions MyServiceClientCredentialsFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const {
CertificateAppCredentials,
ServiceClientCredentialsFactory
} = require('botframework-connector');

const fs = require('fs');

class MyServiceClientCredentialsFactory extends ServiceClientCredentialsFactory
{
constructor() {
super();
this.certKey = fs.readFileSync('c:/temp/selfsign.key').toString();
this.thumbPrint = 'bbaf6096f747c9da6ee27ccf996d668a336b0970';
}

/**
* Validates an app ID.
*
* @param appId The app ID to validate.
* @returns {Promise<boolean>} The result is true if `appId` is valid for the controller; otherwise, false.
*/
isValidAppId(appId)
{
return true;
}

/**
* Checks whether bot authentication is disabled.
*
* @returns {Promise<boolean>} If bot authentication is disabled, the result is true; otherwise, false.
*/
isAuthenticationDisabled()
{
return false;
}

/**
* A factory method for creating ServiceClientCredentials.
*
* @param appId The appId.
* @param audience The audience.
* @param loginEndpoint The login url.
* @param validateAuthority The validate authority value to use.
* @returns {Promise<ServiceClientCredentials>} A [ServiceClientCredentials](xref:botframework-connector.ServiceClientCredentials).
*/
createCredentials(
appId,
audience,
loginEndpoint,
validateAuthority
)
{

const certificateAppCredentials = new CertificateAppCredentials(appId,
this.thumbPrint,this.certKey);
return certificateAppCredentials;
}
}

module.exports.MyServiceClientCredentialsFactory = MyServiceClientCredentialsFactory;
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Bot Authentication

Bot Framework v4 bot authentication sample

This bot has been created using [Bot Framework](https://dev.botframework.com), it shows how to use authentication in your bot using OAuth.

The sample uses the bot authentication capabilities in [Azure Bot Service](https://docs.botframework.com), providing features to make it easier to develop a bot that authenticates users to various identity providers such as Azure AD (Azure Active Directory), GitHub, Uber, etc.

NOTE: Microsoft Teams currently differs slightly in the way auth is integrated with the bot. Refer to sample 46.teams-auth.

## Prerequisites

- [Node.js](https://nodejs.org) version 10.14 or higher

```bash
# determine node version
node --version
```

## To try this sample

- Clone the repository

```bash
git clone https://github.com/Microsoft/botbuilder-samples.git
```

- In a console, navigate to `samples/javascript_nodejs/18.bot-authentication`

```bash
cd samples/javascript_nodejs/18.bot-authentication
```

- Install modules

```bash
npm install
```

- Deploy your bot to Azure, see [Deploy your bot to Azure](https://aka.ms/azuredeployment)

- [Add Authentication to your bot via Azure Bot Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-authentication?view=azure-bot-service-4.0&tabs=csharp)

After Authentication has been configured via Azure Bot Service, you can test the bot.

## 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 bot authentication capabilities in Azure Bot Service, providing features to make it easier to develop a bot that authenticates users to various identity providers such as Azure AD (Azure Active Directory), GitHub, Uber, etc. These updates also take steps towards an improved user experience by eliminating the magic code verification for some clients.

## 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)
- [Add Authentication to Your Bot Via Azure Bot Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-authentication?view=azure-bot-service-4.0&tabs=csharp)
- [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)
- [Language Understanding using LUIS](https://docs.microsoft.com/en-us/azure/cognitive-services/luis/)
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
- [Restify](https://www.npmjs.com/package/restify)
- [dotenv](https://www.npmjs.com/package/dotenv)
13 changes: 13 additions & 0 deletions UserProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

class UserProfile {
constructor(transport, name, age, picture) {
this.transport = transport;
this.name = name;
this.age = age;
this.picture = picture;
}
}

module.exports.UserProfile = UserProfile;
42 changes: 42 additions & 0 deletions bots/authBot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

const { DialogBot } = require('./dialogBot');

class AuthBot extends DialogBot {
/**
*
* @param {ConversationState} conversationState
* @param {UserState} userState
* @param {Dialog} dialog
*/
constructor(conversationState, userState, dialog) {
super(conversationState, userState, dialog);

this.onMembersAdded(async (context, next) => {
const membersAdded = context.activity.membersAdded;
for (let cnt = 0; cnt < membersAdded.length; cnt++) {
if (membersAdded[cnt].id !== context.activity.recipient.id) {
await context.sendActivity('Welcome to AuthenticationBot. Type anything to get logged in. Type \'logout\' to sign-out.');
}
}

await next();
});

this.onTokenResponseEvent(async (context, next) => {
console.log('Running dialog with Token Response Event Activity.');
await this.dialog.run(context, this.dialogState);

await next();
});


}

async handleTeamsSigninVerifyState(context, state) {
await this.dialog.run(context, this.dialogState);
}
}

module.exports.AuthBot = AuthBot;
48 changes: 48 additions & 0 deletions bots/dialogBot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

const { TeamsActivityHandler } = require('botbuilder');

class DialogBot extends TeamsActivityHandler {
/**
*
* @param {ConversationState} conversationState
* @param {UserState} userState
* @param {Dialog} dialog
*/
constructor(conversationState, userState, dialog) {
super();
if (!conversationState) throw new Error('[DialogBot]: Missing parameter. conversationState is required');
if (!userState) throw new Error('[DialogBot]: Missing parameter. userState is required');
if (!dialog) throw new Error('[DialogBot]: Missing parameter. dialog is required');

this.conversationState = conversationState;
this.userState = userState;
this.dialog = dialog;
this.dialogState = this.conversationState.createProperty('DialogState');
this.userProfileAccessor = this.userState.createProperty('UserProfile');

this.onMessage(async (context, next) => {
console.log('Running dialog with Message Activity.');
const userProfile = await this.userProfileAccessor.get(context, {});
userProfile.userid = context.activity.from.id;
// Run the Dialog with the new message Activity.
await this.dialog.run(context, this.dialogState);

await next();
});
}

/**
* Override the ActivityHandler.run() method to save state changes after the bot logic completes.
*/
async run(context) {
await super.run(context);

// Save any state changes. The load happened during the execution of the Dialog.
await this.conversationState.saveChanges(context, false);
await this.userState.saveChanges(context, false);
}
}

module.exports.DialogBot = DialogBot;
Original file line number Diff line number Diff line change
@@ -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": ""
}
}
}
Original file line number Diff line number Diff line change
@@ -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": ""
}
}
}
Loading

0 comments on commit 8213473

Please sign in to comment.