web-dev-qa-db-ja.com

ASP.NET Core2アプリケーションでidentityserver4のOpenIdConnect認証をサインアウトできません

私のIdentityServerはidentityserver4フレームワークを使用しています( http:// localhost:90 )。そして、以下のようにクライアントをIdentityServerに登録します。

clients.Add(
     new Client
     {
         ClientId = "customer.api",
         ClientName = "Customer services",
         AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
         RequireConsent = false,
         AllowAccessTokensViaBrowser = true,

         RedirectUris = { "http://localhost:60001/signin-oidc" },
         PostLogoutRedirectUris = { "http://localhost:60001/signout-callback-oidc" },
         ClientSecrets = new List<Secret>
         {
             new Secret("testsecret".Sha256())
         },
         AllowedScopes = new List<string>
         {
             IdentityServerConstants.StandardScopes.OpenId,
             IdentityServerConstants.StandardScopes.Profile,
             IdentityServerConstants.StandardScopes.Email,
             IdentityServerConstants.StandardScopes.OfflineAccess,
             "customerprivatelinesvn.api",                        
         },
         AllowOfflineAccess = true,
         AlwaysIncludeUserClaimsInIdToken = true,
         AllowedCorsOrigins = { "http://localhost:60001" }
     });  

これが私のクライアントアプリでの認証です( http:// localhost:60001 )。

private void AddAuthentication(IServiceCollection services)
{
    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";       
    })
    .AddCookie()
    .AddOpenIdConnect("oidc", options =>
    {
        Configuration.GetSection("OpenIdConnect").Bind(options);        
    });    
}    

"OpenIdConnect": {
    "SignInScheme": "Cookies",
    "Authority": "http://localhost:9000/",
    "RequireHttpsMetadata": false,
    "ClientId": "customer.api",
    "ClientSecret": "testsecret",
    "Scope": [ "customerprivatelinesvn.api", "offline_access" ],
    "CallbackPath": "/signin-oidc",
    "ResponseType": "code id_token token",
    "GetClaimsFromUserInfoEndpoint": true,
    "SaveTokens": true
  }

クライアントアプリのHomeController

[Authorize]
public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View();
    }    
}

ユーザーがログインした後のクライアントアプリのCookieは次のとおりです。 enter image description here

以下のようにサインアウトアクションを実装しようとしています

public class AccountController : Controller
{
    public async Task<IActionResult> Signout()
    {
        await HttpContext.SignOutAsync("Cookies");
        await HttpContext.SignOutAsync("oidc");

        return RedirectToAction("Index", "Home");                  
    }
}

ただし、ユーザーがサインアウトしても、IDサーバーのエンドセッションエンドポイントは呼び出されません。フィドラーのトラフィックを見ると、IDサーバーへのリクエストはありません。

enter image description here

私の期待は、ユーザーがサインアウトすると、IDサーバーのエンドセッションエンドポイントを呼び出し、以下のようにIDサーバーのログアウトリンクにリダイレクトすることです。

enter image description here

enter image description here

OwinContextサインアウトを呼び出すことで、MVCアプリケーションでこれを簡単に行うことができます

private void LogoutOwin(IOwinContext context)
        {
            context.Authentication.SignOut();
        }

ただし、サインアウト方法はASP.NET Core2では機能しなくなりました。

注:クライアントアプリはAJAX 5アプリであるため、angular postからサインアウトアクションを呼び出しています。

ASP.NET Core 2でサインアウトを正しく実装する方法を知っている人はいますか?

どうもありがとうございました。

よろしく、

ケビン

5
Kevin Hoang

私は今私の問題を解決することができます。

1)SignOutResultを返すと、エンドセッションエンドポイントが呼び出されます。

2)フォームを送信するためにAJAX投稿を変更します。

public class AccountController : Controller
{
    public IActionResult Signout()
    {
        return new SignOutResult(new[] { "oidc", "Cookies" });            
    }
}


<form action="/Account/Signout" id="signoutForm" method="post" novalidate="novalidate">
    <ul class="nav navbar-nav navbar-right">
        <li><a href="javascript:document.getElementById('signoutForm').submit()">Sign out</a></li>
    </ul>
</form>
12
Kevin Hoang

サインアウトを許可するには、次のログアウトアクションを使用します。

_public async Task Logout()
{
    await HttpContext.SignOutAsync("Cookies");
    await HttpContext.SignOutAsync("oidc");
}
_

これはまさにクイックスタートが使用するように言っていることです( http://docs.identityserver.io/en/release/quickstarts/3_interactive_login.html )。あなた(そして私)は賢すぎました。チュートリアルのアクションを見て、「それは完了していません。アクションの結果が返されないので、自分のページにリダイレクトしてみましょう」と思いました。

実際に起こることは、HttpContext.SignOutAsync("oidc");がデフォルトのActionResultを設定することです(これは、サインアウトを完了するためにOpenIdConnectプロバイダーにリダイレクトすることです)。 return RedirectToAction("Index", "Home");で独自に指定することにより、これをオーバーライドするため、サインアウトアクションは発生しません。

ログアウト後にリダイレクトする

この回答 から、ログアウトが完了した後にリダイレクトURLを指定する方法は、AuthenticationPropertiesを使用することです。

_public async Task Logout()
{
   await context.SignOutAsync("Cookies");
   var prop = new AuthenticationProperties
   {
       RedirectUri = "/logout-complete"
   };
   // after signout this will redirect to your provided target
   await context.SignOutAsync("oidc", prop);
}
_
6
Wilco

Net Core 2.0では、列挙型CookieAuthenticationDefaultsおよびOpenIdConnectDefaultsを使用するようにコードを変更します

    services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddOpenIdConnect(SetOpenIdConnectOptions);


private static void SetOpenIdConnectOptions(OpenIdConnectOptions options)
{
    options.ClientId = "auAuthApp_implicit";
    options.Authority = "http://localhost:55379/";

    options.SignInScheme = "Cookies";
    options.RequireHttpsMetadata = false;

    options.SaveTokens = true;
    options.ResponseType = "id_token token";
    options.GetClaimsFromUserInfoEndpoint = true;

}

そして...

public async Task<IActionResult> Logout()
{
    await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);

    return RedirectToAction("Index", "Home");
}
2
alhpe