Как получить токен OAuth2 OpenId из Identity Server 4 для клиента, использующего OWIN - PullRequest
0 голосов
/ 08 января 2019

Я использую IdentityServer4, чтобы получить токены OpenId для моего веб-приложения. Но мое веб-приложение использует Owin для безопасности. Я не могу найти примеры примеров того, где это делается.

Так что этот код работает; В моем клиенте;

using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
using SIR.API.Caller.Helpers;

namespace SIR.API.Caller
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = Settings.SignInAsAuthenticationType    // "Cookies";
            });

            app.UseOpenIdConnectAuthentication(openIdConnectOptions: new OpenIdConnectAuthenticationOptions
            {
                AuthenticationType = "oidc",
                Authority = Settings.AuthorityUrl1,      //ID Server,  "https://localhost:44314/"; https://localhost:44307/
                ClientId = Settings.ClientId,           // "SIR"
                Scope = Settings.Scope,                 // "openid profile";
                ResponseType = Settings.ResponseType,   // "id_token code";
                SignInAsAuthenticationType = Settings.SignInAsAuthenticationType,
                //--------------------------------------// "Cookies";
                RedirectUri = Settings.RedirectUri,     // URL of website, http://localhost:50000/signin-oidc;
                //RedirectUri = Settings.RedirectUri1,     // URL of website, http://localhost:53200/signin-oidc;
                RequireHttpsMetadata = Settings.RequireHttpsMetadata,
                //--------------------------------------// true
                ClientSecret = "secret"
            });

            app.Use(async (ctx, next) =>
            {
                var message = ctx.Authentication.User.Identity.IsAuthenticated
                    ? $"User: {ctx.Authentication.User.Identity.Name}"
                    : "User Not Authenticated";
                await next();
            });
        }
    }
}

На моем сервере ID 4 запускается:

using System.Security.Cryptography.X509Certificates;
using IdentityServer4;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Mulalley.IdentityServer4.Helpers;
using QuickstartIdentityServer;

namespace Mulalley.IdentityServer4
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            // configure identity server with in-memory stores, keys, clients and scopes
            services.AddIdentityServer()
                //.AddDeveloperSigningCredential()
                .AddSigningCredential(new X509Certificate2(Settings.CertPath, Settings.Password))
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddTestUsers(Config.GetUsers());

            services.AddAuthentication()
                .AddGoogle("Google", options =>
                {
                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;

                    // register your IdentityServer with Google at https://console.developers.google.com
                    // enable the Google+ API
                    // set the redirect URI to http://localhost:port/signin-google
                    options.ClientId = "copy client ID from Google here";
                    options.ClientSecret = "copy client secret from Google here";
                })
                .AddOpenIdConnect("oidc", "OpenID Connect", options =>
                {
                    options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                    options.SignOutScheme = IdentityServerConstants.SignoutScheme;

                    options.Authority = "https://demo.identityserver.io/";
                    options.ClientId = "implicit";

                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        NameClaimType = "name",
                        RoleClaimType = "role"
                    };
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseIdentityServer();
            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }
    }
}

и Config.cs есть;

using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System.Collections.Generic;
using System.Security.Claims;

namespace QuickstartIdentityServer
{
    public class Config
    {
        // scopes define the resources in your system
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("SIR", "Service Inspection Report")
            };
        }

        // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            var baseUri = "http://localhost:53200/";
            // client credentials client
            return new List<Client>
            {
                new Client
                {
                    ClientId = "client",
                    AllowedGrantTypes = GrantTypes.ClientCredentials,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "SIR" },
                    AlwaysIncludeUserClaimsInIdToken = true
                },

                // resource owner password grant client
                new Client
                {
                    ClientId = "ro.client",
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = { "SIR" },
                    AlwaysIncludeUserClaimsInIdToken = true
                },

                // OpenID Connect hybrid flow and client credentials client (MVC)
                new Client
                {
                    ClientId = "SIR",
                    ClientName = "SIR",
                    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },

                    RedirectUris = { baseUri + "signin-oidc" },
                    PostLogoutRedirectUris = { baseUri + "signout-callback-oidc" },

                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "SIR"
                    },
                    AllowOfflineAccess = true,
                    AlwaysIncludeUserClaimsInIdToken = true
                }
            };
        }

        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>
            {
                new TestUser
                {
                    SubjectId = "1",
                    Username = "alice",
                    Password = "password",

                    Claims = new List<Claim>
                    {
                        new Claim("name", "Alice"),
                        new Claim("website", "https://alice.com")
                    }
                },
                new TestUser
                {
                    SubjectId = "2",
                    Username = "bob",
                    Password = "password",

                    Claims = new List<Claim>
                    {
                        new Claim("name", "Bob"),
                        new Claim("website", "https://bob.com")
                    }
                }
            };
        }
    }
}

И вопрос в том, как мне получить токен в C #, чтобы я мог на него взглянуть? И как мне установить GetClaimsFromUserInfoEndpoint = true, который недоступен в OWIN? Есть ли примеры кода, на которые я могу посмотреть с OWIN-доступом к ID4?

РЕДАКТИРОВАТЬ: Этот код, кажется, то, что мне нужно: https://identitymodel.readthedocs.io/en/latest/client/token.html

Однако я ввел код и получил токен доступа, который при вводе в jwt.io выдает сообщение «Недопустимая подпись».

       private static async Task<TokenResponse> GetClientCredentialsTokenResponse()
        {
            var client = new HttpClient();
            var tokenRequest = new ClientCredentialsTokenRequest
            {
                Address = Settings.AuthorityUrl1 + "connect/token",
                ClientId = Settings.ClientId,
                ClientSecret = "secret",
                Scope = "SIR"
            };

            return await client.RequestClientCredentialsTokenAsync(tokenRequest);
        }

        private static async Task<TokenResponse> GetTokenResponse()
        {
            var client = new HttpClient();
            var tokenRequest = new TokenRequest
            {
                Address = Settings.AuthorityUrl1 + "connect/token",
                GrantType = GrantType.ClientCredentials,

                ClientId = Settings.ClientId,
                ClientSecret = "secret",

                Parameters =
                {
                    {"scope", "SIR"}
                }
            };

            return await client.RequestTokenAsync(tokenRequest);
        }

        private static void ThrowResponseException(TokenResponse response)
        {
            const string message = "Problem accessing the UserInfo endpoint";
            if (response.Exception == null)
            {
                throw new Exception($"{message}: {response.Error}. {response.ErrorDescription}.");
            }

            throw new Exception(message, response.Exception);
        }
    }
}
...