5

Sto utilizzando l'identità di asp.net per l'autenticazione basata su token in web api.web api - il token identità asp.net scade anche per la successiva richiesta

Per token di aggiornamento, ho implementato basato sul seguente link

ho aggiunto le seguenti due classi e menzionato nella configurazione di avvio.

dall'interfaccia utente ho chiamato con nome utente e la password solo tramite l'API

http://domain/token

Quando chiamo l'api sopra, la richiesta va direttamente al metodo ValidateClientAuthentication.

Ma in questo metodo la logica è che dobbiamo inviare l'ID client e il segreto del client.

Come sappiamo questi due prima del login utente per l'utente specifico?

Ho pensato che il flusso di lavoro dovrebbe essere come, dobbiamo controllare nome utente e password rispetto al database e generare il token di accesso e aggiornare il token.

Ma qui dove faccio questa logica.

Qual è il flusso di lavoro di questo sistema menzionato nel campione?

Prima di questo sistema, che chiamerò il login API comune/nella mia richiesta, e dopo la verifica di successo,

Chiamerò il codice per rendere l'utente loggato come

var userIdentity=await user.GenerateUserIdentityAsync(UserManager); 

AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, userIdentity); 

Dopo il codice sopra, genererò il token di accesso dall'identità dell'utente.

Ho provato molte volte con la seguente implementazione e sono stufo del flusso.

Aiutatemi per quanto riguarda la logica e il flusso menzionati qui.

SimpleAuthorizationServerProvider

namespace AngularJSAuthentication.API.Providers 
    { 
     public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider 
     { 
      public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
      { 

       string clientId = string.Empty; 
      string clientSecret = string.Empty; 
      Client client = null; 

      if (!context.TryGetBasicCredentials(out clientId, out clientSecret)) 
      { 
       context.TryGetFormCredentials(out clientId, out clientSecret); 
      } 

      if (context.ClientId == null) 
      { 
       //Remove the comments from the below line context.SetError, and invalidate context 
       //if you want to force sending clientId/secrects once obtain access tokens. 
       context.Validated(); 
       //context.SetError("invalid_clientId", "ClientId should be sent."); 
       return Task.FromResult<object>(null); 
      } 

      using (AuthRepository _repo = new AuthRepository()) 
      { 
       client = _repo.FindClient(context.ClientId); 
      } 

      if (client == null) 
      { 
       context.SetError("invalid_clientId", string.Format("Client '{0}' is not registered in the system.", context.ClientId)); 
       return Task.FromResult<object>(null); 
      } 

      if (client.ApplicationType == Models.ApplicationTypes.NativeConfidential) 
      { 
       if (string.IsNullOrWhiteSpace(clientSecret)) 
       { 
        context.SetError("invalid_clientId", "Client secret should be sent."); 
        return Task.FromResult<object>(null); 
       } 
       else 
       { 
        if (client.Secret != Helper.GetHash(clientSecret)) 
        { 
         context.SetError("invalid_clientId", "Client secret is invalid."); 
         return Task.FromResult<object>(null); 
        } 
       } 
      } 

      if (!client.Active) 
      { 
       context.SetError("invalid_clientId", "Client is inactive."); 
       return Task.FromResult<object>(null); 
      } 

      context.OwinContext.Set<string>("as:clientAllowedOrigin", client.AllowedOrigin); 
      context.OwinContext.Set<string>("as:clientRefreshTokenLifeTime", client.RefreshTokenLifeTime.ToString()); 

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

     public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
     { 

      var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin"); 

      if (allowedOrigin == null) allowedOrigin = "*"; 

      context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin }); 

      using (AuthRepository _repo = new AuthRepository()) 
      { 
       IdentityUser user = await _repo.FindUser(context.UserName, context.Password); 

       if (user == null) 
       { 
        context.SetError("invalid_grant", "The user name or password is incorrect."); 
        return; 
       } 
      } 

      var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
      identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 
      identity.AddClaim(new Claim(ClaimTypes.Role, "user")); 
      identity.AddClaim(new Claim("sub", context.UserName)); 

      var props = new AuthenticationProperties(new Dictionary<string, string> 
       { 
        { 
         "as:client_id", (context.ClientId == null) ? string.Empty : context.ClientId 
        }, 
        { 
         "userName", context.UserName 
        } 
       }); 

      var ticket = new AuthenticationTicket(identity, props); 
      context.Validated(ticket); 

     } 

     public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context) 
     { 
      var originalClient = context.Ticket.Properties.Dictionary["as:client_id"]; 
      var currentClient = context.ClientId; 

      if (originalClient != currentClient) 
      { 
       context.SetError("invalid_clientId", "Refresh token is issued to a different clientId."); 
       return Task.FromResult<object>(null); 
      } 

      // Change auth ticket for refresh token requests 
      var newIdentity = new ClaimsIdentity(context.Ticket.Identity); 

      var newClaim = newIdentity.Claims.Where(c => c.Type == "newClaim").FirstOrDefault(); 
      if (newClaim != null) 
      { 
       newIdentity.RemoveClaim(newClaim); 
      } 
      newIdentity.AddClaim(new Claim("newClaim", "newValue")); 

      var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties); 
      context.Validated(newTicket); 

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

     public override Task TokenEndpoint(OAuthTokenEndpointContext context) 
     { 
      foreach (KeyValuePair<string, string> property in context.Properties.Dictionary) 
      { 
       context.AdditionalResponseParameters.Add(property.Key, property.Value); 
      } 

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

    } 
} 

SimpleRefreshTokenProvider

namespace AngularJSAuthentication.API.Providers 
{ 
    public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider 
    { 

     public async Task CreateAsync(AuthenticationTokenCreateContext context) 
     { 
      var clientid = context.Ticket.Properties.Dictionary["as:client_id"]; 

      if (string.IsNullOrEmpty(clientid)) 
      { 
       return; 
      } 

      var refreshTokenId = Guid.NewGuid().ToString("n"); 

      using (AuthRepository _repo = new AuthRepository()) 
      { 
       var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime"); 

       var token = new RefreshToken() 
       { 
        Id = Helper.GetHash(refreshTokenId), 
        ClientId = clientid, 
        Subject = context.Ticket.Identity.Name, 
        IssuedUtc = DateTime.UtcNow, 
        ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime)) 
       }; 

       context.Ticket.Properties.IssuedUtc = token.IssuedUtc; 
       context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc; 

       token.ProtectedTicket = context.SerializeTicket(); 

       var result = await _repo.AddRefreshToken(token); 

       if (result) 
       { 
        context.SetToken(refreshTokenId); 
       } 

      } 
     } 

     public async Task ReceiveAsync(AuthenticationTokenReceiveContext context) 
     { 

      var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin"); 
      context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin }); 

      string hashedTokenId = Helper.GetHash(context.Token); 

      using (AuthRepository _repo = new AuthRepository()) 
      { 
       var refreshToken = await _repo.FindRefreshToken(hashedTokenId); 

       if (refreshToken != null) 
       { 
        //Get protectedTicket from refreshToken class 
        context.DeserializeTicket(refreshToken.ProtectedTicket); 
        var result = await _repo.RemoveRefreshToken(hashedTokenId); 
       } 
      } 
     } 

     public void Create(AuthenticationTokenCreateContext context) 
     { 
      throw new NotImplementedException(); 
     } 

     public void Receive(AuthenticationTokenReceiveContext context) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 
+0

"Se ho impostato token di scadenza di 10 minuti, ..., Token è scaduto in 10 minuti esatti. " Bene, sembra ragionevole! ;-) –

+0

Per la richiesta successiva, il token dovrebbe scadere dovrebbe estendersi. Il token dovrebbe scadere per il tempo di inattività di 10 minuti. –

+0

Sì, ho capito. È solo che la frase era per me curiosa. BTW controlla la mia risposta e il link al tutorial su come estendere la sessione usando i Token di aggiornamento. –

risposta

1

Come sull'utilizzo di aggiornamento gettoni e la loro memorizzazione in un database, come in questi due esempi:

Come ampiamente descritto nel primo link, è possibile creare una propria implementazione di token fornitore per gestire token di aggiornamento:

public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider 
{ 

    public async Task CreateAsync(AuthenticationTokenCreateContext context) 
    { 
     var clientid = context.Ticket.Properties.Dictionary["as:client_id"]; 

     if (string.IsNullOrEmpty(clientid)) 
     { 
      return; 
     } 

     var refreshTokenId = Guid.NewGuid().ToString("n"); 

     using (AuthRepository _repo = new AuthRepository()) 
     { 
      var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime"); 

      var token = new RefreshToken() 
      { 
       Id = Helper.GetHash(refreshTokenId), 
       ClientId = clientid, 
       Subject = context.Ticket.Identity.Name, 
       IssuedUtc = DateTime.UtcNow, 
       ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime)) 
      }; 

      context.Ticket.Properties.IssuedUtc = token.IssuedUtc; 
      context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc; 

      token.ProtectedTicket = context.SerializeTicket(); 

      var result = await _repo.AddRefreshToken(token); 

      if (result) 
      { 
       context.SetToken(refreshTokenId); 
      } 

     } 
    } 
} 
+0

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - [Dalla recensione] (/ recensione/post di bassa qualità/10702608) – dav

+1

@dav, buon punto. –

+0

Ho aggiunto quelle classi e implementato. Non so se questi metodi verranno chiamati automaticamente o devo chiamare questi metodi. se devo chiamare manualmente, allora non so quando/dove chiamare. –