IdentityServer3: промежуточное ПО OWIN Katana выдает ошибку invalid_client, так как не может получить токен

Мы используем IdentityServer3 в качестве поставщика удостоверений и промежуточное ПО OWIN Katana для установления связи на основе OpenId Connect. Аутентификация работает нормально, поскольку мы были перенаправлены на сервер идентификации и обратно на исходный веб-сайт. Но проблема invalid_client возникает, когда я пытаюсь получить токены и получить утверждения в «OpenIdConnectAuthenticationNotifications».

Пожалуйста, проверьте код (класс запуска) ниже и прикрепленный снимок экрана.

public sealed class Startup
{   
    public void Configuration(IAppBuilder app)
    {
        string ClientUri = @"https://client.local";
        string IdServBaseUri = @"https://idm.website.com/core";l
        string TokenEndpoint = @"https://idm.website.com/core/connect/token";
        string UserInfoEndpoint = @"https://idm.website.com/core/connect/userinfo";
        string ClientId = @"WebPortalDemo";
        string ClientSecret = @"aG90apW2+DbX1wVnwwLD+eu17g3vPRIg7p1OnzT14TE=";

        //AntiForgeryConfig.UniqueClaimTypeIdentifier = "sub";
        JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies"
        });

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            ClientId = ClientId,
            Authority = IdServBaseUri,
            RedirectUri = ClientUri,
            PostLogoutRedirectUri = ClientUri,
            ResponseType = "code id_token token",
            Scope = "openid profile roles",
            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name",
                RoleClaimType = "role"
            },
            SignInAsAuthenticationType = "Cookies",

            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                AuthorizationCodeReceived = async n =>
                {
                    // use the code to get the access and refresh token
                    var tokenClient = new TokenClient(
                        TokenEndpoint,
                        ClientId,
                        ClientSecret);

                    var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);

                    if (tokenResponse.IsError)
                    {
                        throw new Exception(tokenResponse.Error);
                    }

                    // use the access token to retrieve claims from userinfo
                    var userInfoClient = new UserInfoClient(UserInfoEndpoint);

                    var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                    // create new identity
                    var id = new ClaimsIdentity(n.AuthenticationTicket.Identity.AuthenticationType);
                    //id.AddClaims(userInfoResponse.GetClaimsIdentity().Claims);
                    id.AddClaims(userInfoResponse.Claims);

                    id.AddClaim(new Claim("access_token", tokenResponse.AccessToken));
                    id.AddClaim(new Claim("expires_at", DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
                    id.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                    id.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                    id.AddClaim(new Claim("sid", n.AuthenticationTicket.Identity.FindFirst("sid").Value));

                    n.AuthenticationTicket = new AuthenticationTicket(
                        new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role"),
                        n.AuthenticationTicket.Properties);
                },

                RedirectToIdentityProvider = n =>
                {
                    // if signing out, add the id_token_hint
                    if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
                    {
                        var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");

                        if (idTokenHint != null)
                        {
                            n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
                        }

                    }

                    return Task.FromResult(0);
                }
            }

        });
    }
}

введите здесь описание изображения

Конфигурация клиента в IdSvr3 была указана для использования гибридного потока, и я много раз проверял, что идентификатор клиента и секрет клиента, чтобы убедиться, что они верны.

Вот конфигурация клиента на стороне сервера:

введите здесь описание изображения


person TejSoft    schedule 04.05.2017    source источник
comment
Что говорят журналы сервера идентификации?   -  person rawel    schedule 04.05.2017
comment
Где я могу найти журналы сервера идентификации?   -  person TejSoft    schedule 04.05.2017
comment
identityserver.github.io/Documentation/docsv2/configuration/   -  person rawel    schedule 04.05.2017


Ответы (1)


Мне удалось решить проблему, просмотрев журналы, созданные сервером идентификации. В журналах говорилось, что секрет клиента неверен, когда я несколько раз проверял, точно ли секрет соответствует тому, что показывалось на сервере идентификации. Но потом я понял, что секретом должен быть сам текст, а НЕ хешированный. Модифицированный код, который работал, приведен ниже:

string ClientId = @"WebPortalDemo";
//string ClientSecret = @"aG90apW2+DbX1wVnwwLD+eu17g3vPRIg7p1OnzT14TE="; // Incorrect secret, didn't work
string ClientSecret = @"love"; // Actual text entered as secret, worked

Кредит: @rawel

person TejSoft    schedule 08.05.2017