web-dev-qa-db-fra.com

Authentification Firebase (JWT) avec .NET Core

Je développe une API simple qui gère l'authentification faite par Firebase - à utiliser plus tard avec les clients Android.

Donc, dans la console Firebase, j'ai activé les méthodes de connexion Facebook et Google et créé un exemple de page html que je peux utiliser pour tester la méthode de connexion - cette fonction suivante est appelée par un bouton:

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);
        });
    }

ensuite j'utilise le token et l'envoie à mon API avec un simple appel ajax de jQuery ici:

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;
        }
    });
}

Prochain arrêt: le backend API - écrit avec .NET Core.

Sous le démarrage, j'ai configuré l'authentification JwtBearer (package 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,
    },
});

Et voici le code du contrôleur - avec le [Authorize] attribut:

[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();
    }
}

La réponse de l'API est 200 OK (HttpContext.User.Identity.IsAuthenticated est true dans le Controller), mais je pense que non. Mon problème est que je ne suis pas entièrement sûr que ce soit sécurisé.

Comment cela vérifie-t-il la partie signature du jeton JWT? J'ai vu beaucoup d'échantillons de code mentionnant l'algorithme x509 ou RS256, où vont-ils avec cela? Ne devrait pas vérifier une sorte de certificat ou de clé privée avec le IssuerSigningKey ou TokenDecryptionKey de la classe TokenValidationParameters? Qu'est-ce qui me manque?

Sources de connaissances pertinentes sur la question:

15
Israel Rodriguez

Firebase utilise le RSA256 cryptosystème à clé asymétrique, ce qui signifie qu'il possède une clé publique et une clé privée. Signature un jeton se produit avec la clé privée, tandis que vérification d'un jeton se produit avec la clé publique.

Le diagramme suivant illustre comment la signature de jeton se produit.

enter image description here

Lors de la connexion et de l'accès à un point de terminaison sécurisé, les étapes suivantes sont impliquées.

  1. Lorsque notre application démarre (et ensuite plus tard aussi périodiquement), le JwtBearerMiddleware appelle https://securetoken.google.com/my-firebase-project/.well-known/openid-configuration, où il peut accéder aux clés publiques actuelles de Google. Il est important que lorsque nous utilisons un système de cryptage asymétrique à clé publique, la la clé publique ne soit pas gardée secrète, mais elle est publiée à la vue de tous.
  2. Un client se connecte en utilisant ses informations d'identification via Firebase (ce sont les propres informations d'identification du client, elles n'ont rien à voir avec la clé utilisée pour signer le jeton).
  3. Si la connexion a réussi, Firebase crée un jeton JWT pour le client. Une partie cruciale de ce jeton est que il est signé à l'aide de la clé privée de la paire de clés . Contrairement à la clé publique, la clé privée n'est jamais exposée publiquement, elle est gardée secrète dans l'infrastructure de Google.
  4. Le client reçoit le jeton JWT.
  5. Le client appelle un point de terminaison sécurisé sur notre API et place le jeton dans l'en-tête Authorization. À ce stade, le JwtBearerMiddleware dans le pipeline vérifie ce jeton et vérifie s'il est valide (s'il a été signé avec la clé privée de Google). La chose importante à réaliser ici est que pour faire la vérification, notre Api n'a pas besoin d'avoir accès à la clé privée. Seule la clé publique est nécessaire pour cela. Après vérification, le middleware remplit HttpContext.User, et HttpContext.User.Identity.IsAuthenticated en conséquence.

Vous pouvez trouver une description encore plus simple de ce concept sur la page Wikipedia RSA , et plus d'informations sur Firebase + ASP.NET dans mon article de blog .

18
Mark Vincze

Pour le côté backend, il existe un package Nuget qui fait l'affaire pour vous:

Install-Package AspNetCore.Firebase.Authentication

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  ILoggerFactory loggerFactory)
{      
app.UseFirebaseAuthentication("https://securetoken.google.com/MYPROJECTNAME", "MYPROJECTNAME");
}

Il fait l'audience, l'émetteur, la signature et la validation de la validité

6
Raphaël

Le paquet NuGet utilise l'ancien mécanisme d'authentification ASP NET Core 1.x

L'authentification a été modifiée: https://docs.Microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

1
xlogic