Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync with latest changes. #98

Merged
merged 1 commit into from
Jul 12, 2019
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
  •  
  •  
  •  
7 changes: 4 additions & 3 deletions Samples/BetaSamples/RemoteMediaSamples/IncidentBot.sln
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2036
# Visual Studio Version 16
VisualStudioVersion = 16.0.29102.190
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DCC9792D-0B15-4167-8A9F-BB5DDDA6E7D6}"
ProjectSection(SolutionItems) = preProject
..\..\configure_cloud.ps1 = ..\..\configure_cloud.ps1
Getting Started with the Remote Media Samples.md = Getting Started with the Remote Media Samples.md
..\Graph.props = ..\Graph.props
..\nuget.config = ..\nuget.config
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IncidentBot", "IncidentBot\IncidentBot.csproj", "{FA70E97D-7018-4B08-A9D0-ABA9967AD7DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Common", "..\..\Common\Sample.Common\Sample.Common.csproj", "{3268E59C-90DC-4D7B-97EA-A1DBB2716DF3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Common", "..\..\Common\Sample.Common\Sample.Common.csproj", "{3268E59C-90DC-4D7B-97EA-A1DBB2716DF3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
10 changes: 9 additions & 1 deletion Samples/BetaSamples/RemoteMediaSamples/IncidentBot/Bot/Bot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ public class Bot
/// <param name="graphLogger">The graph logger.</param>
public Bot(BotOptions options, IGraphLogger graphLogger)
{
var instanceNotificationUri = CallAffinityMiddleware.GetWebInstanceCallbackUri(new Uri(options.BotBaseUrl, HttpRouteConstants.OnIncomingRequestRoute));
this.BotInstanceUri = CallAffinityMiddleware.GetWebInstanceCallbackUri(options.BotBaseUrl);

var instanceNotificationUri = CallAffinityMiddleware.GetWebInstanceCallbackUri(
new Uri(options.BotBaseUrl, HttpRouteConstants.OnIncomingRequestRoute));

this.graphLogger = graphLogger;
var name = this.GetType().Assembly.GetName().Name;
Expand Down Expand Up @@ -146,6 +149,11 @@ public Bot(BotOptions options, IGraphLogger graphLogger)
/// </summary>
public Dictionary<string, MediaPrompt> MediaMap { get; } = new Dictionary<string, MediaPrompt>();

/// <summary>
/// Gets the bots instance URI.
/// </summary>
public Uri BotInstanceUri { get; }

/// <summary>
/// Gets the client.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ namespace IcMBot.Controllers
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Graph.Communications.Common;
using Microsoft.Graph.Communications.Core.Serialization;
using Sample.Common.Logging;
using Sample.IncidentBot;
using Sample.IncidentBot.Bot;
using Sample.IncidentBot.Data;
using Sample.IncidentBot.IncidentStatus;
Expand Down Expand Up @@ -47,9 +49,24 @@ public async Task<IActionResult> PostIncidentAsync([FromBody] IncidentRequestDat

try
{
var botMeetingCall = await this.bot.RaiseIncidentAsync(incidentRequestData).ConfigureAwait(false);
var call = await this.bot.RaiseIncidentAsync(incidentRequestData).ConfigureAwait(false);

return this.Ok(botMeetingCall.Id);
var callUriTemplate = new UriBuilder(this.bot.BotInstanceUri);
callUriTemplate.Path = HttpRouteConstants.CallRoutePrefix.Replace("{callLegId}", call.Id);
callUriTemplate.Query = this.bot.BotInstanceUri.Query.Trim('?');

var callUri = callUriTemplate.Uri.AbsoluteUri;
var values = new Dictionary<string, string>
{
{ "legId", call.Id },
{ "scenarioId", call.ScenarioId.ToString() },
{ "call", callUri },
{ "logs", callUri.Replace("/calls/", "/logs/") },
};

var serializer = new CommsSerializer(pretty: true);
var json = serializer.SerializeObject(values);
return this.Ok(json);
}
catch (Exception e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Sample.IncidentBot.Http
using Microsoft.AspNetCore.Mvc;
using Microsoft.Graph.Communications.Common;
using Microsoft.Graph.Communications.Common.Telemetry;
using Microsoft.Graph.Communications.Core.Serialization;
using Sample.IncidentBot.Bot;
using Sample.IncidentBot.Data;

Expand Down Expand Up @@ -52,7 +53,23 @@ public async Task<IActionResult> JoinCallAsync([FromBody] JoinCallRequestData jo
try
{
var call = await this.bot.JoinCallAsync(joinCallBody).ConfigureAwait(false);
return this.Ok(call.Id);

var callUriTemplate = new UriBuilder(this.bot.BotInstanceUri);
callUriTemplate.Path = HttpRouteConstants.CallRoutePrefix.Replace("{callLegId}", call.Id);
callUriTemplate.Query = this.bot.BotInstanceUri.Query.Trim('?');

var callUri = callUriTemplate.Uri.AbsoluteUri;
var values = new Dictionary<string, string>
{
{ "legId", call.Id },
{ "scenarioId", call.ScenarioId.ToString() },
{ "call", callUri },
{ "logs", callUri.Replace("/calls/", "/logs/") },
};

var serializer = new CommsSerializer(pretty: true);
var json = serializer.SerializeObject(values);
return this.Ok(json);
}
catch (Exception e)
{
Expand Down Expand Up @@ -81,10 +98,17 @@ public ActionResult<List<Dictionary<string, string>>> OnGetCalls()
foreach (var callHandler in this.bot.CallHandlers.Values)
{
var call = callHandler.Call;
var callUriTemplate = new UriBuilder(this.bot.BotInstanceUri);
callUriTemplate.Path = HttpRouteConstants.CallRoutePrefix.Replace("{callLegId}", call.Id);
callUriTemplate.Query = this.bot.BotInstanceUri.Query.Trim('?');

var callUri = callUriTemplate.Uri.AbsoluteUri;
var values = new Dictionary<string, string>
{
{ "legId", call.Id },
{ "scenarioId", call.ScenarioId.ToString() },
{ "call", callUri },
{ "logs", callUri.Replace("/calls/", "/logs/") },
};
calls.Add(values);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<RootNamespace>Sample.IncidentBot</RootNamespace>
<AssemblyName>Sample.IncidentBot</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<PlatformTarget>x64</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

<Import Project="$(MSBuildThisFileDirectory)..\..\..\Graph.props" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
"Domain": "contoso.com",
"TenantId": "00000000-0000-0000-0000-000000000000",

"AppId": "00000000-0000-0000-0000-000000000000",
"AppSecret": "__placeholder__"
"AppId": "%AppId%",
"AppSecret": "%AppSecret%"
},
"Bot": {
"AppId": "00000000-0000-0000-0000-000000000000",
"AppSecret": "__placeholder__",
"AppId": "%AppId%",
"AppSecret": "%AppSecret%",
"PlaceCallEndpointUrl": "https://graph.microsoft.com/beta",
"BotBaseUrl": "https://incidentbot.contoso.com"
"BotBaseUrl": "%ServiceDns%"
}
}
121 changes: 29 additions & 92 deletions Samples/Common/Sample.Common/Authentication/AuthenticationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,16 @@
namespace Sample.Common.Authentication
{
using System;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Graph.Communications.Client.Authentication;
using Microsoft.Graph.Communications.Common;
using Microsoft.Graph.Communications.Common.Telemetry;
using Microsoft.Identity.Client;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
Expand All @@ -28,10 +26,6 @@ namespace Sample.Common.Authentication
/// <seealso cref="IRequestAuthenticationProvider" />
public class AuthenticationProvider : ObjectRoot, IRequestAuthenticationProvider
{
private const string Resource = "https://graph.microsoft.com";
private const string DefaultScope = Resource + "/.default";
private static readonly string[] Scopes = new[] { DefaultScope };

/// <summary>
/// The application name.
/// </summary>
Expand All @@ -47,11 +41,6 @@ public class AuthenticationProvider : ObjectRoot, IRequestAuthenticationProvider
/// </summary>
private readonly string appSecret;

/// <summary>
/// The application certificate.
/// </summary>
private readonly X509Certificate2 appCert;

/// <summary>
/// The open ID configuration refresh interval.
/// </summary>
Expand Down Expand Up @@ -82,21 +71,6 @@ public AuthenticationProvider(string appName, string appId, string appSecret, IG
this.appSecret = appSecret.NotNullOrWhitespace(nameof(appSecret));
}

/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationProvider" /> class.
/// </summary>
/// <param name="appName">The application name.</param>
/// <param name="appId">The application identifier.</param>
/// <param name="appCert">The application certificate.</param>
/// <param name="logger">The logger.</param>
public AuthenticationProvider(string appName, string appId, X509Certificate2 appCert, IGraphLogger logger)
: base(logger.NotNull(nameof(logger)).CreateShim(nameof(AuthenticationProvider)))
{
this.appName = appName.NotNullOrWhitespace(nameof(appName));
this.appId = appId.NotNullOrWhitespace(nameof(appId));
this.appCert = appCert.NotNull(nameof(appCert));
}

/// <summary>
/// Authenticates the specified request message.
/// This method will be called any time there is an outbound request.
Expand All @@ -111,31 +85,34 @@ public AuthenticationProvider(string appName, string appId, X509Certificate2 app
/// </returns>
public async Task AuthenticateOutboundRequestAsync(HttpRequestMessage request, string tenant)
{
const string Schema = "Bearer";
const string schema = "Bearer";
const string replaceString = "{tenant}";
const string oauthV2TokenLink = "https://login.microsoftonline.com/{tenant}";
const string resource = "https://graph.microsoft.com";

// If no tenant was specified, we craft the token link using the common tenant.
// https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints
tenant = string.IsNullOrWhiteSpace(tenant) ? "common" : tenant;
var options = new ConfidentialClientApplicationOptions
{
ClientName = this.appName,
ClientId = this.appId,
ClientVersion = this.GetType().Assembly.GetName().Version.ToString(),
TenantId = tenant,
LogLevel = LogLevel.Info,
EnablePiiLogging = false,
IsDefaultPlatformLoggingEnabled = false,
AzureCloudInstance = AzureCloudInstance.AzurePublic,
};
var tokenLink = oauthV2TokenLink.Replace(replaceString, tenant);

this.GraphLogger.Info("AuthenticationProvider: Generating OAuth token.");
var context = new AuthenticationContext(tokenLink);
var creds = new ClientCredential(this.appId, this.appSecret);

ConfidentialClientApplicationBuilder builder = ConfidentialClientApplicationBuilder
.CreateWithApplicationOptions(options)
.WithLogging(this.LogCallback);
IConfidentialClientApplication app = string.IsNullOrEmpty(this.appSecret)
? builder.WithCertificate(this.appCert).Build()
: builder.WithClientSecret(this.appSecret).Build();
AuthenticationResult result;
try
{
result = await this.AcquireTokenWithRetryAsync(context, resource, creds, attempts: 3).ConfigureAwait(false);
}
catch (Exception ex)
{
this.GraphLogger.Error(ex, $"Failed to generate token for client: {this.appId}");
throw;
}

AuthenticationResult result = await this.AcquireTokenWithRetryAsync(app, 3).ConfigureAwait(false);
this.GraphLogger.Info($"AuthenticationProvider: Generated OAuth token. Expires in {result.ExpiresOn.Subtract(DateTimeOffset.UtcNow).TotalMinutes} minutes.");

request.Headers.Authorization = new AuthenticationHeaderValue(Schema, result.AccessToken);
request.Headers.Authorization = new AuthenticationHeaderValue(schema, result.AccessToken);
}

/// <summary>
Expand Down Expand Up @@ -223,65 +200,25 @@ public async Task<RequestValidationResult> ValidateInboundRequestAsync(HttpReque
return new RequestValidationResult { IsValid = true, TenantId = tenantClaim.Value };
}

/// <summary>
/// Callback delegate that allows application developers to consume logs, and handle them in a custom manner. This
/// callback is set using Microsoft.Identity.Client.AbstractApplicationBuilder`1.WithLogging(Microsoft.Identity.Client.LogCallback,System.Nullable{Microsoft.Identity.Client.LogLevel},System.Nullable{System.Boolean},System.Nullable{System.Boolean}).
/// If PiiLoggingEnabled is set to true, when registering the callback this method will receive the messages twice:
/// once with the containsPii parameter equals false and the message without PII,
/// and a second time with the containsPii parameter equals to true and the message might contain PII.
/// In some cases (when the message does not contain PII), the message will be the same.
/// For details see https://aka.ms/msal-net-logging.
/// </summary>
/// <param name="logLevel">Log level of the log message to process.</param>
/// <param name="message">Pre-formatted log message.</param>
/// <param name="containsPii">
/// Indicates if the log message contains Organizational Identifiable Information (OII)
/// or Personally Identifiable Information (PII) nor not.
/// If Microsoft.Identity.Client.Logger.PiiLoggingEnabled is set to false then this value is always false.
/// Otherwise it will be true when the message contains PII.
/// </param>
private void LogCallback(LogLevel logLevel, string message, bool containsPii)
{
TraceLevel level;
switch (logLevel)
{
case LogLevel.Error:
level = TraceLevel.Error;
break;
case LogLevel.Warning:
level = TraceLevel.Warning;
break;
case LogLevel.Info:
level = TraceLevel.Info;
break;
default:
level = TraceLevel.Verbose;
break;
}

this.GraphLogger.Log(level, message, nameof(IConfidentialClientApplication));
}

/// <summary>
/// Acquires the token and retries if failure occurs.
/// </summary>
/// <param name="app">The confidential application.</param>
/// <param name="context">The application context.</param>
/// <param name="resource">The resource.</param>
/// <param name="creds">The application credentials.</param>
/// <param name="attempts">The attempts.</param>
/// <returns>
/// The <see cref="AuthenticationResult" />.
/// </returns>
private async Task<AuthenticationResult> AcquireTokenWithRetryAsync(IConfidentialClientApplication app, int attempts)
private async Task<AuthenticationResult> AcquireTokenWithRetryAsync(AuthenticationContext context, string resource, ClientCredential creds, int attempts)
{
while (true)
{
attempts--;

try
{
return await app
.AcquireTokenForClient(Scopes)
.ExecuteAsync()
.ConfigureAwait(false);
return await context.AcquireTokenAsync(resource, creds).ConfigureAwait(false);
}
catch (Exception)
{
Expand Down
4 changes: 2 additions & 2 deletions Samples/Common/Sample.Common/Sample.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.Graph.Communications.Client" Version="1.1.0-prerelease.581" />
<PackageReference Include="Microsoft.Graph.Communications.Core.Calls" Version="1.1.0-prerelease.581" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.1.0" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="5.5.0" />
</ItemGroup>

Expand All @@ -23,7 +23,7 @@
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Net.Http" Version="4.3.3" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>

</Project>
8 changes: 4 additions & 4 deletions Samples/CommsSamples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ Global
{3268E59C-90DC-4D7B-97EA-A1DBB2716DF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3268E59C-90DC-4D7B-97EA-A1DBB2716DF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3268E59C-90DC-4D7B-97EA-A1DBB2716DF3}.Release|Any CPU.Build.0 = Release|Any CPU
{64538D87-16CD-4A13-ADA9-63EBA7C80BBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64538D87-16CD-4A13-ADA9-63EBA7C80BBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64538D87-16CD-4A13-ADA9-63EBA7C80BBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64538D87-16CD-4A13-ADA9-63EBA7C80BBE}.Release|Any CPU.Build.0 = Release|Any CPU
{64538D87-16CD-4A13-ADA9-63EBA7C80BBE}.Debug|Any CPU.ActiveCfg = Debug|x64
{64538D87-16CD-4A13-ADA9-63EBA7C80BBE}.Debug|Any CPU.Build.0 = Debug|x64
{64538D87-16CD-4A13-ADA9-63EBA7C80BBE}.Release|Any CPU.ActiveCfg = Release|x64
{64538D87-16CD-4A13-ADA9-63EBA7C80BBE}.Release|Any CPU.Build.0 = Release|x64
{24E33708-FB5C-45F8-81CA-B0C857435FFB}.Debug|Any CPU.ActiveCfg = Debug|x64
{24E33708-FB5C-45F8-81CA-B0C857435FFB}.Debug|Any CPU.Build.0 = Debug|x64
{24E33708-FB5C-45F8-81CA-B0C857435FFB}.Debug|Any CPU.Deploy.0 = Debug|x64
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.28803.202
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36341412-BFDE-495F-8216-7736CE191F39}"
ProjectSection(SolutionItems) = preProject
configure_cloud.ps1 = configure_cloud.ps1
..\..\configure_cloud.ps1 = ..\..\configure_cloud.ps1
E-SDK Samples.postman_collection.json = E-SDK Samples.postman_collection.json
..\..\Graph.props = ..\..\Graph.props
..\..\nuget.config = ..\..\nuget.config
Expand Down
Loading