Firebase Authentication (JWT) with .NET Core

Firebase Authentication (JWT) with .NET Core



I'm developing a simple API that handles Authentication made by Firebase - to be used later with Android clients.



So in Firebase console I enabled Facebook and Google sign-in methods and created a sample html page that I can use it to test the login method - this next function is called by a button:


function loginFacebook()
var provider = new firebase.auth.FacebookAuthProvider();
var token = "";
firebase.auth().signInWithPopup(provider).then(function (result)
var token = result.credential.accessToken;
var user = result.user;
alert("login OK");
user.getToken().then(function (t)
token = t;
loginAPI();
);
).catch(function (error)
var errorCode = error.code;
var errorMessage = error.message;
alert(errorCode + " - " + errorMessage);
);



next I use the token and send it to my API with a simple ajax call from jQuery here:


function loginAPI()

$.ajax(
url: "http://localhost:58041/v1/Users/",
dataType: 'json',
type: 'GET',
beforeSend: function (xhr)
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Authorization", "Bearer " + token);
,
error: function (ex)
console.log(ex.status + " - " + ex.statusText);
,
success: function (data)
console.log(data);
return data;

);



Next stop: the API backend - written with .NET Core.



Under the Startup I've configured the JwtBearer Auth (package Microsoft.AspNetCore.Authentication.JwtBearer):


Microsoft.AspNetCore.Authentication.JwtBearer


app.UseJwtBearerAuthentication(new JwtBearerOptions

AutomaticAuthenticate = true,
IncludeErrorDetails = true,
Authority = "https://securetoken.google.com/PROJECT-ID",
TokenValidationParameters = new TokenValidationParameters

ValidateIssuer = true,
ValidIssuer = "https://securetoken.google.com/PROJECT-ID",
ValidateAudience = true,
ValidAudience = "PROJECT-ID",
ValidateLifetime = true,
,
);



And here is the Controller code - with the [Authorize] attribute:


[Authorize]


[Authorize]
[Route("v1/[controller]")]
public class UsersController : Controller

private readonly ILogger _logger;
private readonly UserService _userService;

public UsersController(ILogger<UsersController> logger, UserService userService)

_logger = logger;
_userService = userService;


[HttpGet]
public async Task<IList<User>> Get()

return await _userService.GetAll();




The API response is 200 OK (HttpContext.User.Identity.IsAuthenticated is true inside the Controller), but I think it shouldn't. My problem is that I'm not entirely sure that this is secure.


HttpContext.User.Identity.IsAuthenticated


true



How this is checking the signature part of the JWT token? I saw a lot of code samples mentioning x509 or RS256 algorithm, where do they fit with this? Shouldn't be checking against some kind of certificate or private key with the IssuerSigningKey or TokenDecryptionKey from the TokenValidationParameters class? What I'm missing?


IssuerSigningKey


TokenDecryptionKey


TokenValidationParameters



Relevant sources of knowledge about the issue:





The response is 200 OK even if you don't pass the Authorization header? That's definitely wrong. Do you have the app.UseMvc() call before or after app.UseJwtBearerAuthentication()?
– Mark Vincze
Feb 21 '17 at 8:24


200 OK


Authorization


app.UseMvc()


app.UseJwtBearerAuthentication()





If I don't pass the Authorization header, the the response is 401. And the app.UseMvc() is after the app.UseJwtBearerAuthentication(). I'm just not sure about the security. I tried to hack my app and was not able to. Maybe I'm just paranoid.
– Israel Rodriguez
Feb 21 '17 at 13:56


Authorization


401


app.UseMvc()


app.UseJwtBearerAuthentication()





Hmm, but you say the response "shouldn't be 200". Why? Are you intentionally passing an incorrect token in the header? Or why do you expect the response not to be 200?
– Mark Vincze
Feb 21 '17 at 15:58






Since I'm not providing a private key anywhere in my code so I think that shouldn't work, but after being unable to hack it, I think I'm just paranoid.
– Israel Rodriguez
Feb 21 '17 at 17:40





I'm afraid you misunderstand how the token signing works in this flow. Your application is not supposed to provide (or have) a private key (or any kind of key). I added a description of the flow to my blog post: blog.markvincze.com/secure-an-asp-net-core-api-with-firebase/…
– Mark Vincze
Feb 22 '17 at 10:47




3 Answers
3



Firebase uses the RSA256 asymmetric key cryptosystem, which means it has a public and a private key. Signing a token happens with the private key, while verifying a token happens with the public key.



The following diagram illustrates how the token signing happens.



enter image description here



During signing in and accessing a secure endpoint, the following steps are involved.


JwtBearerMiddleware


https://securetoken.google.com/my-firebase-project/.well-known/openid-configuration


Authorization


JwtBearerMiddleware


HttpContext.User


HttpContext.User.Identity.IsAuthenticated



You can find an even simpler description of this concept on the RSA Wikipedia page, and some more information about Firebase + ASP.NET in my blog post.





Thanks for the clarification @Mark
– Israel Rodriguez
Feb 23 '17 at 20:03





Great explanation, thanks :-)
– jhm
Mar 2 '17 at 10:29





@Mark Vincze - Could you perhaps have a look at this question as well (related)? stackoverflow.com/q/42560558/1409779 Would be much appreciated :-)
– jhm
Mar 2 '17 at 16:21




For the backend side, there is a Nuget package that does the trick for you:



Install-Package AspNetCore.Firebase.Authentication


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

app.UseFirebaseAuthentication("https://securetoken.google.com/MYPROJECTNAME", "MYPROJECTNAME");



It does the audience, issuer, signature and validity validation





Not sure this works with ASP .NET Core 2.0. I get the following error: Could not load type 'Microsoft.AspNetCore.Builder.JwtBearerOptions' from assembly 'Microsoft.AspNetCore.Authentication.JwtBearer, Version=2.0.0.0
– Primico
Oct 25 '17 at 1:02





@Raphaël What is ApiKey for?
– Tzvi Gregory Kaidanov
May 21 at 9:56






@TzviGregoryKaidanov actually it's in the appsettings, but unused, as the middleware only validate token & signature, which doesn't require ApiKey
– Raphaël
May 22 at 10:08





@Primico I published a .netcore2.0 compatible package
– Raphaël
May 22 at 10:08





@ Raphaël workes like a charm. Thank you!
– Tzvi Gregory Kaidanov
May 23 at 7:15



The NuGet packet is using the old ASP NET Core 1.x Authentication mechanism



The authentication has been changed: https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x





Published the package AspNetCore.Firebase.Authentication 2.0 which support .aspnetcore2.0
– Raphaël
May 22 at 10:09






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)