Skip to content

Commit

Permalink
Add graph & api call to worker2 (#901)
Browse files Browse the repository at this point in the history
* initial commit to add graph & api call to worker2

* remove renamed file

* more updates to worker2

* update test templates

* fix usings

* one more using

* move api calls to greeterService

* fix variable name

* remove space

* fix helloReply
  • Loading branch information
jennyf19 authored Jan 25, 2021
1 parent 9bc1a37 commit 00086af
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,19 @@
"shortName": ""
},
"ExcludeLaunchSettings": {
"longName": "exclude-launch-settings",
"longName": "exclude-launch-settings",
"shortName": ""
},
"CalledApiUrl": {
"longName": "called-api-url",
"shortName": ""
},
"CalledApiScopes": {
"longName": "called-api-scopes",
"shortName": ""
},
"CallsMicrosoftGraph": {
"longName": "calls-graph",
"shortName": ""
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,41 @@
}
},
"skipRestore": {
"type": "parameter",
"datatype": "bool",
"description": "If specified, skips the automatic restore of the project on create.",
"defaultValue": "false"
},
"CalledApiUrl": {
"type": "parameter",
"datatype": "string",
"replaces": "[WebApiUrl]",
"defaultValue": "https://graph.microsoft.com/v1.0",
"description": "URL of the API to call from the web app. This option only applies if --auth SingleOrg or --auth IndividualB2C is specified."
},
"CallsMicrosoftGraph": {
"type": "parameter",
"datatype": "bool",
"description": "If specified, skips the automatic restore of the project on create.",
"defaultValue": "false"
"defaultValue": "false",
"description": "Specifies if the web app calls Microsoft Graph. This option only applies if --auth SingleOrg is specified."
},
"CalledApiScopes": {
"type": "parameter",
"datatype": "string",
"replaces": "user.read",
"description": "Scopes to request to call the API from the web app. This option only applies if --auth SingleOrg or --auth IndividualB2C is specified."
},
"GenerateApi": {
"type": "computed",
"value": "((IndividualB2CAuth || OrganizationalAuth) && (CalledApiUrl != \"https://graph.microsoft.com/v1.0\" || CalledApiScopes != \"user.read\"))"
},
"GenerateGraph": {
"type": "computed",
"value": "(OrganizationalAuth && CallsMicrosoftGraph)"
},
"GenerateApiOrGraph": {
"type": "computed",
"value": "(GenerateApi || GenerateGraph)"
}
},
"primaryOutputs": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.32.0" />
<!--<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0-0" />-->
<PackageReference Include="Microsoft.Identity.Web" Version="1.*" />
<!--#if (GenerateGraph) -->
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="1.*" />
<!--#endif -->
</ItemGroup>
</Project>
81 changes: 76 additions & 5 deletions ProjectTemplates/templates/Worker-CSharp/GreeterService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@
using Grpc.Core;
#if (!NoAuth)
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
#endif
#if (GenerateApi)
using Microsoft.Extensions.Configuration;
using Microsoft.Identity.Web;
using System.Net;
using System.Net.Http;
#endif
#if (GenerateGraph)
using Microsoft.Graph;
#endif
using Microsoft.Extensions.Logging;
#if (OrganizationalAuth || IndividualB2CAuth)
#if (!NoAuth)
using Microsoft.Identity.Web.Resource;
#endif

Expand All @@ -13,26 +23,87 @@ namespace Company.Application1
public class GreeterService : Greeter.GreeterBase
{
private readonly ILogger<GreeterService> _logger;
public GreeterService(ILogger<GreeterService> logger)

#if (!NoAuth)
// The web API will only accept tokens 1) for users, and 2) having the "api-scope" scope for this API
static readonly string[] scopeRequiredByApi = new string[] { "api-scope" };
#endif

#if (GenerateApi)
private readonly IDownstreamWebApi _downstreamWebApi;

public GreeterService(ILogger<GreeterService> logger,
IDownstreamWebApi downstreamWebApi)
{
_logger = logger;
_downstreamWebApi = downstreamWebApi;
}

static string[] scopeRequiredByAPI = new string[] { "access_as_user" };
[Authorize]
public override async Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
var httpContext = context.GetHttpContext();
httpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
using var response = await _downstreamWebApi.CallWebApiForUserAsync("DownstreamApi").ConfigureAwait(false);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var apiResult = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
// Do something with apiResult
}
else
{
var error = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new HttpRequestException($"Invalid status code in the HttpResponseMessage: {response.StatusCode}: {error}");
}

return new HelloReply()
{
Message = "Hello " + request.Name
};
}

#elseif (GenerateGraph)
private readonly GraphServiceClient _graphServiceClient;

public GreeterService(ILogger<GreeterService> logger,
GraphServiceClient graphServiceClient)
{
_logger = logger;
_graphServiceClient = graphServiceClient;
}

[Authorize]
public override async Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
var httpContext = context.GetHttpContext();
httpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
var user = await _graphServiceClient.Me.Request().GetAsync();

return new HelloReply()
{
Message = "Hello " + user.DisplayName
};
}
#else
public GreeterService(ILogger<GreeterService> logger)
{
_logger = logger;
}

#if (!NoAuth)
[Authorize]
#endif
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
#if (OrganizationalAuth || IndividualB2CAuth)
#if (!NoAuth)
var httpContext = context.GetHttpContext();
httpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByAPI);
httpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
#endif
return Task.FromResult(new HelloReply
{
Message = "Hello " + request.Name
});
}
#endif
}
}
27 changes: 23 additions & 4 deletions ProjectTemplates/templates/Worker-CSharp/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Http;
#if (GenerateGraph)
using Microsoft.Graph;
#endif

namespace Company.Application1
{
Expand All @@ -28,15 +31,31 @@ public void ConfigureServices(IServiceCollection services)

#if (OrganizationalAuth)
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
#if (GenerateApiOrGraph)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
#if (GenerateApi)
.AddDownstreamWebApi("DownstreamApi", Configuration.GetSection("DownstreamApi"))
#endif
#if (GenerateGraph)
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
#endif
.AddInMemoryTokenCaches();
#else
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));

services.AddAuthorization();
#endif
#elif (IndividualB2CAuth)
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
#if (GenerateApi)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamWebApi("DownstreamApi", Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
#else
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C"));

services.AddAuthorization();
#endif
#endif
services.AddAuthorization();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand Down
15 changes: 15 additions & 0 deletions ProjectTemplates/test-templates-from-nuget.bat
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,21 @@ cd worker2-b2c
dotnet new worker2 --auth IndividualB2C
dotnet sln ..\..\tests.sln add worker2-b2c.csproj
cd ..

echo "Test worker2, single-org, calling microsoft graph"
mkdir worker2-singleorg-callsgraph
cd worker2-singleorg-callsgraph
dotnet new worker2 --auth SingleOrg --calls-graph
dotnet sln ..\..\tests.sln add worker2-singleorg-callsgraph.csproj
cd ..

echo "Test worker2, single-org, calling a downstream web api"
mkdir worker2-singleorg-callswebapi
cd worker2-singleorg-callswebapi
dotnet new worker2 --auth SingleOrg --called-api-url "https://graph.microsoft.com/beta/me" --called-api-scopes "user.read"
dotnet sln ..\..\tests.sln add worker2-singleorg-callswebapi.csproj
cd ..

cd ..

echo "Configure the applications"
Expand Down
14 changes: 14 additions & 0 deletions ProjectTemplates/test-templates.bat
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,20 @@ dotnet new worker2 --auth IndividualB2C
dotnet sln ..\..\tests.sln add worker2-b2c.csproj
cd ..

echo "Test worker2, single-org, calling microsoft graph"
mkdir worker2-singleorg-callsgraph
cd worker2-singleorg-callsgraph
dotnet new worker2 --auth SingleOrg --calls-graph
dotnet sln ..\..\tests.sln add worker2-singleorg-callsgraph.csproj
cd ..

echo "Test worker2, single-org, calling a downstream web api"
mkdir worker2-singleorg-callswebapi
cd worker2-singleorg-callswebapi
dotnet new worker2 --auth SingleOrg --called-api-url "https://graph.microsoft.com/beta/me" --called-api-scopes "user.read"
dotnet sln ..\..\tests.sln add worker2-singleorg-callswebapi.csproj
cd ..

cd ..

echo "Configure the applications"
Expand Down

0 comments on commit 00086af

Please sign in to comment.