Azure AD User info with JWT Bearer token and ASP.NET Core 2 WebApi - asp.net-core

I found a tutorial where I can sign in to my application with Azure AD credentials.
In my frontend I'm using Xamarin.Forms.
In my backend I'm using ASP.NET Core 2.0 WebApi.
Backend:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAD:Tenant"]);
options.Audience = Configuration["AzureAd:Audience"];
});
}
It's pretty simple.
In my frontend I'm filling in my credentials and asking for a access_token.
{
"token_type": "Bearer",
"scope": "user_impersonation",
"expires_in": "3600",
"ext_expires_in": "0",
"expires_on": "1507104075",
"not_before": "1507100175",
"resource": "my_resource",
"access_token": "my_access_token",
"refresh_token": "my_refresh_token"
}
The access_token i'm filling in the headers with Authorization set with bearer my_access_token.
My Api know's all my information because it will automaticly set claims with the info from my access_token. This info is provided by Azure AD. (fullname, firstname, lastname, ...)
But how can I get this information in my frontend?

You might want to check out the active-directory-dotnet-native-desktop sample on GitHub.
I shows how to use ADAL.NET in a desktop app, to get a token for a service. you will need to adapt it for your Xamarin forms client, but the principle is the same as far as authentication is concerned.
Also it contains a service and you would replace it by your own service and get a token for your web API by changing the resource ID to be the one of your application created using the ASP.NET wizard (you'll find it in the Azure portal as described in the readme.md of the sample)
the idea is that you first get a token using ADAL.Net line 92 of TodoListClient/MainWindow.xaml.cs
result = await authContext.AcquireTokenAsync(todoListResourceId, clientId, redirectUri, ...)
and then you use it as a bearer token line 121
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);

If all the info you required is include in the access token, you can just decode the access token on the client. The access token is a JWT, it is easy to research code sample to decode the access token like following threads:
How to decode JWT Token?
Decoding and verifying JWT token using System.IdentityModel.Tokens.Jwt
And if you also require more user info, you can refresh the access token for the Microsoft Graph, and call the me endpoint of Microsoft Graph(refer here). And below is the document about how to refresh the access token via refresh token:
Refreshing the access tokens

Related

How to configure Azure AD authentication in Hybrid ASP.NET Core MVC (backend) and Vuejs SPA (frontend)?

My application is a hybrid approach where use ASP.NET Core MVC as my backend. I have various controllers which my front end uses to pull data from our database and also to do API calls on MS Graph. I am using the following program.cs file to get the authentication initiated when a user first logs on to the site:
//authentication pipline
builder.Services.AddHttpContextAccessor();
var initialScopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
builder.Configuration.Bind("AzureAd", options);
options.Events = new OpenIdConnectEvents
{
//Tap into this event to add a UserID Claim to a new HttpContext identity
OnTokenValidated = context =>
{
//This query returns the UserID from the DB by sending the email address in the claim from Azure AD
string query = "select dbo.A2F_0013_ReturnUserIDForEmail(#Email) as UserID";
string connectionString = builder.Configuration.GetValue<string>("ConnectionStrings:DBContext");
string signInEmailAddress = context.Principal.FindFirstValue("preferred_username");
using (var connection = new SqlConnection(connectionString))
{
var queryResult = connection.QueryFirst(query, new { Email = signInEmailAddress });
var claims = new List<Claim>
{
new Claim("UserID", queryResult.UserID.ToString())
};
var appIdentity = new ClaimsIdentity(claims);
context.Principal.AddIdentity(appIdentity);
}
return Task.CompletedTask;
},
};
}).EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
//Add Transient Services
builder.Services.AddTransient<IOneDrive, OneDrive>();
builder.Services.AddControllers(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();
builder.Services.AddRazorPages().AddRazorPagesOptions(options =>
{
options.Conventions.AllowAnonymousToFolder("/Login");
options.Conventions.AuthorizeFolder("/");
options.Conventions.AuthorizeFolder("/files");
}).AddMicrosoftIdentityUI();
// Add the UI support to handle claims challenges
builder.Services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
builder.Services.AddRequiredScopeAuthorization();
In the Azure AD portal my application is registered as a web app. So when a user initially goes to the site they are redirected to https://login.microsoftonline.com/blahblah to get the login process started. This is automated by the Azure AD identity platform. Then once the login occurs they are redirected to localhost where the VueJS spa is loaded (localhost:43862). My spa uses various axios requests to the controllers and they pull data and vue router loads components. However, my issue is say the user needs to relog in because the cookie is expired or they logged out in another tab. The next axios request made by the expired session does not redirect the user to Azure login screen but instead results in an CORS error. So I need to get my axios requests to force the page redirect to Azure AD login screen (which probably is the worst idea since CORS policy is resulting in error) or have it return a redirect to localhost/login which is my own custom login screen with a button to Azure AD login and shouldnt impact CORS. So how do I intercept this Azure AD redirect to Azure AD login and replace with my own?
I have also tried to return a 401 error code so I could check for that in my axios request but to no avail it does nothing. If I put a breakpoint there it does hit this code but it does not change the status code of the response and I still get 302. My code for that was to try and add to the event :
OnRedirectToIdentityProvider = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
}
My other ideas was maybe I should set my CORS policy to allow redirects from login.microsoft.com? Or would this be bad practice?
I can answer part of your question... First, for our API application which is protected by Azure AD, what the API should do is validating the request whether it contained a correct access token in the request header, if yes, give the response, if no, then give error like 401 or 403. A normal API application shouldn't have a UI to let users sign in. Anyway, if you want to expose an API in an MVC project, it's OK, but for API itself, it shouldn't have a UI.
Let's see sample below, I had a .net 6 web api project, and here's my program.cs:
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration);
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
And it requires configurations in appsetting.json.
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "azure_ad_client_id",
"ClientSecret": "client_secret",
"Domain": "tenant_id",
"TenantId": "tenant_id",
//"Audience": "api://azure_ad_client_id_which exposed_api" // here I used the same azure ad app to expose API, so I can comment this property
},
And this is the Controller:
[ApiController]
[Route("[controller]")]
[Authorize]
public class WeatherForecastController : ControllerBase
{
[RequiredScope("Tiny.Read")]
[HttpGet]
public string Get()
{
return "world";
}
}
I had an Azure AD app, and I exposed an API like this:
I also add this API for the same Azure AD app.
Then let's do a test. When I call this API directly, I will get 401 error:
If I used an expired token within the request, I will also get 401 error:
But if I used a correct token(go to https://jwt.io to decode the token, we should see it containing correct scope, for me its "scp": "Tiny.Read",), I will get response:
And till now, the API part had finished. Let's see the client SPA. For SPA, you should integrate MSAL so that you can make your users to sign in via Azure AD, and generate the access token for calling MS graph API or your own API. The code for generating access token should be the same but you should set different scope for different API. In my scenario, my API required a scope Tiny.Read, then I should set in my client App.
Here's an screenshot for generating access token in react. You need to set the scope in your code.
Now you have the method to generate access token, you already know the API url. Then you can send request to call api, using AJAX, using fetch, or something else, sending an http request is ok. And in the calling api part, you also need to handle the response. If the response code is 401, then you need to do some logic, maybe redirect to the sign in page. And you said you had trouble here, you met CORS issue. I can't answer this part. I think it depends on how you redirect to Azure AD sign in page. I'm afraid you can take a look at this sample to learn how to sign in users and call graph api.

OpenIddict - ASP.NET Core Client - ROPC

I am trying to implement an architecture formed by
.NET Core MVC client
Auth Server with OpenIdDict
Regarding the Auth Server I should have implemented a Resource Owner Password Credentials Grant: the token endpoint authenticates the user, creates a principal and releases
access_token
refresh_token
id_token
each with claims with appropriately set destinations
The problem is the client. Wanting to implement a ROPC client, the web application must
call the token endpoint
fetch the access_token
Build a Principal cookie with related claims
How can I build a cookie with claims inside?
How do I recover the claims? The access_token is encrypted. How can I use the id_token to retrieve the claims and put them inside the cookie?
Edit:
Here the code that generate the tokens
if (request.IsPasswordGrantType())
{
var user = await _userService.FindUserByUserNameOrEmail(request.Username);
if (user == null)
return GetForbidResponse("Account non trovato.");
// Validate the username/password parameters
bool pwdCheck = await _userService.CheckUserPassword(user, request.Password);
if (!pwdCheck)
return GetForbidResponse("Password non valida.");
//Create the principal
var principal = CreateUserPrincipal(user);
//Set Scopes
SetPrincipalScopes(principal, request);
return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
And this is an example of response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhGN0EwMTI2Nzc3QzkxMDE5QTk2NEE2NDhERUE0RTAwOUQ5QkNFRUMiLCJ4NXQiOiJqM29CSm5kOGtRR2Fsa3BramVwT0FKMmJ6dXciLCJ0eXAiOiJhdCtqd3QifQ.eyJuYW1lIjoicHN5Y2hvODciLCJlbWFpbCI6ImRhdmlkZS5tYWdnaXVsbGlAZ21haWwuY29tIiwic3ViIjoiMTk1MiIsInJvbGUiOlsiVXNlciIsIlN5c0FkbWluIl0sIm9pX2F1X2lkIjoiNiIsIm9pX3Rrbl9pZCI6IjI2Iiwic2NvcGUiOiJvcGVuaWQgb2ZmbGluZV9hY2Nlc3MiLCJleHAiOjE2NDgxNDgzMjgsImlzcyI6Imh0dHBzOi8vbG9jYWxob3N0OjUwMDEvIiwiaWF0IjoxNjQ4MTQ0NzI4fQ.nCcIbLpYDCNi093uPYHH1KA7-1StRm8G4QLRp_MeEO3ixHP2syoL_nSmkwUrv2_NHrNLzbzTgn4SSaKZTVvKHbOXs89s2S3-vJD62DnB_bc2M--z2V-4txerwTK4Q1zGwV28YtJgG_lLR-KBYvi4DQPqBH0FDAy9DF72P7gmEb_xkeUTmSvzQ3MklyuYNK6youI-y5R0x_0QEFWwkpGYnHTEIj_RmaEvz3Nz3Ic_vhwOnjCOMpAE7KLO7cYT2xFiNKwbIDfsnmHnzaFhUMdzpPsvk-VyGTu35kB4ME6mQnPObWktzncdZu1wXVoYYs3NQdRzTxxJkC0Zw0YPr4jpUA",
"token_type": "Bearer",
"expires_in": 3599,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhGN0EwMTI2Nzc3QzkxMDE5QTk2NEE2NDhERUE0RTAwOUQ5QkNFRUMiLCJ4NXQiOiJqM29CSm5kOGtRR2Fsa3BramVwT0FKMmJ6dXciLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiIxOTUyIiwib2lfYXVfaWQiOiI2IiwiYXRfaGFzaCI6ImNrN2dSdnhBcnZlN3k2emd0ZWZlZ3ciLCJvaV90a25faWQiOiIyOCIsImV4cCI6MTY0ODE0NTkyOCwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NTAwMS8iLCJpYXQiOjE2NDgxNDQ3Mjh9.iFsE4eWiSfvpzTRHFWCtX-HiHXaWJ9UO7cQdTT2u-Md87jLTSB66mmBECLdYWEYFKCi-RyX3ZKAjpoW5Le2OeFsE-wqXxDaEeCIQ9t0nz1lVzdJVHq4RcaiwR1nSEkmOkAD74OzPGj7Vj3BOppUxtXHQG4ZAFCk9CxCQD2yfMwYxikvqAktslwMWoopJtMiig9KnQuhpGIGVAGaucYH2hGgswcYJQwKuN58iFEe3WC0EiNmYG1JRPWIHUukO4bVqwEZVNFSayaMfFLg3BZOvdQ3Eua60P2SYnGJcNAXYA_C571wazZN4AQdnuGHnLhud4NpwceQDrKF1tRe7uTDMxA",
"refresh_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZDQkMtSFM1MTIiLCJraWQiOiJDQ0QwNEJCQTg0RkUxMUE3Nzc1RjAyQjgyNEQ5OEFGNjhEREQ4MEEwIiwidHlwIjoib2lfcmVmdCtqd3QifQ.KH_P3P_DfJmbHKKdqFh2rWaItAubi00dGOkYlyIUg2twzhwAepEvwrEwwk6WVzKv1XwXCBBRqz_Bgub0ks29TauUhYfpew1d6ZPS6C4WQCehcxLsA0LmD8HADvIuW-zhTOSIqP-JdZxaWCZ_jfi61FjjmO5y4iGKXADupid4kSW7CzuBDTscPMNQFs7u6RuCxEXAwtS35vqBR81jmZe-R7b8P87hT-jDef9H_syrzaiBDFBr_-QFN7xbIdOkmvLs4upeB07knj_JoB1V9vUOL9B3CNGT-0BKrU3HHxt2b05kx4YWIsdV7kHx3191HNZh_PkouyZrt9geLcT-dTlMXA.8g0Dk4t6w7rzEarhSPN3EA.yzAcqs3GblO9hlHBZ46-loYrkwE4iqH7qxCNjS0hTO9mGHyDPBuHmiVO2oC6w8btWJkTHU20DEtCiEA1162Lk8I3oezWbyCmXXYRW1Z-HE8waTPBUvm6hcyn6RF6ey9wzG-Qn2TOAOdq8jIxXMUueM1k4UVGhvPjeY6v4FhaNdJFv4l8XvwO9jmoBRGp0uL8n_07RYlY6tyb59CIVLiSvsA_-hDYlimVEUABa27AjQNKj-3ZwWr7JRAD7TPL0Ghbtr7eWNkQrf1zrZ99kIdtxpdAUaRMGCES-qiisbuW3g3b6RwRsE97JW5BBGqs552hZ4fLf1nVHU9U6J4MLrbKWxmCmX8DH3J0y9w0mj2Exa3wUHD7AId1FD2UEdR6y86zxfa7qrfvGXeAbIVtGAPXwcnnUT-M7HtqcHgO-AtJV1Xarpe8C7vDzlRbDGGWIpcUGbD6xWQPe-sTv1jqDcxZ3CX8naKkoojohGzZCUm6IIb_ADdsmuvcVFGuHdOcqc27QDukS_x9V4x1w918Lqi0rR1vBqgAuEPffowAUvDJJIWZPb9Q8JeyE2AF8cENp3HTGNhOweHiQkdtS836_WXA_R8A2bQU2R-hXWJpk56hlN9jZ--F6H1NcO3997SSeVHWQ1YUdzuju7j4HyGxOLx3yB0QpJplG8NGfZfSB2xq-Wi2qB6mW7edj4mL1PlBxGcrphxXeyd14WAMejsKQYueD-t1lt80NmRnkqvqtPARQHTjDcKfHLSbuFddQzlc5UCgQC97bIkM8WUgWTqH8rVNRe6gzQFVID4YxSZvs-aaCtJx0xDWaPTlyceRkaNBOuh4PGDtjRLSpcoh3EtdYL39PatbOM4-2FazY5z5r1rIYaXJ4NmAanH8GwV098TmH1sPQppsxrotKX9T5OqQxucdE2wAyrGCZM4ToyetP2SoJJCcisGU1mMy5Iv26TX9N1Wonu8URGBuhDGAd0GnR2ijX1xe6EEGaTWxUaKb5m8xfByIbXarb1TV2CB8XTwdCy3G_Y5QJQw5k88S7cnTZ4Lq5saPNIvFPhGPuxgrrCFcvP1SshMLHnge5p2mqiIKGTvK1ypZeqOdMVeQeo5HvFHoLTcntPO1n07BbL2K2q9Gq3Vvx5o-jq0cfB6lC63xImII2HrpS053Mng4daU-QIKUkaKsbEflYWVyOzBe6AgNcqHRZ3zxzZRaXn8mVuGz6YjgZE4xeS6M5e0XKlSAae-sPtr6c8sEvhBQ0tHTAWdsSk-OkuLp1f6likr4BvZwwkjgC-sYPqCiCg85npvcf28qZbh1Rs85g-g9FoRfIKljU2gyTAA1MPAx8f6EMhpBaQIi.quAj1ZNggBenfSMNmyKbvKuX_lTD_YFd6viyODV_Ugw"
}
Thank you all

401 with bearer token only auth in .NET Core 3.1 using Azure AD

I'm trying to implement Bearer token (only) authentication in a .NET Core 3.1 API, using Azure AD.
I'm able to retrieve a token from Azure AD after verifying the authorization_code and the browser posts back to my redirect URL with the following:
{"token_type":"Bearer","scope":"User.Read","expires_in":3600,"ext_expires_in":3600,"access_token":"EwBwA8l6...SzT3qoxGbSMg=="} (shortened)
Once I have this token, should I be able to use the [Authorize] attribute directly on my APIs and request using a Bearer token in the header? When I do, I get a 401 response.
I have this in my ConfigureServices():
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = "<guid>";
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuerSigningKey = false,
ValidateAudience = false,
ValidateIssuer = false,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abc123")),
TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abc123"))
};
});
services.AddControllers();
And in Configure() I have:
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
In my error log, the message I'm seeing is:
"Bearer" was not authenticated. Failure message: "No SecurityTokenValidator available for token
I've tried many, many combinations of settings in Startup.cs, and no matter what I can only seem to get a 401 when calling my API from Postman. I'm able to get Cookie authentication working with code samples I've found online, but I don't want that.
Is the issue that the token is encrypted? Am I trying to use the wrong token? Or is there some other issue? Do I need to have identity set up in my app with database tables for AspNetUser, etc.?
In short, I'm just trying to generate a Bearer token using Azure AD as the auth provider, and make calls to my APIs by passing in a Bearer token header.
Looks a bit like you are trying to use a Microsoft Graph API token in your API. (based on this: "scope":"User.Read")
Your front-end app needs to use a scope for your API, not User.Read.
This way it will get an access token which is meant for your API.
Register a scope on your API app registration through the Expose an API section and use the full scope value in your front-end when acquiring the token.
Your back-end needs the following config:
.AddJwtBearer(options =>
{
// add v2.0 to the end if your API is set to get v2 tokens in its manifest
options.Authority = "https://login.microsoftonline.com/your-aad-tenant-id";
options.Audience = "your-api-client-id";
});
This should be the minimum configuration needed for authentication.
It'll look up signing keys etc. automatically from the authority at startup.

.Net core api with AD B2C OAuth 2.0 - Invalid_token error

I am following this resource. I can get the token successfully but get 401 upon using the token in the second call to my api. It says Bearer error='invalid_token'. Earlier it was giving "Invalid issuer" so I decoded the token to use the issuer in "Instance" field of appSettings.json. Following are appSettings and token. What am I doing wrong?
appSettings.json
{
"AzureAdB2C": {
"Instance": "https://login.microsoftonline.com/xxxxxxxxxxxxxxxxxxxxx/v2.0/",
"ClientId": "452gfsgsdfgsdgssfs5425234",
"Domain": "xxxxxxxxxxxxxxx.onmicrosoft.com",
"SignUpSignInPolicyId": "B2C_1_Auth-SignUpIn"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
token
{
"iss": "https://login.microsoftonline.com/23423fsf234234sfsd42342vsx2542/v2.0/",
"exp": 1551878022,
"nbf": 1551874422,
"aud": "ee965664-d1e3-4144-939a-11f77c523b50",
"oid": "a9ee8ebb-433d-424b-ae24-48c73ae9969c",
"sub": "a9ee8ebb-433d-424b-ae24-48c73ae9969c",
"name": "unknown",
"extension_xxxID": "9f27fd88-7faf-e411-80e6-005056851bfe",
"emails": [
"dfgdfgadfgadfg#dgadg.com"
],
"tfp": "B2C_1_Auth-SignUpIn",
"scp": "user_impersonation",
"azp": "4453gdfgdf53535bddhdh",
"ver": "1.0",
"iat": 1551874422
}
AD B2C instance
Azure AD B2C setting
Postman - revalapi highlighted is the uri of the registered app in the previous shot
Token
Error
Ok. Looks like AD B2C + .Net Core is not happy with onmicrosoft.com URI even though the Microsoft docs resource say it does. See here. I had to use the b2clogin.com uri as shown in below screen shots. Hope it helps someone.
Postman
AppSettings.json
Startup.Auth.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme)
.AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C", options));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddApplicationInsightsTelemetry();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseMvc();
}
For registering your B2C dotnet core application first You have to login to your B2C Tenant.
After successful Registration configure following step for implicit grant flow.
Reply URLs
Make sure you have done this step accordingly:
Go to Settings and add postman callback URL to : https://www.getpostman.com/oauth2/callback
Once you enter this URL correctly click on Save upper left.
See the screen shot below:
Edit Manifest
For implicit grand flow click on your application manifest and search oauth2AllowImplicitFlow property
make it to true
see the screen shot below:
Your settings for azure B2C is done for implicit grant flow API call.
Postman
Now fire up your post man and select request type as OAuth 2.0 Like below:
Now Click on Get New Access Token and new popup will appear
See the screen shot below:
Add your tenant ID on Auth URL Like this :
https://login.microsoftonline.com/YourB2CTenantId/oauth2/authorize?resource=https://graph.microsoft.com
Set Your Client Id
Set Scope you want to access
Now click on Request Token In response you will get your implicit grant access token:
see the screen shot:
Access Data With this Token:
Copy the token you have accessed already on the Token textbox and select token type as Bearer Token
See the screen shot below:
So tricky part for implicit flow is to set up manifest property oauth2AllowImplicitFlow to true
Hope this could solve your problem. Thank you

Using ASP.NET MVC 6 Web API Identity when I have a token from FB

I'm using FB SDK for iOS to login my users. My understanding is that I can get a granted token from SDK on the client side and use it to authenticate users in my Web API. What I can't understand is how to use SignInManager<ApplicationUser> to authenticate my users only with a token.
You need JWT Bearer authentication.
Facebook grants you an access_token in JSON Web Token (JWT) format. Include that as a bearer token in your Web API requests.
GET http://www.webapi.com/v1/people
Authorization: Bearer the_facebook_access_token_goes_here
Then use the ASP.NET Security JWT bearer middleware. It will read the token and populate the HttpContext.User.Identity.
The ASP.NET team has a sample here: https://github.com/aspnet/Security/tree/dev/samples/JwtBearerSample Here are the fundamentals of how to configure JWT Bearer authentication.
project.json
dependencies : {
"Microsoft.AspNetCore.Authentication.JwtBearer": "1.1.0-*",
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
}
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
// set these to the Facebook Authority and Audience
Authority = ""
Audience = ""
});
Decorate your Web API actions with the [Authorize] attribute.
That might be enough to get you started.