diff --git a/Microsoft.Identity.Web.sln b/Microsoft.Identity.Web.sln index d23238ab5..4b877583b 100644 --- a/Microsoft.Identity.Web.sln +++ b/Microsoft.Identity.Web.sln @@ -120,6 +120,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "grpc", "tests\WebAppCallsWe EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevApps", "DevApps", "{9A51E6E0-A2B0-4D4D-9209-E73B8AD2B9C6}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AzureFunctions", "AzureFunctions", "{2A2EB8D3-88F2-4FA2-8DDB-56B1F4755475}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleFunc", "tests\AzureFunctions\SampleFunc\SampleFunc.csproj", "{BE7E71AD-7272-4431-B50D-357C61CE2F8F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -266,6 +270,10 @@ Global {10260252-4899-44D1-94A1-5BF34746A698}.Debug|Any CPU.Build.0 = Debug|Any CPU {10260252-4899-44D1-94A1-5BF34746A698}.Release|Any CPU.ActiveCfg = Release|Any CPU {10260252-4899-44D1-94A1-5BF34746A698}.Release|Any CPU.Build.0 = Release|Any CPU + {BE7E71AD-7272-4431-B50D-357C61CE2F8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE7E71AD-7272-4431-B50D-357C61CE2F8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE7E71AD-7272-4431-B50D-357C61CE2F8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE7E71AD-7272-4431-B50D-357C61CE2F8F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -315,6 +323,8 @@ Global {8DC4213C-4C13-44AF-9A88-B53EEE2E9132} = {0E188C73-95E7-44D8-96F5-25AAF8BA1AE4} {10260252-4899-44D1-94A1-5BF34746A698} = {DA125992-5622-4D9D-B7AB-79CDC45A66B0} {9A51E6E0-A2B0-4D4D-9209-E73B8AD2B9C6} = {79310504-1334-4F14-93C4-1240913224BA} + {2A2EB8D3-88F2-4FA2-8DDB-56B1F4755475} = {9A51E6E0-A2B0-4D4D-9209-E73B8AD2B9C6} + {BE7E71AD-7272-4431-B50D-357C61CE2F8F} = {2A2EB8D3-88F2-4FA2-8DDB-56B1F4755475} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F4FA8C4C-3251-41CC-939B-7892F5798549} diff --git a/tests/AzureFunctions/SampleFunc.sln b/tests/AzureFunctions/SampleFunc.sln new file mode 100644 index 000000000..50e6b4d71 --- /dev/null +++ b/tests/AzureFunctions/SampleFunc.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.808.4 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleFunc", "SampleFunc\SampleFunc.csproj", "{C9A76FF7-5E35-4C96-AEFF-80F1B2EF7163}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C9A76FF7-5E35-4C96-AEFF-80F1B2EF7163}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9A76FF7-5E35-4C96-AEFF-80F1B2EF7163}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9A76FF7-5E35-4C96-AEFF-80F1B2EF7163}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9A76FF7-5E35-4C96-AEFF-80F1B2EF7163}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {10B2A9EB-3E1F-4A42-ABAD-13C93152FB67} + EndGlobalSection +EndGlobal diff --git a/tests/AzureFunctions/SampleFunc/SampleFunc.cs b/tests/AzureFunctions/SampleFunc/SampleFunc.cs new file mode 100644 index 000000000..9c853a820 --- /dev/null +++ b/tests/AzureFunctions/SampleFunc/SampleFunc.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.WebJobs; +using Microsoft.Azure.WebJobs.Extensions.Http; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Identity.Web; + +namespace SampleFunc +{ + public class SampleFunc + { + private readonly ITokenAcquisition _tokenAcquisition; + + public SampleFunc(ITokenAcquisition tokenAcquisition) + { + _tokenAcquisition = tokenAcquisition; + } + + [FunctionName("SampleFunc")] + public async Task Run( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, + ILogger log) + { + log.LogInformation("C# HTTP trigger function processed a request."); + + var (authenticationStatus, authenticationResponse) = + await req.HttpContext.AuthenticateAzureFunctionAsync(); + if (!authenticationStatus) return authenticationResponse; + + var token = await _tokenAcquisition.GetAccessTokenForAppAsync("https://graph.microsoft.com/.default" ); + + string name = req.HttpContext.User.Identity.IsAuthenticated ? req.HttpContext.User.Identity.Name : null; + + string responseMessage = string.IsNullOrEmpty(name) + ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response." + : $"Hello, {name}. This HTTP triggered function executed successfully."; + + return new OkObjectResult(responseMessage); + } + } +} diff --git a/tests/AzureFunctions/SampleFunc/SampleFunc.csproj b/tests/AzureFunctions/SampleFunc/SampleFunc.csproj new file mode 100644 index 000000000..9ac6ba265 --- /dev/null +++ b/tests/AzureFunctions/SampleFunc/SampleFunc.csproj @@ -0,0 +1,22 @@ + + + netcoreapp3.1 + v3 + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + \ No newline at end of file diff --git a/tests/AzureFunctions/SampleFunc/Startup.cs b/tests/AzureFunctions/SampleFunc/Startup.cs new file mode 100644 index 000000000..1d1b3a433 --- /dev/null +++ b/tests/AzureFunctions/SampleFunc/Startup.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Azure.Functions.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Identity.Web; + +[assembly: FunctionsStartup(typeof(SampleFunc.Startup))] + +namespace SampleFunc +{ + public class Startup : FunctionsStartup + { + public Startup() + { + } + + public override void Configure(IFunctionsHostBuilder builder) + { + // This is configuration from environment variables, settings.json etc. + var configuration = builder.GetContext().Configuration; + + builder.Services.AddAuthentication(sharedOptions => + { + sharedOptions.DefaultScheme = Constants.Bearer; + sharedOptions.DefaultChallengeScheme = Constants.Bearer; + }) + .AddMicrosoftIdentityWebApi(configuration) + .EnableTokenAcquisitionToCallDownstreamApi() + .AddInMemoryTokenCaches(); + } + } +} diff --git a/tests/AzureFunctions/SampleFunc/host.json b/tests/AzureFunctions/SampleFunc/host.json new file mode 100644 index 000000000..0b77e3716 --- /dev/null +++ b/tests/AzureFunctions/SampleFunc/host.json @@ -0,0 +1,11 @@ +{ + "logging": { + "applicationInsights": { + "samplingExcludedTypes": "Request", + "samplingSettings": { + "isEnabled": true + } + } + }, + "version": "2.0" +} diff --git a/tests/AzureFunctions/SampleFunc/local.settings.json.sample b/tests/AzureFunctions/SampleFunc/local.settings.json.sample new file mode 100644 index 000000000..421386dd2 --- /dev/null +++ b/tests/AzureFunctions/SampleFunc/local.settings.json.sample @@ -0,0 +1,13 @@ +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "FUNCTIONS_WORKER_RUNTIME": "dotnet", + "AzureAd:Instance": "https://login.microsoftonline.com/", + "AzureAd:Domain": ".onmicrosoft.com", + "AzureAd:TenantId": "", + "AzureAd:ClientId": "", + "AzureAd:ClientSecret": "", + "AzureAd:AllowWebApiToBeAuthorizedByACL": true + } +} \ No newline at end of file