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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions samples/graph-rsc/csharp/M365Agent/aad.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
{
"id": "TeamsAppInstallation.ReadForUser.All",
"type": "Role"
},
{
"id": "TeamsActivity.Send",
"type": "Role"
}
]
}
Expand Down
15 changes: 0 additions & 15 deletions samples/graph-rsc/csharp/M365Agent/env/.env.local
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,3 @@
TEAMSFX_ENV=local

# Generated during provision, you can also add your own variables.
TEAMS_APP_ID=
AAD_APP_CLIENT_ID=
AAD_APP_OBJECT_ID=
AAD_APP_OAUTH2_PERMISSION_ID=
AAD_APP_TENANT_ID=
AAD_APP_OAUTH_AUTHORITY_HOST=
AAD_APP_OAUTH_AUTHORITY=
TAB_ENDPOINT=

TEAMSFX_M365_USER_NAME=

APP_NAME_SUFFIX=
TAB_DOMAIN=
TEAMS_APP_TENANT_ID=
AAD_APP_ACCESS_AS_USER_PERMISSION_ID=
3 changes: 2 additions & 1 deletion samples/graph-rsc/csharp/M365Agent/m365agents.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ version: v1.2
additionalMetadata:
sampleTag: Microsoft-Teams-Samples:graph-rsc-csharp

environmentFolderPath: ./env
environmentFolderPath: ./env
projectId:
4 changes: 3 additions & 1 deletion samples/graph-rsc/csharp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ The simplest way to run this sample in Teams is to use Teams Toolkit for Visual

1) Register your app with Microsoft identity platform via the Microsoft Entra ID portal (Microsoft Entra ID app registration)
- Your app must be registered in the Microsoft Entra ID portal to integrate with the Microsoft identity platform and call Microsoft Graph APIs. See [Register an application with the Microsoft identity platform](https://docs.microsoft.com/graph/auth-register-app-v2).
**Note** - Make sure you have added `TeamsAppInstallation.ReadForUser.All` as Application level
**Note** - Make sure you have added below permissions
1. `TeamsAppInstallation.ReadForUser.All` as Application level
2. `TeamsActivity.Send` as Application level

2) Clone the repository
```bash
Expand Down
72 changes: 52 additions & 20 deletions samples/graph-rsc/csharp/RSCDemo/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
using Microsoft.AspNetCore.Mvc;
// <copyright file="HomeController.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// </copyright>

using Azure.Core;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Graph;
using Microsoft.Identity.Client;
Expand All @@ -13,13 +19,13 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static RSCDemo.Helper.GraphClient;

namespace RSCWithGraphAPI.Controllers
{
public class HomeController : Controller
{
private readonly IConfiguration _configuration;

public string appId;

public HomeController(IConfiguration configuration)
Expand Down Expand Up @@ -79,9 +85,24 @@
return result.Value.Select(r => r.Permission).ToList();
}

/// <summary>
/// Get Authenticated Graph Client (fixed for Graph SDK 5+)
/// </summary>
private async Task<GraphServiceClient> GetAuthenticatedClient()
{
var accessToken = await GetToken();

var accessTokenProvider = new SimpleAccessTokenProvider(accessToken);

var authProvider = new BaseBearerTokenAuthenticationProvider(accessTokenProvider);

var graphClient = new GraphServiceClient(authProvider);

return graphClient;
}

/// <summary>
///Get Authenticated Client
/// Simple Access Token Provider for Graph SDK
/// </summary>
public class SimpleAccessTokenProvider : IAccessTokenProvider
{
Expand All @@ -92,21 +113,33 @@
_accessToken = accessToken;
}

public Task<string> GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object> context = null, CancellationToken cancellationToken = default)
public AllowedHostsValidator AllowedHostsValidator { get; }

public async Task<string> GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object> additionalAuthenticationContext = null, CancellationToken cancellationToken = default)

Check warning on line 118 in samples/graph-rsc/csharp/RSCDemo/Controllers/HomeController.cs

View workflow job for this annotation

GitHub Actions / Build All "graph-rsc" csharp

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 118 in samples/graph-rsc/csharp/RSCDemo/Controllers/HomeController.cs

View workflow job for this annotation

GitHub Actions / Build All "graph-rsc" csharp

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
return Task.FromResult(_accessToken);
return _accessToken;
}

public AllowedHostsValidator AllowedHostsValidator => new AllowedHostsValidator();
}

private async Task<GraphServiceClient> GetAuthenticatedClient()
// New helper class to return AccessToken
private class SimpleAccessTokenCredential : TokenCredential
{
var accessToken = await GetToken();
var tokenProvider = new SimpleAccessTokenProvider(accessToken);
var authProvider = new BaseBearerTokenAuthenticationProvider(tokenProvider);
private readonly string _accessToken;

public SimpleAccessTokenCredential(string accessToken)
{
_accessToken = accessToken;
}

public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
{
return new AccessToken(_accessToken, DateTimeOffset.UtcNow.AddHours(1));
}

return new GraphServiceClient(authProvider);
public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
{
return new ValueTask<AccessToken>(new AccessToken(_accessToken, DateTimeOffset.UtcNow.AddHours(1)));
}
}

/// <summary>
Expand Down Expand Up @@ -142,19 +175,18 @@
{
// Read and display the response content
string responseBody = await response.Content.ReadAsStringAsync();

var responseData = JsonConvert.DeserializeObject<ResponseData>(responseBody);
var installedAppList = responseData.Value;

foreach(AppData element in installedAppList)
foreach (AppData element in installedAppList)
{
if (element.TeamsAppDefinition.DisplayName == "RSC-GraphAPI ")
{
appId = element.Id;
}
};
}

if(appId != null)
if (appId != null)
{
await SendNotification(reciepientUserId, appId);
return Json("Message sent successfully");
Expand All @@ -167,13 +199,13 @@
else
{
Console.WriteLine($"Error: {response.StatusCode}");
return Json("Error occured");
return Json("Error occurred");
}
}
catch (Exception ex)
{
{
Console.WriteLine($"Error: {ex.Message}");
return Json("Error occured"+ ex.Message);
return Json("Error occurred: " + ex.Message);
}
}
}
Expand Down Expand Up @@ -230,7 +262,7 @@
else
{
Console.WriteLine($"Error: {response.StatusCode}");
return "Notification sent";
return "Notification failed";
}
}
catch (Exception ex)
Expand Down
44 changes: 44 additions & 0 deletions samples/graph-rsc/csharp/RSCDemo/Helper/GraphClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// <copyright file="GraphClient.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// </copyright>

using Microsoft.Graph;
using Microsoft.Kiota.Abstractions.Authentication;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using System;

namespace RSCDemo.Helper
{
public class GraphClient
{

public class SimpleAccessTokenProvider : IAccessTokenProvider
{
private readonly string _accessToken;

public SimpleAccessTokenProvider(string accessToken)
{
_accessToken = accessToken;
}

public Task<string> GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object> context = null, CancellationToken cancellationToken = default)
{
return Task.FromResult(_accessToken);
}

public AllowedHostsValidator AllowedHostsValidator => new AllowedHostsValidator();
}

public static GraphServiceClient GetGraphClient(string accessToken)
{
var tokenProvider = new SimpleAccessTokenProvider(accessToken);
var authProvider = new BaseBearerTokenAuthenticationProvider(tokenProvider);

return new GraphServiceClient(authProvider);
}

}
}
9 changes: 5 additions & 4 deletions samples/graph-rsc/csharp/RSCDemo/Models/DemoViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Microsoft.Graph;
using System;
// <copyright file="DemoViewModel.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// </copyright>

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RSCWithGraphAPI.Models
{
Expand Down
5 changes: 4 additions & 1 deletion samples/graph-rsc/csharp/RSCDemo/Models/ErrorViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
// <copyright file="ErrorViewModel.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// </copyright>

namespace RSCWithGraphAPI.Models
{
Expand Down
7 changes: 6 additions & 1 deletion samples/graph-rsc/csharp/RSCDemo/Models/ResponseData.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
using System.Collections.Generic;
// <copyright file="ResponseData.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// </copyright>

using System.Collections.Generic;

namespace RSCWithGraphAPI.Models
{
Expand Down
22 changes: 11 additions & 11 deletions samples/graph-rsc/csharp/RSCDemo/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ClientId": "<<Client Id>>",
"ClientSecret": "<<Client Secret>>",
"TenantId": "<<Tenant Id>>"
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ClientId": "",
"ClientSecret": "",
"TenantId": ""
}
Loading