web-dev-qa-db-fra.com

Comment les jetons au porteur sont-ils stockés côté serveur dans l'API Web 2?

Je configure l'authentification par jeton du porteur dans l'API Web 2 et je ne comprends pas comment (ni où) le jeton du porteur est stocké côté serveur. Voici le code pertinent:

Démarrage:

public partial class Startup
{
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
    public static Func<UserManager<IdentityUser>> UserManagerFactory { get; set; }
    public static string PublicClientId { get; private set; }

    static Startup()
    {
        PublicClientId = "self";
        UserManagerFactory = () => new UserManager<IdentityUser>(new UserStore<IdentityUser>());
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
        };
    }

    public void ConfigureAuth(IAppBuilder app)
    {
        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        app.UseOAuthBearerTokens(OAuthOptions);
    }
}

WebApiConfig:

public class WebApiConfig
{
    public static void ConfigureWebApi()
    {
        Register(GlobalConfiguration.Configuration);
    }

    public static void Register(HttpConfiguration http)
    {
        AuthUtil.ConfigureWebApiToUseOnlyBearerTokenAuthentication(http);
        http.Routes.MapHttpRoute("ActionApi", "api/{controller}/{action}", new {action = Actions.Default});
    }
}

AuthUtil:

public class AuthUtil
{
    public static string Token(string email)
    {
        var identity = new ClaimsIdentity(Startup.OAuthOptions.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, email));
        var ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
        var currentUtc = new SystemClock().UtcNow;
        ticket.Properties.IssuedUtc = currentUtc;
        ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
        var token = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);
        return token;
    }

    public static void ConfigureWebApiToUseOnlyBearerTokenAuthentication(HttpConfiguration http)
    {
        http.SuppressDefaultHostAuthentication();
        http.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
    }
}

LoginController:

public class LoginController : ApiController
{
    ...

    public HttpResponseMessage Post([FromBody] LoginJson loginJson)
    {
        HttpResponseMessage loginResponse;
        if (/* is valid login */)
        {
            var accessToken = AuthUtil.Token(loginJson.email);
            loginResponse = /* HTTP response including accessToken */;
        }
        else
        {
            loginResponse = /* HTTP response with error */;
        }
        return loginResponse;
    }
}

En utilisant le code ci-dessus, je suis en mesure de me connecter et de stocker le jeton porteur côté client dans un cookie, puis d'appeler des contrôleurs marqués avec [Autoriser] et cela me permet d'entrer.

Mes questions sont:

  1. Où/comment le jeton porteur est-il stocké côté serveur? Il semble que cela se passe à travers l'un des appels OWIN mais je ne peux pas dire où.

  2. Est-il possible de conserver les jetons porteurs sur une base de données côté serveur afin qu'ils puissent rester en place après un redémarrage du serveur d'API Web?

  3. Si la réponse à la question # 2 est non, y a-t-il un moyen pour un client de conserver son jeton de porteur et de le réutiliser même après que l'API Web est en panne et revient? Bien que cela puisse être rare en production, cela peut se produire assez souvent lors de tests locaux.

57
dposada
  1. Ils ne sont pas stockés côté serveur - ils sont délivrés au client et le client les présente à chaque appel. Ils sont vérifiés car ils sont signés par la clé de protection de l'hôte Owin. Dans l'hébergement SystemWeb, cette clé de protection est le paramètre machineKey de web.config.

  2. Ce n'est pas nécessaire, tant que la clé de protection utilisée par l'hôte owin ne change pas lors des redémarrages du serveur.

  3. Un client peut conserver un jeton aussi longtemps que le jeton est valide.

87
Brock Allen

Pour ceux qui cherchent à définir web.config, voici un exemple

<system.web>
<machineKey validation="HMACSHA256" validationKey="64-hex"
                 decryption="AES" decryptionKey="another-64-hex"/>
</system.web>

Vous avez besoin à la fois de validationKey et de decriptionkey pour le faire fonctionner.

Et voici comment générer des clés https://msdn.Microsoft.com/en-us/library/ms998288.aspx

3
Bruce Wang

Pour ajouter à cela, le jeton peut être conservé côté serveur à l'aide de la propriété SessionStore de CookieAuthenticationOptions. Je ne recommanderais pas de faire cela, mais c'est là si vos jetons deviennent excessivement grands.

Il s'agit d'un IAuthenticationSessionStore afin que vous puissiez implémenter votre propre support de stockage.

2
thisispaulsmith

Par défaut, le jeton n'est pas stocké par le serveur. Seul votre client l'a et l'envoie via l'en-tête d'autorisation au serveur.

Si vous avez utilisé le modèle par défaut fourni par Visual Studio, dans la méthode Startup ConfigureAuth, l'extension IAppBuilder suivante est appelée: app.UseOAuthBearerTokens (OAuthOptions).

0
Supriya Verma