IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

1.基于概念

OAuth2.0与身份认证协议的角色映射

IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

 IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

OpenID Connect 这个协议是2014颁发的,基于OAuth2.0,在这个协议中,ID Token会和Access Token一起发回客户端应用,它还提供了一个UserInfo这个端点,通过此端点可以获取用户信息,还提供了一级标识身份的scopes和claims(profile、email、address、phone)

 IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

这个协议定义了三个流程:

 IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

Identity Server4.0的结构图

IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

2.三种流程模式

IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

IdentityServer上:

在startup.cs页面中ConfiureServices页面中,应将json config 方式改为code config方式。即按如下方式切换注释代码

// in-memory, code config

            builder.AddInMemoryIdentityResources(Config.GetIdentityResources());

            builder.AddInMemoryApiResources(Config.GetApis());

            builder.AddInMemoryClients(Config.GetClients());

  // in-memory, json config

            //builder.AddInMemoryIdentityResources(Configuration.GetSection("IdentityResources"));

 //builder.AddInMemoryApiResources(Configuration.GetSection("ApiResources"));

//builder.AddInMemoryClients(Configuration.GetSection("clients"));

 

public static class Config

    {

        public static IEnumerable<IdentityResource> GetIdentityResources()

        {

            return new IdentityResource[]

            {

                new IdentityResources.OpenId(),

                new IdentityResources.Profile(),

            };

        }

        public static IEnumerable<ApiResource> GetApis()

        {

            return new ApiResource[]

            {

                new ApiResource("api1", "My API #1")

            };

        }

        public static IEnumerable<Client> GetClients()

        {

            return new[]

            {

                // client credentials flow client

                new Client

                {

                    ClientId = "console client",

                    ClientName = "Client Credentials Client",

                    AllowedGrantTypes = GrantTypes.ClientCredentials,

                    ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },

                    AllowedScopes = {"api1" }

                }              

            };

        }

   }

 

客户端控制台程序代码:

static async Task Main(string[] args)

        {

            //Discovery endpoint

            Console.WriteLine("Hello World!");

            var client = new HttpClient();

            var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");

            if(disco.IsError)

            {

                Console.WriteLine(disco.Error);

                return;

            }

            //Request access token,客户端必须带有:ClientCredentials

            var tokenResponse =await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest {

                Address = disco.TokenEndpoint,

                ClientId = "console client",

                ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",

                Scope= "api1"

            });

            if (tokenResponse.IsError)

            {

                Console.WriteLine(tokenResponse.Error);

                return;

            }

            var apiClient = new HttpClient();

            apiClient.SetBearerToken(tokenResponse.AccessToken);

            var response = await apiClient.GetAsync("http://localhost:5002/api/values");

            if (!response.IsSuccessStatusCode)

            {

                Console.WriteLine(response.StatusCode);

            }

            else

            {

                var content = await response.Content.ReadAsStringAsync();

                Console.WriteLine(content);

             }

asp.net core api资源应用:

public class Startup

     {

        public Startup(IConfiguration configuration)

        {

            Configuration = configuration;

        }

        public IConfiguration Configuration { get; }

 

        // This method gets called by the runtime. Use this method to add services to the container.

        public void ConfigureServices(IServiceCollection services)

        {         

            //使用IdentityServer认证和授权

            services.AddMvcCore().AddAuthorization().AddJsonFormatters();

            services.AddAuthentication("Bearer")

                .AddJwtBearer("Bearer", options =>

                {

                    options.Authority = "http://localhost:5000";

                    options.RequireHttpsMetadata = false;

                    options.Audience = "api1";

                });          

          }

           public void Configure(IApplicationBuilder app, IHostingEnvironment env)

           {   //使用identityserver

            app.UseAuthentication();

            app.UseMvc();

           }

  }

 

 

 

[Route("api/[controller]")]

    [Authorize]

    [ApiController]

    public class ValuesController : ControllerBase

    {

        // GET api/values

        [HttpGet]

        public ActionResult<IEnumerable<string>> Get()

        {

            return new string[] { "value1", "value2","value3"};

        }

总结:Client Credentials这种方式,客户端应用不代表用户,客户端应用本身就相当于是资源所有者;通常用于机器对机器的通信;客户端也需要身份认证。

IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

可采用工具软件监控客户端与服务端的通信:

IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式

将获取的access token放到网站https://jwt.io/,进行解码,即可以看到token中包含的许多用用信息。

IdentityServer4专题之五:OpenID Connect及其Client Credentials流程模式