52

In un progetto API Web sto sostituendo il normale processo di autenticazione per controllare i token. Il codice simile a questa:Perché my ClaimsIdentity IsAuthenticated è sempre false (per Web api Autorizza filtro)?

if (true) // validate the token or whatever here 
{ 
    var claims = new List<Claim>(); 
    claims.Add(new Claim(ClaimTypes.Name, "MyUser")); 
    claims.Add(new Claim(ClaimTypes.NameIdentifier, "MyUserID")); 
    claims.Add(new Claim(ClaimTypes.Role, "MyRole")); 

    var claimsIdentity = new ClaimsIdentity(claims); 

    var principal = new ClaimsPrincipal(new[] { claimsIdentity }); 
    Thread.CurrentPrincipal = principal; 
    HttpContext.Current.User = principal; 
} 

E poi quando applico l'attributo [Authorize] a un controller, non riesce ad autorizzare.

codice di debug conferma lo stesso comportamento:

// ALWAYS FALSE! 
if (HttpContext.Current.User.Identity.IsAuthenticated) { 
    // do something 
} 

Perché si pensa che l'utente non è autenticato anche se ho costruito un ClaimsIdentity valido e assegnato al filo?

risposta

109

Il problema è dovuto a una modifica in.Net 4.5. Come spiegato da this article, la semplice costruzione di un'identità delle attestazioni non rende più IsAuthenticated restituisce true. Invece, è necessario passare una stringa (non importa cosa) nel costruttore.

Quindi questa riga nel codice sopra:

var claimsIdentity = new ClaimsIdentity(claims); 

Diventa questo:

// exact string doesn't matter 
var claimsIdentity = new ClaimsIdentity(claims, "CustomApiKeyAuth"); 

E il problema è risolto. Aggiornamento: vedere altre risposte da Leo. Il valore esatto di AuthenticationType può o non può essere importante a seconda di cos'altro hai nella tua pipeline di autenticazione.

Aggiornamento 2: come suggerito da Robin van der Knaap nei commenti, potrebbe essere appropriato uno dei valori System.Security.Claims.AuthenticationTypes.

var claimsIdentity = new ClaimsIdentity(claims, AuthenticationTypes.Password); 

// and elsewhere in your application... 
if (User.Identity.AuthenticationType == AuthenticationTypes.Password) { 
    // ... 
} 
+8

Sebbene sia possibile aggiungere qualsiasi stringa, secondo MSDN questo dovrebbe essere in genere uno dei valori definiti nella classe AuthenticationTypes. http://msdn.microsoft.com/en-us/library/system.security.claims.claimsidentity.authenticationtype(v=vs.110).aspx –

+1

Esempio: var claimsIdentity = new ClaimsIdentity (rivendicazioni, AuthenticationTypes.Password); –

+2

Il valore della stringa diventa visibile in User.Identity.AuthenticationType –

10

Mentre la risposta fornita ha una certa validità, non è del tutto corretta. Non si può presumere che l'aggiunta di qualsiasi stringa funzionerà magicamente. Come affermato in uno dei commenti, questa stringa deve corrispondere uno dei AuthenticationTypes enumerazione che a sua volta deve corrispondere a quello specificato nel middleware di autenticazione OWIN/autorizzazione .... per esempio ...

public void ConfigureOAuth(IAppBuilder app) 
     { 
      app.UseCors(CorsOptions.AllowAll); 

      OAuthAuthorizationServerOptions serverOptions = new OAuthAuthorizationServerOptions() 
      { 
       AllowInsecureHttp = true, 
       TokenEndpointPath = new Microsoft.Owin.PathString("/token"), 
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
       AuthenticationType = AuthenticationTypes.Password, 
       AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active, 
       Provider = new AppAuthServerProvider() 
      }; 


      app.UseOAuthAuthorizationServer(serverOptions); 
      app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions() 
       { 
        AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active, 
        AuthenticationType = AuthenticationTypes.Password 
       });    
     } 

Tuttavia, nello scenario sopra non sarebbe molto importante. Ma, se si utilizza più livelli di autenticazione/autorizzazione rivendicazioni saranno associati a quello che corrisponde lo stesso AuthenticationType ... un altro esempio è quando si utilizza l'autenticazione di cookie ...

public void Configuration(IAppBuilder app) 
     { 
      app.UseCookieAuthentication(new CookieAuthenticationOptions 
      { 
       AuthenticationType = "ApplicationCookie", 
       LoginPath = new PathString("/auth/login") 
      }); 
     } 

dove AuthenticationType descrive il nome del cookie, poiché la tua app potrebbe aver ottenuto altri cookie da altri fornitori è importante impostare lo AuthenticationType quando si istanziano le rivendicazioni per associare quindi al cookie corretto

+0

In .NET Core è possibile utilizzare le costanti come 'AuthenticationType', ad es.[CookieAuthenticationDefaults.AuthenticationScheme] (https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.cookies.cookieauthenticationdefaults.authenticationscheme) o [JwtBearerDefaults.AuthenticationScheme] (https://docs.microsoft .com/it-it/dotnet/api/microsoft.aspnetcore.authentication.jwtbearer.jwtbearerdefaults.authenticationscheme). –