Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Data.Tables" Version="12.7.0" />
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Blobs" Version="1.2.3" />
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Keys" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.11" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.18.1" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.18.1" />
<PackageReference Include="Microsoft.Identity.Web" Version="1.25.5" />
<PackageReference Include="Azure.Data.Tables" Version="12.11.0" />
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Blobs" Version="1.5.3" />
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Keys" Version="1.6.3" />
<PackageReference Include="Azure.Identity" Version="1.21.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.23.1" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.23.1" />
<PackageReference Include="Microsoft.Identity.Web" Version="4.9.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Net.Http.Headers;
using Azure.Data.Tables;
using Azure.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Bot.Builder;
Expand Down Expand Up @@ -51,22 +50,17 @@

if (useAzure)
{
var azureCredential = new DefaultAzureCredential();

#pragma warning disable ASP0000 // No singletons declared above, just options objects
var postConfigSp = services.BuildServiceProvider();
#pragma warning restore ASP0000
var azureCredential = new Azure.Identity.DefaultAzureCredential();

// Configure the Microsoft.AspNetCore.DataProtection library for encrypting tokens
// at rest and creating tamper-evident state values for OAuth flows
var keyringOptions = postConfigSp.GetRequiredService<IOptions<KeyringConfiguration>>().Value;

// Configure the DataProtection library to use blob storage for persistence & KeyVault for securely storing root key
// We use this combination so that the bot can scale out w/o having incompatible encryption
var keyringConfig = builder.Configuration.GetSection("Keyring").Get<KeyringConfiguration>()!;
services
.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri(keyringOptions.BlobUri), azureCredential)
.ProtectKeysWithAzureKeyVault(new Uri(keyringOptions.KeyIdentifierUri), azureCredential);
.PersistKeysToAzureBlobStorage(new Uri(keyringConfig.BlobUri), azureCredential)
.ProtectKeysWithAzureKeyVault(new Uri(keyringConfig.KeyIdentifierUri), azureCredential);

// Configure a 'replay validator' to ensure that user logins cannot be replayed.
// This uses Azure table storage to allow for scale-out of the bot.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
},
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "{{ Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs)}}",
"TenantId": "{{ Enter the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs)}}",
"ClientId": "{{ Enter the Client Id (Application ID obtained from the Azure portal)}}",
"ClientSecret": "{{ Enter the Client Secret (Obtained from the Azure portal)}}",
"Scopes": "access_as_user",
"CallbackPath": "/signin-oidc"
},
"Bot": {
"MicrosoftAppType": "MultiTenant",
"MicrosoftAppType": "SingleTenant",
"MicrosoftAppId": "{{ Enter the Client Id (Application ID obtained from the Azure portal for the bot's registration)}}",
"MicrosoftAppPassword": "{{ Enter the Client Secret (Obtained from the Azure portal for the bot's registration)"
"MicrosoftAppPassword": "{{ Enter the Client Secret (Obtained from the Azure portal for the bot's registration)}}",
"MicrosoftAppTenantId": "{{ Enter the Tenant Id (Obtained from the Azure portal)}}"
},
"OAuth": {
"AuthorizeUrl": "https://github.com/login/oauth/authorize",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace QRAppInstallation.Pages
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace QRAppInstallation.Pages
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using QRAppInstallation;
using QRAppInstallation.Bots;
using QRAppInstallation.Dialogs;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers().AddNewtonsoftJson();
builder.Services.AddHttpClient();
builder.Services.AddRazorPages();

// Create the storage we'll be using for User and Conversation state.
builder.Services.AddSingleton<IStorage, MemoryStorage>();

// Create the Conversation state.
builder.Services.AddSingleton<ConversationState>();

// The Dialog that will be run by the bot.
builder.Services.AddSingleton<MainDialog>();

// Create the Bot Framework Adapter with error handling enabled.
builder.Services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

// Create the bot as a transient.
builder.Services.AddTransient<IBot, AuthBot<MainDialog>>();

var app = builder.Build();

app.UseDefaultFiles();
app.UseStaticFiles();
app.UseWebSockets();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();

app.Run();
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AdaptiveCards" Version="2.7.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.11" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.18.1" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.18.1" />
<PackageReference Include="Microsoft.Graph" Version="5.76.0" />
<PackageReference Include="AdaptiveCards" Version="3.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.0" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.23.1" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.23.1" />
<PackageReference Include="Microsoft.Graph" Version="5.78.0" />
</ItemGroup>

<ItemGroup>
<ItemGroup>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Graph;
Expand Down Expand Up @@ -32,23 +30,16 @@ public SimpleGraphClient(string token)
// Install app in team.
public async Task InstallAppInTeam(string teamId, string appId)
{
try
var graphClient = GetAuthenticatedClient();
var teamsAppInstallation = new TeamsAppInstallation
{
var graphClient = GetAuthenticatedClient();
var teamsAppInstallation = new TeamsAppInstallation
AdditionalData = new Dictionary<string, object>()
{
AdditionalData = new Dictionary<string, object>()
{
{"teamsApp@odata.bind", "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/"+ appId}
}
};
{"teamsApp@odata.bind", "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/"+ appId}
}
};

await graphClient.Teams[teamId].InstalledApps.PostAsync(teamsAppInstallation);
}
catch (Exception ex)
{
throw;
}
await graphClient.Teams[teamId].InstalledApps.PostAsync(teamsAppInstallation);
}

// Get an Authenticated Microsoft Graph client using the token issued to the user.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"MicrosoftAppType": "SingleTenant",
"MicrosoftAppId": "{{Microsoft-App-Id}}",
"MicrosoftAppPassword": "{{Microsoft-App-Password}}",
"MicrosoftAppTenantId": "{{Microsoft-Tenant-Id}}",
"ConnectionName": "{{ Auth Connection Name }}",
"ApplicationBaseUrl": "{{ Application Base Url }}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"appId": "${{AAD_APP_CLIENT_ID}}",
"name": "app-installation-using-qr-code-aad",
"accessTokenAcceptedVersion": 2,
"signInAudience": "AzureADMultipleOrgs",
"signInAudience": "AzureADMyOrg",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"optionalClaims": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"This sample showcases the installation of a Microsoft Teams app through a QR code, allowing users to generate a QR code containing the app ID and easily install the app by scanning it. Key features include bot integration, Teams SSO, adaptive cards, task modules, and device permissions, all accessible via mobile clients."
],
"creationDateTime": "2021-11-10",
"updateDateTime": "2024-10-10",
"updateDateTime": "2025-05-18",
"products": [
"Teams"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

const { DialogBot } = require('./dialogBot');
const { tokenExchangeOperationName } = require('botbuilder');
const { SsoOAuthHelpler } = require('../SsoOAuthHelpler');
const { SsoOAuthHelpler } = require('../ssoOauthHelpler');

class TeamsBot extends DialogBot {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ const { LogoutDialog } = require('./logoutDialog');
const MAIN_DIALOG = 'MainDialog';
const MAIN_WATERFALL_DIALOG = 'MainWaterfallDialog';
const OAUTH_PROMPT = 'OAuthPrompt';
const { SsoOAuthPrompt } = require('./ssoOAuthPrompt');
const { polyfills } = require('isomorphic-fetch');
const { SsoOAuthPrompt } = require('./ssoOauthPrompt');
const adaptiveCards = require('../models/adaptiveCard');
const { CardFactory } = require('botbuilder');
const Token_State_Property = 'TokenData';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ provision:
- uses: script
with:
run:
# echo "::set-teamsfx-env MICROSOFT_APP_TYPE=SingleTenant";
# echo "::set-teamsfx-env MICROSOFT_APP_TENANT_ID=${{AAD_APP_TENANT_ID}}";
echo "::set-teamsfx-env MICROSOFT_APP_TYPE=MultiTenant";
echo "::set-teamsfx-env MICROSOFT_APP_TENANT_ID=common";
echo "::set-teamsfx-env MICROSOFT_APP_TYPE=SingleTenant";
echo "::set-teamsfx-env MICROSOFT_APP_TENANT_ID=${{AAD_APP_TENANT_ID}}";

- uses: arm/deploy # Deploy given ARM templates parallelly.
with:
Expand Down
Loading
Loading