azure oauth 2.0 how to protect web api from external organization web api? - azure

I am new to Azure and trying to protect/web api hosted in azure using oauth 2.0.
This web api will be called from other web api/deamon which is in control of other organization.
I am aware of client credential flow, but in this scenario external api is hosted outside azure ad. We have no idea of where it is hosted and how this third external web api/deamon is hosted? How should we do authentication/authorization for our web api, so that any external service can use it?

You know about client credential flow, then you should know that this kind of flow doesn't need a user to sign in to generate access token, but only need an azure ad application with the client secret. This azure ad application can come from your tenant, so it doesn't require the web api/deamon which is in control of other organization to have an application, you can create the app in your tenant then provide it to the external web api. What you need to make sure is that the external is really a daemon application.
Let's assume that the external app that need to call your api which is protected by azure ad is a daemon application, then client credential flow is suitable here.
Code for external api to generate access token
//you can see it when you add api permission
var scopes = new[] { "api://exposed_apis_app_id/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
// using Azure.Identity;
var options = new TokenCredentialOptions{AuthorityHost = AzureAuthorityHosts.AzurePublicCloud};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var tokenRequestContext = new TokenRequestContext(scopes);
var token = clientSecretCredential.GetTokenAsync(tokenRequestContext).Result.Token;
Code for your api to add authentication for azure ad, you still have some more configurations, you can refer to my this answer, some related document: authorize the token with role and jwt token configuration.
[Authorize]
public class HelloController : Controller
{
public IActionResult Index()
{
HttpContext.ValidateAppRole("User.Read");//You set it when adding app role
Student stu = new Student();
stu.age = 18;
return Json(stu) ;
}
}
appsettings:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "2c0xxxxxxx57",
"Domain": "tenantname.onmicrosoft.com", // for instance contoso.onmicrosoft.com. Not used in the ASP.NET core template
"TenantId": "common",
"Audience": "8fxxxx78"
}
startup.cs, don't forget "app.UseAuthentication();app.UseAuthorization();" in Configure method
public void ConfigureServices(IServiceCollection services)
{
services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
services.AddControllersWithViews();
}
create an azure ad application in your tenant and expose an api with a role.
you can create another azure ad application, add client secret and add the application permission created before in the API permissions blade.
provide the application id and client secret to those external app and let them use these to generate access token, then they can use the access token to call your api.
modify your api to authorize the token if has the correct role.

Related

OAUTH / Azure Functions: Method to auth AAD user for endpoints that don't support service principals

I've been leveraging Azure Function Apps to automate items in Azure. I currently have working functions that connect to Microsoft Graph, Resource Explorer, KV etc. using service principal / OAUTH client credentials flow (inside the function app). To call my function app, I've implemented implicit flow. While I'm not an expert at OAUTH, I am familiar enough now to get this configured and working.
However, there are Azure endpoints I need to use that don't support using a service principal token, they only support an actual AAD user requesting a token. Here's one that I want to run: Create synchronizationJob
If you look at the permissions section of the above link, you'll see that "application" is not supported. I did test this in a function: I can run these endpoints in Graph Explorer fine (as myself), but they fail in the function when using a token linked to a service principal.
Since this new automation is going to be an Azure Function (and not an interactive user), I can't use the authorization code flow. I need this service account's OAUTH to be non-interactive.
TL;DR
I can run the above endpoint in Azure's Graph Explorer just fine:
Azure Graph Explorer
since I'm authenticating as myself, and have a token generated based on my user ID. But for automating using Azure Functions where I need to use this endpoint (which doesn't support OAUTH using an SP), I need some way to have a back-end AAD user auth and pull a token that can be used to run the endpoint.
Any help is welcome! Feel free to tell me that I'm either missing something very basic, or not understanding a core principal here.
As juunas mentioned no guarantee that will work though, I test in my side and it seems doesn't work although I assigned "Global administrator" role to the service principal.
For your situation, you can request the access token in your function code and then use the access token to request the graph api.
Add the code like below in your function to get access token.
HttpClient client = new HttpClient();
var values = new Dictionary<string, string>
{
{ "client_id", "<your app client id>" },
{ "scope", "<scope>" },
{ "username", "<your user name>" },
{ "password", "<your password>" },
{ "grant_type", "password" },
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("https://login.microsoftonline.com/<your tenant id>/oauth2/v2.0/token", content);
var responseString = await response.Content.ReadAsStringAsync();
var obj = JObject.Parse(responseString);
var accessToken = (string)obj["access_token"];
And then use the access token got above to request graph api.

How to secure an Azure Function accessed by a Blazor Wasm app with Azure AD B2C?

Scenario: I have a Blazor wasm app secured with B2C Authentication that needs to call an HTTP triggered Azure function. What would be the best method to secure that Azure function so that only the Blazor app and/or authenticated users could call that function?
So far I know how to secure the Blazor app with B2C (obviously silly!) and I've also been able to add B2C auth to an Azure function and secure the calls by validating the jwt token. But it's not clear in my head how the two parts should jive together.
Should I expose an API in the app registration of the Azure Function in the B2C tenant? If so, how the Blazor app would make authenticated calls to the Azure function?
Or do I simply send the jwt token from the Blazor app through the http request headers of the Azure function call and then validate that token manually inside the function?
I've been reading a lot of different posts on the subject lately but I still can't figure out what's THE best solution to achieve it.
Any help/cues would be appreciated.
Thanks!
ps: I'm not interested in using the Azure API management since it's a little bit on the pricey side for a pretty simple app solution.
If you want to call Azure function projected by Azure AD B2C, please refer to the following steps
Configure Azure AD B2C for Azure function
Create Azure B2C app.
Web App/API : Yes
Allow Implicit Flow : Yes
Set Reply URL in B2C app: https://{function app url}/.auth/login/aad/callback
Set App ID URL in B2C App : https://{tennat}/{prefix}
Note down B2C apps Application ID.
Define API scope. Go to B2C app => Published scopes.
Get your B2C user flows/policy’s metadata URL. Note down this URL.
It can be obtained from Run User Flow page.
It’s format is like https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/v2.0/.well-known/openid-configuration?p={policy}.
Go to your functions => Authentication / Authorization.
Set following
App Service Authentication : On
Action to take when not authenticated : Login with Azure AD
Authentication providers : Azure AAD
Management Mode : Advanced
Client Id : {Application Id from Step 4}
Issuer URL : {URL from step 6}
Allowed Audience: {Application Id URL from Step 3}
Create Client application For more details, please refer to here.
Configure CORS policy in Azure Function
Configure Application
Create
dotnet new blazorwasm -au IndividualB2C --aad-b2c-instance "{AAD B2C INSTANCE}" --client-id "{CLIENT ID}" --domain "{TENANT DOMAIN}" -o {APP NAME} -ssp "{SIGN UP OR SIGN IN POLICY}"
Code
Create Custom AuthorizationMessageHandler class
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
NavigationManager navigationManager)
: base(provider, navigationManager)
{
ConfigureHandler(
authorizedUrls: new[] { "<your function app url>" },
scopes: new[] { "<the function app API scope your define>" });
}
}
Add the following code in Program.cs.
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
// register CustomAuthorizationMessageHandler
builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
// configure httpclient
// call the following code please add packageMicrosoft.Extensions.Http 3.1.0
builder.Services.AddHttpClient("ServerAPI", client =>
client.BaseAddress = new Uri("<your function app url>"))
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
// register the httpclient
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
.CreateClient("ServerAPI"));
// configure Azure AD auth
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add("<the function app API scope your define>");
});
await builder.Build().RunAsync();
}
Call the API
#page "/fetchdata"
#using Microsoft.AspNetCore.Components.WebAssembly.Authentication
#inject HttpClient Http
<h1>Call Azure Function</h1>
<p>This component demonstrates fetching data from the server.</p>
<p>Result: #forecasts</p>
<button class="btn btn-primary" #onclick="CallFun">Call Function</button>
#code {
private string forecasts;
protected async Task CallFun()
{
forecasts = await Http.GetStringAsync("api/http");
}
}

Azure B2C - Use msal to get authorization to call Graph API

I recently got started working with B2C. I managed to get their sample application/API using MSAL and an API working with my own tenant.
Now I wanted to:
Figure out how I can run this sample without using an API. The sample uses Scopes to get read/write access to the API. If I remove the references to the API from the app, it no longer works. Surely there should be some way to authenticate to B2C without requiring an API? This is not really important to my application but I'm mostly curious if the webservice HAS to be there as part of the auth-process?
Communicate with Graph Api (Windows or Microsoft Graph?). The sample MS provides uses ADAL and some console application. I cannot find a sample that uses MSAL, so I am having trouble incorporating it into my own application. Is it now possible to call Graph API using MSAL? If it is, is there some documentation on how to do this somewhere?
I tried simply following the docs above and registering an app/granting it permissions. Then putting the client ID/key into my own application (the MSAL one from the first sample), but then I just get a message from B2C that looks like:
Correlation ID: 01040e7b-846c-4f81-9a0f-ff515fd00398
Timestamp: 2018-01-30 10:55:37Z
AADB2C90068: The provided application with ID '9cd938c6-d3ed-4146-aee5-a661cd7d984b' is not valid against this service. Please use an application created via the B2C portal and try again.
It's true that it's not registered via the B2C portal, but that is what the instructions say; to register it in the B2C tenant under App Registrations, not the B2c portal.
The Startup class where all the magic happens looks like:
public partial class Startup
{
// App config settings
public static string ClientId = ConfigurationManager.AppSettings["ida:ClientId"];
public static string ClientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
public static string AadInstance = ConfigurationManager.AppSettings["ida:AadInstance"];
public static string Tenant = ConfigurationManager.AppSettings["ida:Tenant"];
public static string RedirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
public static string ServiceUrl = ConfigurationManager.AppSettings["api:TaskServiceUrl"];
public static string ApiIdentifier = ConfigurationManager.AppSettings["api:ApiIdentifier"];
public static string ReadTasksScope = ApiIdentifier + ConfigurationManager.AppSettings["api:ReadScope"];
public static string WriteTasksScope = ApiIdentifier + ConfigurationManager.AppSettings["api:WriteScope"];
public static string[] Scopes = new string[] { ReadTasksScope, WriteTasksScope };
// B2C policy identifiers
public static string SignUpSignInPolicyId = ConfigurationManager.AppSettings["ida:SignUpSignInPolicyId"];
public static string EditProfilePolicyId = ConfigurationManager.AppSettings["ida:EditProfilePolicyId"];
public static string ResetPasswordPolicyId = ConfigurationManager.AppSettings["ida:ResetPasswordPolicyId"];
public static string DefaultPolicy = SignUpSignInPolicyId;
// OWIN auth middleware constants
public const string ObjectIdElement = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
// Authorities
public static string Authority = String.Format(AadInstance, Tenant, DefaultPolicy);
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
// Generate the metadata address using the tenant and policy information
MetadataAddress = String.Format(AadInstance, Tenant, DefaultPolicy),
// These are standard OpenID Connect parameters, with values pulled from web.config
ClientId = ClientId,
RedirectUri = RedirectUri,
PostLogoutRedirectUri = RedirectUri,
// Specify the callbacks for each type of notifications
Notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
},
// Specify the claims to validate
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
},
// Specify the scope by appending all of the scopes requested into one string (seperated by a blank space)
Scope = $"{OpenIdConnectScopes.OpenId} {ReadTasksScope} {WriteTasksScope}"
}
);
}
/*
* On each call to Azure AD B2C, check if a policy (e.g. the profile edit or password reset policy) has been specified in the OWIN context.
* If so, use that policy when making the call. Also, don't request a code (since it won't be needed).
*/
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
var policy = notification.OwinContext.Get<string>("Policy");
if (!string.IsNullOrEmpty(policy) && !policy.Equals(DefaultPolicy))
{
notification.ProtocolMessage.Scope = OpenIdConnectScopes.OpenId;
notification.ProtocolMessage.ResponseType = OpenIdConnectResponseTypes.IdToken;
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(), policy.ToLower());
}
return Task.FromResult(0);
}
/*
* Catch any failures received by the authentication middleware and handle appropriately
*/
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
notification.HandleResponse();
// Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in policy"
if (notification.ProtocolMessage.ErrorDescription != null && notification.ProtocolMessage.ErrorDescription.Contains("AADB2C90118"))
{
// If the user clicked the reset password link, redirect to the reset password route
notification.Response.Redirect("/Account/ResetPassword");
}
else if (notification.Exception.Message == "access_denied")
{
notification.Response.Redirect("/");
}
else
{
notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message);
}
return Task.FromResult(0);
}
/*
* Callback function when an authorization code is received
*/
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
// Extract the code from the response notification
var code = notification.Code;
string signedInUserID = notification.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(ClientId, Authority, RedirectUri, new ClientCredential(ClientSecret), userTokenCache, null);
try
{
AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, Scopes);
}
catch (Exception ex)
{
//TODO: Handle
throw;
}
}
}
With regards to #2, you can only use the Azure AD Graph API with an Azure AD B2C directory, as noted in the "Azure AD B2C: Use the Azure AD Graph API" article.
Here is how (which I have copied from a previous answer)...
Azure AD B2C issues tokens using the Azure AD v2.0 endpoint:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
The Azure AD Graph API requires tokens that are issued using the Azure AD v1.0 endpoint:
https://login.microsoftonline.com/{tenant}/oauth2/token
At design-time:
Register the web application using the Azure AD B2C portal.
Register the web application using the Azure AD portal and grant the Read directory data permission.
At runtime:
The web application redirects the end user to the Azure AD B2C v2.0 endpoint for sign-in. Azure AD B2C issues an ID token containing the user identifier.
The web application acquires an access token from the Azure AD v1.0 endpoint using the application credentials that were created at design-time in step 2.
The web application invokes the Azure AD Graph API, passing the user identifier that was received in step 1, with the access token that was issued in step 2, and queries the user object, etc.
This answer is just addressing question #1, I am unsure on #2 other than it is not publicly documented as far as I know.
B2C does not require you to use an API/service when building your app. In the sample you're looking at it's using 2 libraries to do slightly different (but related) things.
First, it's using an OWIN middleware module to help facilitate the authentication piece. This helps your app identify who a user is, but does not authorize your app to do perform actions or access data on their behalf. This library will net you a session with the end user and basic information about them as well as a authorization code you can use later on.
The other library being used is MSAL. MSAL is a client library for token acquisition and management. In this case after the initial authentication takes place using the aforementioned middleware, MSAL will use the authorization code to get access and refresh tokens that your app can use to call APIs. This is able to take place without end user interaction because they would have already consented to the app (and you would've configured the permissions your app needed). MSAL then manages the refresh and caching of these tokens, and makes them accessible via AcquireTokenSilent().
In order to remove the API functionality from the sample app, you'd need to do a bit more than just remove the scope. Specifically, eliminating the code in the TaskController.cs that is trying to call APIs, remove most usage of MSAL, and likely a few more things. This sample implements a Web App only architecture (Warning: it's for Azure AD not Azure AD B2C. The code is very similar, but would require a bit of modification).

Authenticating as a Service with Azure AD B2C

We have setup our application using Azure AD B2C and OAuth, this works fine, however I am trying to authenticate as a service in order to make service to service calls. I am slightly new to this, but I have followed some courses on Pluralsight on how to do this on "normal" Azure Active Directory and I can get it to work, but following the same principles with B2C does not work.
I have this quick console app:
class Program
{
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; //APIClient ApplicationId
private static string appKey = ConfigurationManager.AppSettings["ida:appKey"]; //APIClient Secret
private static string aadInstance = ConfigurationManager.AppSettings["ida:aadInstance"]; //https://login.microsoftonline.com/{0}
private static string tenant = ConfigurationManager.AppSettings["ida:tenant"]; //B2C Tenant
private static string serviceResourceId = ConfigurationManager.AppSettings["ida:serviceResourceID"]; //APP Id URI For API
private static string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
private static AuthenticationContext authContext = new AuthenticationContext(authority);
private static ClientCredential clientCredential = new ClientCredential(clientId, appKey);
static void Main(string[] args)
{
AuthenticationResult result = authContext.AcquireToken(serviceResourceId, clientCredential);
Console.WriteLine("Authenticated succesfully.. making HTTPS call..");
string serviceBaseAddress = "https://localhost:44300/";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = httpClient.GetAsync(serviceBaseAddress + "api/location?cityName=dc").Result;
if (response.IsSuccessStatusCode)
{
string r = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(r);
}
}
}
And the service is secured like this:
private void ConfigureAuth(IAppBuilder app)
{
var azureADBearerAuthOptions = new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
}
};
app.UseWindowsAzureActiveDirectoryBearerAuthentication(azureADBearerAuthOptions);
}
In my B2C tenant I have two different applications that are pretty much setup as this:
Both applications have been setup with secrets coming from the "keys" option. The keys generated are slightly differently structured than when using Azure Active Directory.
I can successfully get a token, but I get 401 when trying to connect to the other service. Do I have to do something different on the authorization side when using B2C compared to Azure Active Directory?
Azure Active Directory B2C can issue access tokens for access by a web or native app to an API app if:
Both of these apps are registered with B2C; and
The access token is issued as result of an interactive user flow (i.e. the authorization code or implicit flows).
Currently, your specific scenario -- where you are needing an access token to be issued for access by a daemon or server app to the API app (i.e. the client credentials flow) -- isn't supported, however you can register both of these apps through the “App Registrations” blade for the B2C tenant.
You can upvote support for the client credentials flow by B2C at:
https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/18529918-aadb2c-support-oauth-2-0-client-credential-flow
If the API app is to receive tokens from both the web/native app as well as the daemon/server app, then you will have to configure the API app to validate tokens from two token issuers: one being B2C and other being the Azure AD directory in your B2C tenant.
I found the following very clear article from Microsoft which explains how to set up a "service account" / application which has management access to a B2C tenant. For me, that was the use case for which I wanted to "Authenticating as a Service with Azure AD B2C".
It is possible that having management access to a B2C tenant doesn't allow you access a protected resource for which your B2C tenant is the Authorization server (I haven't tried that), so the OP's use case may be slightly different but it feels very close.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-graph-dotnet
For automated, continuous tasks, you should use some type of service account that you provide with the necessary privileges to perform management tasks. In Azure AD, you can do this by registering an application and authenticating to Azure AD. This is done by using an Application ID that uses the OAuth 2.0 client credentials grant. In this case, the application acts as itself, not as a user, to call the Graph API.
In this article, we'll discuss how to perform the automated-use case. To demonstrate, we'll build a .NET 4.5 B2CGraphClient that performs user create, read, update, and delete (CRUD) operations. The client will have a Windows command-line interface (CLI) that allows you to invoke various methods. However, the code is written to behave in a noninteractive, automated fashion.

Azure active directory v2.0 query for Web API integration on a SharePoint site

We have a SharePoint publishing site with anonymous access hosted on the internet. As per out latest requirements, we need to implement user login (AzureAD, Microsoft personal and work accounts, and more).
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-flows
As per the documentation here, we want to implement this using Web API to get the secure information from the database. We are thinking about using MSAL.js file for user login and logout on the SharePoint and after getting a bearer token we can call the Web API for the additional data from our database.
Standalone Web APIs restriction: “You can use the v2.0 endpoint to build a Web API that is secured with OAuth 2.0. However, that Web API can receive tokens only from an application that has the same Application ID. You cannot access a Web API from a client that has a different Application ID. The client won't be able to request or obtain permissions to your Web API.”
How can we create two applications with same application ID at App Registration Portal? Or should we use the same application ID at SharePoint and Web API’s end?
There is no need to register two application, you only need to one register application. After you register the application, you can using the MSAL library below to get the token to call the web API:
<script class="pre">
var userAgentApplication = new Msal.UserAgentApplication("e5e5f2d3-4f6a-461d-b515-efd11d50c338", null, function (errorDes, token, error, tokenType) {
// this callback is called after loginRedirect OR acquireTokenRedirect (not used for loginPopup/aquireTokenPopup)
})
userAgentApplication.loginPopup(["user.read"]).then(function (token) {
var user = userAgentApplication.getUser();
console.log(token);
// signin successful
}, function (error) {
// handle error
});
</script>
And to protect the web API, you can use the same app and refer the code below:
public void ConfigureAuth(IAppBuilder app)
{
var tvps = new TokenValidationParameters
{
// The web app and the service are sharing the same clientId
ValidAudience = "e5e5f2d3-4f6a-461d-b515-efd11d50c338",
ValidateIssuer = false,
};
// NOTE: The usual WindowsAzureActiveDirectoryBearerAuthenticaitonMiddleware uses a
// metadata endpoint which is not supported by the v2.0 endpoint. Instead, this
// OpenIdConenctCachingSecurityTokenProvider can be used to fetch & use the OpenIdConnect
// metadata document.
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AccessTokenFormat = new JwtFormat(tvps, new OpenIdConnectCachingSecurityTokenProvider("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration")),
});
}

Resources