Dlaczego moje ClaimsIdentity isauthenticated jest zawsze fałszywe (dla Web api Authorize filter)?

W projekcie Web API nadpisuję normalny proces uwierzytelniania, aby sprawdzić tokeny. Kod wygląda mniej więcej tak:

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

I później, gdy zastosuję atrybut [Authorize] do kontrolera, nie autoryzuje się.

Kod debugowania potwierdza to samo zachowanie:

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

Dlaczego uważa, że użytkownik nie jest uwierzytelniony, mimo że skonstruowałem poprawne roszczenie i przypisałem je do wątku?

Author: explunit, 2013-11-28

2 answers

Problem jest spowodowany przełomową zmianą w. Net 4.5. Jak wyjaśniono w w tym artykule , po prostu konstruowanie tożsamości twierdzenia nie sprawia już, że jest to prawdziwy zwrot IsAuthenticated. Zamiast tego musisz przekazać jakiś ciąg znaków (nie ma znaczenia co) do konstruktora.

Więc ta linijka w powyższym kodzie:

var claimsIdentity = new ClaimsIdentity( claims );

Staje się to:

// exact string doesn't matter
var claimsIdentity = new ClaimsIdentity( claims, "CustomApiKeyAuth" );
I problem został rozwiązany. Update: zobacz inne odpowiedzi od Leo. Dokładna wartość AuthenticationType może być ważne w zależności od tego, co jeszcze masz w potoku auth.

Aktualizacja 2: zgodnie z sugestią Robina van der Knaap w komentarzach, jedna z wartości System.Security.Claims.AuthenticationTypes może być odpowiednia.

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

// and elsewhere in your application...
if (User.Identity.AuthenticationType == AuthenticationTypes.Password) {
    // ...
}
 111
Author: explunit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-17 17:26:52

Chociaż udzielona odpowiedź ma w sobie pewną ważność, nie jest do końca poprawna. Nie można zakładać, że samo dodanie dowolnego ciągu będzie magicznie działać. Jak podano w jednym z komentarzy, ciąg ten musi pasować do jednego z AuthenticationTypes wyliczenie, które z kolei musi być zgodne z podanym w OWIN authentication / authorization middleware....na przykład...

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

Jednak w powyższym scenariuszu nie miałoby to większego znaczenia. Ale jeśli używasz więcej poziomów uwierzytelniania/autoryzacji roszczenia będą powiązane z tym, który pasuje do tego samego AuthenticationType...innym przykładem jest użycie uwierzytelniania plików cookie...

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

Gdzie AuthenticationType opisuje nazwę pliku cookie, ponieważ Twoja aplikacja mogła uzyskać inne pliki cookie od innych dostawców, ważne jest, aby ustawić AuthenticationType podczas tworzenia instancji roszczeń, aby powiązać je z prawidłowym plikiem cookie

 10
Author: Leo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-25 02:10:25