52

Web APIプロジェクトでは、代わりにトークンをチェックするための通常の認証プロセスをオーバーライドしています。コードは次のようになります。なぜ私のClaimsIdentity IsAuthenticatedは常にfalseです(Web API Authorizeフィルタ用)?

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

をそして、私はコントローラに[Authorize]属性を適用すると、後で、それは認可に失敗しました。

デバッグコードは同じ動作を確認:

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

なぜそれは私が有効なClaimsIdentityを構築し、スレッドにそれを割り当てられたにも関わらず、ユーザーが認証されていないと思うのですか?

答えて

109

.Net 4.5では大きな変更が原因で問題が発生しています。 this articleで説明されているように、クレームIDを作成するだけでIsAuthenticatedをtrueに戻すことはなくなりました。代わりに、コンストラクタに文字列(何に関係なく)を渡す必要があります。

したがって、上記のコードでこの行:

var claimsIdentity = new ClaimsIdentity(claims); 

はこのようになります。

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

そして、問題が解決されます。 更新:レオからの他の回答を参照してください。正確なAuthenticationType値は、認証パイプラインに他に何があるかによって重要であるかもしれません。

更新2:コメントでRobin van der Knaapが提案したように、System.Security.Claims.AuthenticationTypes値の1つが適切かもしれません。

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

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

MSDNによれば、通常、AuthenticationTypesクラスで定義されている値の1つである必要があります。 http://msdn.microsoft.com/en-us/library/system.security.claims.claimsidentity.authenticationtype(v=vs.110).aspx –

+1

例:var claimsIdentity = new ClaimsIdentity(claims、AuthenticationTypes.Password); –

+2

文字列の値がUser.Identity.AuthenticationTypeに表示されます –

10

提供された回答には有効性がありますが、完全に正しいとは限りません。任意の文字列を追加するだけで魔法のように動作することは想定できません。コメントの1で述べたように、この文字列は、例えば...

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

しかし....今度はOWIN認証/認可ミドルウェアに指定されたものと一致しなければなりませんAuthenticationTypes列挙のいずれかと一致しなければなりません上記のシナリオではそれほど重要ではありません。あなたはクレームが同じAuthenticationTypeに一致するものに関連付けられます複数の認証/権限レベルを使用している場合は、クッキー認証を使用する場合でも、...別の例では、...

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

ですアプリが他のプロバイダから他のCookieを取得している可能性があるため、正しいCookieに関連付けるためにクレームをインスタンス化するときにAuthenticationTypeを設定することが重要です

+0

.NET Coreでは、定数を「AuthenticationType」として使用できます。[CookieAuthenticationDefaults.AuthenticationScheme](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.cookies.cookieauthenticationdefaults.authenticationscheme)または[JwtBearerDefaults.AuthenticationScheme](https://docs.microsoft .com/en-us/dotnet/api/microsoft.aspnetcore.authentication.jwtbearer.jwtbearerdefaults.authenticationscheme)。 –

関連する問題