错误代码500&无法取消对邮件的保护。重定向至标识服务器4中的客户端时 [英] Error code 500 "Unable to unprotect the message.State" when redirecting to Client in IdentityServer4

查看:47
本文介绍了错误代码500&无法取消对邮件的保护。重定向至标识服务器4中的客户端时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用IdentityServer4并尝试手动验证我的ASP.NET Core 3.1客户端(手动创建请求以了解流)。 这是我的客户登录:

[HttpGet]
public IActionResult ManualLogin()
{
    var myNonce = Guid.NewGuid().ToString();    
    var myState = Guid.NewGuid().ToString();

    var req = "https://localhost:5000/connect/authorize?" +
        "client_id=mvc" +
        "&redirect_uri=https://localhost:44381/signin-oidc" +
        "&response_type=code id_token" +
        "&scope=openid profile offline_access email" +
        "&response_mode=form_post" +
        $"&nonce={myNonce}" +
        $"&state={myState}";
        
    return Redirect(req);
}

此登录方法运行良好,一切正常,但我不想使用它:

//[HttpGet]
//public async Task LoginAsync()
//{
//     await HttpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
//     {
//         RedirectUri = "https://localhost:44381/Home/external-login-callback"
//    });
// }

我的客户的启动.cs:

public void ConfigureServices(IServiceCollection services)
{
    // for using IHttpClientFactory
    services.AddHttpClient();

    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

    // adding Authentication services to DependencyInjection
    services.AddAuthentication(config =>
    {
        config.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;

        config.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)

        .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, config =>
        {
            config.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

            config.Authority = "https://localhost:5000";

            config.ClientId = "mvc";

            config.ClientSecret = "secret";

            config.SaveTokens = true;

            config.UseTokenLifetime = false;

            // Hybrid Flow
            config.ResponseType = "code id_token";

            config.Scope.Add("openid");
            config.Scope.Add("offline_access");
            config.Scope.Add("profile");
            config.Scope.Add("email");

            config.GetClaimsFromUserInfoEndpoint = true;

            config.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = JwtClaimTypes.GivenName,
                RoleClaimType = JwtClaimTypes.Role,
            };

            // config.AuthenticationMethod = OpenIdConnectRedirectBehavior.FormPost;
        });

    services.AddControllersWithViews();
}

我的客户定义:

new Client
{
    ClientId = "mvc",
    ClientName ="My mvc client testing",
    ClientSecrets = { new Secret("secret".Sha256()) },

    AllowedGrantTypes = GrantTypes.Hybrid,

    // where to redirect to after login
    RedirectUris = { "https://localhost:44381/signin-oidc" },

    // where to redirect to after logout
    PostLogoutRedirectUris = { "https://localhost:44381/signout-callback-oidc" },

    AllowedScopes = new List<string>
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
    },

    AllowOfflineAccess = true,
    UpdateAccessTokenClaimsOnRefresh = true,
    AccessTokenType = AccessTokenType.Reference,
    RequireConsent = false,

    RequireClientSecret = true,
    //AlwaysIncludeUserClaimsInIdToken = true,
    RequirePkce = false,
}

我的IS4的启动.cs:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();

        var builder = services.AddIdentityServer()
            .AddInMemoryIdentityResources(Config.IdentityResources)
            .AddInMemoryApiScopes(Config.ApiScopes)
            .AddInMemoryClients(Config.Clients)
            .AddTestUsers(TestUsers.Users);

        builder.AddDeveloperSigningCredential();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseStaticFiles();
        app.UseRouting();

        app.UseIdentityServer();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
        });
    }
}

客户端重定向成功到IS4登录页面,然后我就可以对用户进行身份验证了,当重定向回我客户端上的signin-oidcurl时,我得到了500 Internal Server Error

Unable to unprotect the message.State.

Exception: Unable to unprotect the message.State.
Unknown location

Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()

Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

我没有多个oidc,只有一个!我错过了什么?


更新1:在@ToreNestenius评论之后:

我将请求的reDirect_uri更改为:

&redirect_uri=https://localhost:44381/home/MyCallback"

并将回调添加到IS4客户端的配置中,然后是我的回调:

[HttpPost]
[ActionName("mycallback")]
public async Task mycallbackAsync(
    string code, 
    string scope, 
    string state, 
    string session_state,
    string login_required)
{
    var theRequest = $"https://localhost:5000/connect/token";

    var client = _httpClientFactory.CreateClient();
    
    var theContent = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string,string>("client_id","mvc"),
        new KeyValuePair<string,string>("client_secret","secret"),
        new KeyValuePair<string,string>("grant_type","hybrid"),
        new KeyValuePair<string,string>("code",code),
        new KeyValuePair<string,string>("redirect_uri", "https://localhost:5002/home/mycallback"),
    });

    theContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

    var base64StringUserPass = Convert.ToBase64String(Encoding.ASCII.GetBytes($"mvc:secret"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64StringUserPass);

    var response = await client.PostAsync(req, theContent);
    if (!response.IsSuccessStatusCode)
    {
        Console.WriteLine(response.StatusCode);
        return;
    }
 
    var content = await response.Content.ReadAsStringAsync();
    var theAccessToken = JsonConvert.DeserializeObject<Token>(content);
    
    // -----------------------------
    // get user info
    //var access_token = theAccessToken.access_token;
    //string userInfo = await getUserInfoAsync(access_token);
}

现在我可以正确地处理回调,然后发出一个accesToken并获取userInfo。

推荐答案

您在代码中使用

    "&redirect_uri=https://localhost:44381/signin-oidc" +

这意味着您正在尝试重定向回客户端中的OpenIDConnect身份验证处理程序/方案。但是它期望传入的请求包含它无法识别的状态和随机数值。因为初始身份验证请求不是来自该处理程序。

因为您希望学习OpenID-Connect并手动完成(就像我学习它时一样)。我建议您将redirectURI更改为您自己的控制器中的一个操作方法。像https://localhost:44381/test/callback";

一样

我建议您在了解完整的手动流程之前,避免使用OpenIDConnect处理程序。

回调方法签名应如下所示:

/// <summary>
/// This method is called with the authorization code and state parameter
/// </summary>
/// <param name="code">authorization code generated by the authorization server. This code is relatively short-lived, typically lasting between 1 to 10 minutes depending on the OAuth service.</param>
/// <param name="state"></param>
/// <returns></returns>

[HttpPost]
public IActionResult Callback(string code, string state)
{

    //To be secure then the state parameter should be compared 
    to the state sent in the previous step

    var url = new Url(_openIdSettings.token_endpoint);

    //Get the tokens based on the code, using https://flurl.dev/docs/fluent-http/
    var token = url.PostUrlEncodedAsync(new
    {
        client_id = "authcodeflowclient",     
        client_secret = "mysecret",
        grant_type = "authorization_code",
        code_verifier = code_verifier,
        code = code,
        redirect_uri = "https://localhost:5001/CodeFlow/callback"

    }).ReceiveJson<Token>().Result;

    return View(token);
}

这篇关于错误代码500&无法取消对邮件的保护。重定向至标识服务器4中的客户端时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆