Question Expiration du jeton OAuth dans l'application MVC6


J'ai donc une application MVC6 qui inclut un serveur d'identité (utilisant IdentityServer3 de ThinkTecture) et une application de services Web MVC6.

Dans l'application de services Web, j'utilise ce code dans Startup:

app.UseOAuthBearerAuthentication(options =>
{
    options.Authority = "http://localhost:6418/identity";
    options.AutomaticAuthentication = true;
    options.Audience = "http://localhost:6418/identity/resources";
});

Ensuite, j'ai un contrôleur avec une action qui a le Authorize attribut.

J'ai une application JavaScript qui s'authentifie auprès du serveur d'identité, puis utilise le jeton JWT fourni pour accéder à l'action des services Web.

Cela fonctionne et je ne peux accéder à l'action qu'avec un jeton valide.

Le problème survient lorsque le JWT a expiré. Ce que j'obtiens, c'est ce qui semble être une page d'erreur ASP.NET 500 détaillée qui renvoie des informations d'exception pour l'exception suivante:

System.IdentityModel.Tokens.SecurityTokenExpiredException   IDX10223: La validation de la durée de vie a échoué. Le jeton a expiré.

Je suis assez nouveau sur OAuth et sur la sécurisation des API Web en général, donc je suis peut-être hors de base, mais une erreur 500 ne me semble pas appropriée pour un jeton expiré. Ce n'est certainement pas convivial pour un client de service Web.

Est-ce le comportement attendu et, dans la négative, est-ce que je dois faire quelque chose pour obtenir une réponse plus appropriée?


13
2017-08-31 23:45


origine


Réponses:


Edit: ce bogue a été corrigé dans ASP.NET Core RC2 et la solution de contournement décrite dans cette réponse n'est plus nécessaire.


Remarque: cette solution ne fonctionnera pas sur ASP.NET 5 RC1, à cause de cet autre bug. Vous pouvez migrer vers la RC2 nightly builds ou créer un middleware personnalisé qui attrape les exceptions lancées par le middleware porteur JWT et renvoie une réponse 401:

app.Use(next => async context => {
    try {
        await next(context);
    }

    catch {
        // If the headers have already been sent, you can't replace the status code.
        // In this case, throw an exception to close the connection.
        if (context.Response.HasStarted) {
            throw;
        }

        context.Response.StatusCode = 401;
    }
});

Malheureusement, cela signifie que le middleware porteur JWT / OAuth2 (géré par MSFT) fonctionne actuellement par défaut, mais il devrait être finalement corrigé. Vous pouvez voir ce ticket GitHub pour plus d'informations: https://github.com/aspnet/Security/issues/411

Heureusement, vous pouvez facilement "contourner" ce problème en utilisant AuthenticationFailed notification:

app.UseOAuthBearerAuthentication(options => {
    options.Notifications = new OAuthBearerAuthenticationNotifications {
        AuthenticationFailed = notification => {
            notification.HandleResponse();

            return Task.FromResult<object>(null);
        }
    };
});

11
2017-09-02 12:45