2014-09-25 26 views
26

Ho iniziato a creare una API Web per le app mobili e ho difficoltà a implementare l'autenticazione. Uso Bearer e sebbene tutto sia a posto, non riesco a ottenere l'azione da parte dell'utente corrente nel controller. HttpContext.Current.User.Identity.Name è null (lo stesso è il risultato di HttpContext.Current.User.Identity.GetUserId()). Qui ci sono i pezzi di codice importante:Utente corrente nell'autenticazione owin

Startup.cs:

public partial class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      var config = new HttpConfiguration(); 
      ConfigureAuth(app); 
      WebApiConfig.Register(config); 
      app.UseWebApi(config); 
     } 
    } 

Startup.Auth.cs

public partial class Startup 
{ 
     static Startup() 
     { 
      OAuthOptions = new OAuthAuthorizationServerOptions 
      { 
       TokenEndpointPath = new PathString("/token"), 
       Provider = new ApplicationOAuthProvider(), 
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
       AllowInsecureHttp = true 
      }; 

      OAuthBearerOptions = new OAuthBearerAuthenticationOptions(); 
     } 

     public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } 
     public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; } 


     public static string PublicClientId { get; private set; } 

     public void ConfigureAuth(IAppBuilder app) 
     { 
      app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions 
      { 
       AccessTokenProvider = new AuthenticationTokenProvider() 
      }); 
      app.UseOAuthBearerTokens(OAuthOptions); 

      app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 

     } 
} 

ApplicationOAuthProvider.cs:

 public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
     { 

      string clientId, clientSecret; 

      if (!context.TryGetBasicCredentials(out clientId, out clientSecret)) 
      { 
       return SetErrorAndReturn(context, "client error", ""); 
      } 

      if (clientId == "secret" && clientSecret == "secret") 
      { 
       context.Validated(); 
       return Task.FromResult<object>(null); 
      } 

      return SetErrorAndReturn(context, "client error", ""); 
     } 

     public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
     { 

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

      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("sub", context.UserName)); 
      identity.AddClaim(new Claim("role", "user")); 

      context.Validated(identity); 
     } 


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

AuthRepository.cs:

public class AuthRepository : IDisposable 
    { 
     private readonly AuthContext _ctx; 

     private readonly UserManager<IdentityUser> _userManager; 

     public AuthRepository() 
     { 
      _ctx = new AuthContext(); 
      _userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx)); 
     } 

     public async Task<IdentityResult> RegisterUser(UserModel userModel) 
     { 
      var user = new IdentityUser 
      { 
       UserName = userModel.UserName 
      }; 

      var result = await _userManager.CreateAsync(user, userModel.Password); 

      return result; 
     } 

     public async Task<IdentityUser> FindUser(string userName, string password) 
     { 
      IdentityUser user = await _userManager.FindAsync(userName, password); 
      return user; 
     } 

     public void Dispose() 
     { 
      _ctx.Dispose(); 
      _userManager.Dispose(); 

     } 
    } 

AuthContext.cs:

public class AuthContext : IdentityDbContext<IdentityUser> 
    { 
     public AuthContext() 
      : base("AuthContext") 
     { 

     } 
    } 

E finnaly ValuesController.cs:

[Authorize] 
public class ValuesController : ApiController 
{ 

    public IEnumerable<string> Get() 
    { 
     return new String[] {HttpContext.Current.User.Identity.Name, HttpContext.Current.User.Identity.GetUserId(),ClaimsPrincipal.Current.Identity.Name}; 
    } 
} 

Quando vado a questa azione, ho nulli 3 volte. Nonostante ciò, l'intero processo di autenticazione sembra andare bene - solo quando invio un buon token, ho accesso. Qualcuno ha un'idea di cosa c'è che non va qui?

+0

Avete un punto di interruzione impostato su 'return new String [] {HttpContext ...'? Dov'è il primo null? – user1477388

+0

L'ultimo valore non nullo è Identità (quindi non ottengo un errore, ma null come valore restituito) – user3558203

+0

Anche 'GetUserId()' è nullo? – user1477388

risposta

55

sul metodo di GrantResourceOwnerCredentials Una volta aggiunto pretese dopo la convalida della password nome utente è necessario aggiungere questa affermazione:

identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 

In questo modo l'ID utente sarà riempito quando si chiama User.Identity.Name all'interno del controller protetta. Spero che questo risolva il tuo problema.

+1

Sfortunatamente, non ha aiutato. Ho ancora zero. Non sono sicuro di aver capito la parte con il controller protetto btw. Quello che ho fatto è stato semplicemente aggiungere la tua linea dopo identità. AddClaim (new Claim ("role", "user")); – user3558203

+2

Intendo per Controller protetto un attributo controller con [Autorizza], se è stato selezionato il valore User.Identity.IsAuthenticated è impostato su true e User.Identity.Name è sempre vuoto dopo aver aggiunto questo reclamo? –

+3

Desidero inoltre ringraziarvi per la soluzione di cui sopra! Giusto per chiarire cosa ha detto l'utente55 .. devi aggiungere il reclamo nel provider e quindi riconnetterti per creare un nuovo token prima di vedere la modifica (stavo aggiornando la pagina con il mio token esistente e mi chiedevo perché non potevo vedere lo username, ha) – alimac83