diff --git a/GraphExplorerAppModeService/GraphExplorerAppModeService.csproj b/GraphExplorerAppModeService/GraphExplorerAppModeService.csproj
index 522ad66e5..52b8f98f0 100644
--- a/GraphExplorerAppModeService/GraphExplorerAppModeService.csproj
+++ b/GraphExplorerAppModeService/GraphExplorerAppModeService.csproj
@@ -8,5 +8,7 @@
+
+
diff --git a/GraphExplorerAppModeService/Interfaces/IGraphAppAuthProvider.cs b/GraphExplorerAppModeService/Interfaces/IGraphAppAuthProvider.cs
index 669e3feeb..56198c228 100644
--- a/GraphExplorerAppModeService/Interfaces/IGraphAppAuthProvider.cs
+++ b/GraphExplorerAppModeService/Interfaces/IGraphAppAuthProvider.cs
@@ -1,4 +1,5 @@
-using System;
+using Microsoft.Graph;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -6,7 +7,8 @@
namespace GraphExplorerAppModeService.Interfaces
{
- interface IGraphAppAuthProvider
+ public interface IGraphAppAuthProvider
{
+ GraphServiceClient GetAuthenticatedGraphClient(string accessToken);
}
}
diff --git a/GraphExplorerAppModeService/Services/GraphAppAuthProvider.cs b/GraphExplorerAppModeService/Services/GraphAppAuthProvider.cs
index 67f55c01a..877ebea9c 100644
--- a/GraphExplorerAppModeService/Services/GraphAppAuthProvider.cs
+++ b/GraphExplorerAppModeService/Services/GraphAppAuthProvider.cs
@@ -1,8 +1,11 @@
using GraphExplorerAppModeService.Interfaces;
using Microsoft.Extensions.Configuration;
+using Microsoft.Graph;
+using Microsoft.Identity.Web;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
@@ -11,9 +14,14 @@ namespace GraphExplorerAppModeService.Services
{
public class GraphAppAuthProvider : IGraphAppAuthProvider
{
- public GraphAppAuthProvider(IConfiguration configuration)
- {
- }
+ public GraphServiceClient GetAuthenticatedGraphClient(string accessToken) =>
+ new GraphServiceClient(new DelegateAuthenticationProvider(
+ async requestMessage =>
+ {
+ // Append the access token to the request
+ requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+ }));
}
+
}
diff --git a/GraphWebApi/Controllers/GraphExplorerAppModeController.cs b/GraphWebApi/Controllers/GraphExplorerAppModeController.cs
index 01ea80cae..4d311b3b9 100644
--- a/GraphWebApi/Controllers/GraphExplorerAppModeController.cs
+++ b/GraphWebApi/Controllers/GraphExplorerAppModeController.cs
@@ -2,49 +2,62 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
-using GraphExplorerAppModeService.Interfaces;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Identity.Web;
using System.Net.Http;
using System.Net.Http.Headers;
+using Microsoft.Graph;
+using System.Net;
+using Microsoft.Identity.Client;
+using System.Threading;
+using Microsoft.Extensions.Primitives;
+using GraphExplorerAppModeService.Services;
+using GraphExplorerAppModeService.Interfaces;
+using Microsoft.Extensions.Configuration;
namespace GraphWebApi.Controllers
{
[ApiController]
public class GraphExplorerAppModeController : ControllerBase
{
- private readonly ITokenAcquisition tokenAcquisition;
- public GraphExplorerAppModeController(ITokenAcquisition tokenAcquisition)
+ private readonly IGraphAppAuthProvider _graphClient;
+ private readonly ITokenAcquisition _tokenAcquisition;
+
+ private readonly IConfiguration _config;
+
+ public GraphExplorerAppModeController(IConfiguration configuration, ITokenAcquisition tokenAcquisition, IGraphAppAuthProvider graphServiceClient)
{
- this.tokenAcquisition = tokenAcquisition;
+ this._graphClient = graphServiceClient;
+ this._tokenAcquisition = tokenAcquisition;
+ this._config = configuration;
}
[Route("api/[controller]/{*all}")]
[Route("graphproxy/{*all}")]
[HttpGet]
- public async Task GetAsync(string all, [FromHeader] string Authorization)
+ [AuthorizeForScopes(Scopes = new[] { "https://graph.microsoft.com/.default" })]
+ public async Task GetAsync(string all)
{
- return await ProcessRequestAsync("GET", all, null, Authorization).ConfigureAwait(false);
+ return await this.ProcessRequestAsync("GET", all, null, _config.GetSection("AzureAd").GetSection("TenantId").Value).ConfigureAwait(false);
}
- [Route("api/[controller]/{*all}")]
- [Route("graphproxy/token/{tenantId}")]
- [HttpGet]
- [AuthorizeForScopes(Scopes = new[] { "https://graph.microsoft.com/.default" })]
- public async Task GetTokenAsync(string tenantId)
+ private async Task GetTokenAsync(string tenantId)
{
// Acquire the access token.
string scopes = "https://graph.microsoft.com/.default";
- return await tokenAcquisition.GetAccessTokenForAppAsync(scopes, tenantId, null);
+
+ return await _tokenAcquisition.GetAccessTokenForAppAsync(scopes, tenantId, null);
}
+
[Route("api/[controller]/{*all}")]
[Route("graphproxy/{*all}")]
[HttpPost]
- public async Task PostAsync(string all, [FromBody] object body, [FromHeader] string Authorization)
+ [AuthorizeForScopes(Scopes = new[] { "https://graph.microsoft.com/.default" })]
+ public async Task PostAsync(string all, [FromBody] object body)
{
- return await ProcessRequestAsync("POST", all, body, Authorization).ConfigureAwait(false);
+ return await ProcessRequestAsync("POST", all, body, _config.GetSection("AzureAd").GetSection("TenantId").Value).ConfigureAwait(false);
}
[Route("api/[controller]/{*all}")]
@@ -52,29 +65,122 @@ public async Task PostAsync(string all, [FromBody] object body, [
[HttpDelete]
public async Task DeleteAsync(string all, [FromHeader] string Authorization)
{
- return await ProcessRequestAsync("DELETE", all, null, Authorization).ConfigureAwait(false);
+ return await ProcessRequestAsync("DELETE", all, null, _config.GetSection("AzureAd").GetSection("TenantId").Value).ConfigureAwait(false);
}
[Route("api/[controller]/{*all}")]
[Route("graphproxy/{*all}")]
[HttpPut]
- public async Task PutAsync(string all, [FromBody] object body, [FromHeader] string Authorization)
+ [AuthorizeForScopes(Scopes = new[] { "https://graph.microsoft.com/.default" })]
+ public async Task PutAsync(string all, [FromBody] object body)
+ {
+ return await ProcessRequestAsync("PUT", all, body, _config.GetSection("AzureAd").GetSection("TenantId").Value).ConfigureAwait(false);
+ }
+
+ private string GetBaseUrlWithoutVersion(GraphServiceClient graphClient)
+ {
+ var baseUrl = graphClient.BaseUrl;
+ var index = baseUrl.LastIndexOf('/');
+ return baseUrl.Substring(0, index);
+ }
+
+ public class HttpResponseMessageResult : IActionResult
{
- return await ProcessRequestAsync("PUT", all, body, Authorization).ConfigureAwait(false);
+ private readonly HttpResponseMessage _responseMessage;
+
+ public HttpResponseMessageResult(HttpResponseMessage responseMessage)
+ {
+ _responseMessage = responseMessage; // could add throw if null
+ }
+
+ public async Task ExecuteResultAsync(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = (int)_responseMessage.StatusCode;
+
+ foreach (var header in _responseMessage.Headers)
+ {
+ context.HttpContext.Response.Headers.TryAdd(header.Key, new StringValues(header.Value.ToArray()));
+ }
+
+ context.HttpContext.Response.ContentType = _responseMessage.Content.Headers.ContentType.ToString();
+
+ using (var stream = await _responseMessage.Content.ReadAsStreamAsync())
+ {
+ await stream.CopyToAsync(context.HttpContext.Response.Body);
+ await context.HttpContext.Response.Body.FlushAsync();
+ }
+ }
}
[Route("api/[controller]/{*all}")]
[Route("graphproxy/{*all}")]
[HttpPatch]
- public async Task PatchAsync(string all, [FromBody] object body, [FromHeader] string Authorization)
+ [AuthorizeForScopes(Scopes = new[] { "https://graph.microsoft.com/.default" })]
+ public async Task PatchAsync(string all, [FromBody] object body)
+ {
+ return await ProcessRequestAsync("PATCH", all, body, _config.GetSection("AzureAd").GetSection("TenantId").Value).ConfigureAwait(false);
+ }
+
+ private async Task ProcessRequestAsync(string method, string all, object content, string tenantId)
{
- return await ProcessRequestAsync("PATCH", all, body, Authorization).ConfigureAwait(false);
+ GraphServiceClient _graphServiceClient = _graphClient.GetAuthenticatedGraphClient(GetTokenAsync(tenantId).Result.ToString());
+
+ var qs = HttpContext.Request.QueryString;
+
+ var url = $"{GetBaseUrlWithoutVersion(_graphServiceClient)}/{all}{qs.ToUriComponent()}";
+
+ var request = new BaseRequest(url, _graphServiceClient, null)
+ {
+ Method = method,
+ ContentType = HttpContext.Request.ContentType,
+ };
+
+ var neededHeaders = Request.Headers.Where(h => h.Key.ToLower() == "if-match" || h.Key.ToLower() == "consistencylevel").ToList();
+ if (neededHeaders.Count() > 0)
+ {
+ foreach (var header in neededHeaders)
+ {
+ request.Headers.Add(new HeaderOption(header.Key, string.Join(",", header.Value)));
+ }
+ }
+
+ var contentType = "application/json";
+ try
+ {
+ using (var response = await request.SendRequestAsync(content?.ToString(), CancellationToken.None, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false))
+ {
+ response.Content.Headers.TryGetValues("content-type", out var contentTypes);
+
+ contentType = contentTypes?.FirstOrDefault() ?? contentType;
+
+ var byteArrayContent = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
+ Console.WriteLine(byteArrayContent);
+ return new HttpResponseMessageResult(ReturnHttpResponseMessage(HttpStatusCode.OK, contentType, new ByteArrayContent(byteArrayContent)));
+ }
+ }
+ catch (ServiceException ex)
+ {
+ return new HttpResponseMessageResult(ReturnHttpResponseMessage(ex.StatusCode, contentType, new StringContent(ex.Error.ToString())));
+ }
}
- private async Task ProcessRequestAsync(string method, string all, object content, string Authorizaton)
+ private static HttpResponseMessage ReturnHttpResponseMessage(HttpStatusCode httpStatusCode, string contentType, HttpContent httpContent)
{
-
- return Ok();
+ var httpResponseMessage = new HttpResponseMessage(httpStatusCode)
+ {
+ Content = httpContent
+ };
+
+ try
+ {
+ httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
+ }
+ catch
+ {
+ httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
+ }
+
+ return httpResponseMessage;
}
}
}
diff --git a/GraphWebApi/GraphWebApi.csproj b/GraphWebApi/GraphWebApi.csproj
index 99e0191a5..20b3fd145 100644
--- a/GraphWebApi/GraphWebApi.csproj
+++ b/GraphWebApi/GraphWebApi.csproj
@@ -49,10 +49,12 @@
+
+
diff --git a/GraphWebApi/Startup.cs b/GraphWebApi/Startup.cs
index f14f69a6d..342d1aab5 100644
--- a/GraphWebApi/Startup.cs
+++ b/GraphWebApi/Startup.cs
@@ -30,6 +30,8 @@
using System.Threading.Tasks;
using Microsoft.Identity.Web;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
+using GraphExplorerAppModeService.Services;
+using GraphExplorerAppModeService.Interfaces;
namespace GraphWebApi
{
@@ -51,6 +53,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
+ .AddMicrosoftGraph(Configuration.GetSection("GraphV1"))
.AddInMemoryTokenCaches();
services.AddDistributedMemoryCache();
services.AddAuthentication(option =>
@@ -103,6 +106,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddMemoryCache();
services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();