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

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.

Related

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

Is Authorization Policy requireAuthenticatedUser compatible with multiple forms of authentication (cookie and JWT)

I have an ASP.NET Core 2.2 MVC Application with a web API. I'm using cookie auth for MVC pages and JWT Bearer auth for API. I followed the solution described How can i implement Cookie base authentication and jwt in asp.net core 2.2? which is based on https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2
The trouble comes when I want to add an authorization policy to ensure the entire site is available to authenticated users
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
})
When I do this, the JWT Bearer authentication is ignored even though the atrribute [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] is present. Thus accessing these API controllers returns a redirect to the login page.
How could I enable the authorization policy and still maintain both forms of authentication? A workaround is to add [Authorize] attribute to all controllers
You can combine the jwt bearer schema and asp.net identity authentication schema when building AuthorizationPolicy :
var policy = new AuthorizationPolicyBuilder(new[] { JwtBearerDefaults.AuthenticationScheme, IdentityConstants.ApplicationScheme })
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
So that both authenticated by asp.net identity and JWT token authentication could access your protected actions .
It seems like it is a known issue in the .Net core. I am using .NET Core 3.1 and it is still not resolved.
Here is my workaround:
var principal = context.User;
if (!principal.Identity.IsAuthenticated)
{
return Task.FromResult(0); //user not logged in
}

Azure AD User info with JWT Bearer token and ASP.NET Core 2 WebApi

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

Authentication and Authorization with ASP.NET Core and Service Stack

I have a ASP.Net Core MVC Web App that users needs to logon to get the id_token from the IdentityServer4 and then that id_token will be passed to webapi implemented in ServiceStack to obtain the authorization code. The subsequent call to the webapi will use the authorization code.
So far what I have read is for the Web App, it should use openid cookie token (UseOpenIdConnectAuthentication). For the webapi, it should use the bearer token. My question is how I can pass that http only cookie token from the client side browser as a bearer token in the http header. As the cookie is http only, it can't be accessed by the Javascript. Moreover, the ASP.NET Core cookie middleware encrypts the cookie, can that encrypted cookie be decrypted by the ServiceStack webapi (if the cookie is passed to the webapi)?
Am I going in the right direction? Any suggestion is welcome.
Thanks
You can find an example of your scenario here: https://identityserver4.readthedocs.io/en/release/quickstarts/5_hybrid_and_api_access.html
The authorization code is only used to get access tokens from the identity server, it is not used to authenticate to APIs.
Here is how the flow should work:
User logs in at Identity Server
Your MVC app gets an authorization code and id token
The id token tells your MVC app who the user is
The authorization code is exchanged for an access token and refresh token with identity server for the API
Now the MVC app can make HTTP calls from its backend using the access token
Authentication cookie is created and returned to user
Front-end submits the authentication cookie with every request to MVC backend, which authenticates every request automatically that hits MVC, then when you want to call the API from there, get it as shown in the docs, and attach it to your requests
I think the point you are missing here is that once the user is logged in, you will get the access token in the response as well when you land back on the client application. If you are using Hybrid Flow, on the client app we configure it as
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ClientId = "mvc",
ClientSecret = "secret",
ResponseType = "code id_token",
Scope = { "api1", "offline_access" },
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true
});
See the ResponseType we ask for code i.e the access code. So you need not to call or login again. Once you want to call your api just get the token like
var access_token = await HttpContext.Authentication.GetTokenAsync("access_token");
// call api
var client = new HttpClient();
client.SetBearerToken(access_token);
var response = await client.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
And if you using Implicit flow, your front end can get the access token using oidc-client library and user.access_token will have it.

Authenticating and Authorizing using ADFS WS-Fed protocol

I am working on implementing Authenticating and Authorization in my application.
For Authentication:
I configured by ADFS Server with WS-Fed Sign in Protocol and enabled JWT. Created MVC application and configured to use WS-Fed for authenticating user.
Now question here is how do I store JWT token in my cookie after successfully login?
Here is my code
public partial class Startup
{
private static string realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
private static string adfsMetadata = ConfigurationManager.AppSettings["ida:ADFSMetadata"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions{ CookieName="JwtToken",CookieHttpOnly=false});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata
});
}
}
For Authorization
I have a separate Web API project. I want to authorize my api's by passing the JWT token in header of every request but not sure how to extract JWT token from cookie and pass it to web api for validating.
I found the answer here http://www.software-architects.com/devblog/2015/02/02/ADFS-and-ADAL-Lab.
ADAL (Active Directory Authentication Libraryfor .NET and for JavaScript) which can be used to acquire token in mvc application and pass the token in header for authorizing web api.