asp.net core系列 74 Identityserver4 授权许可类型应用场景分析

 一.概述

  在项目中做集成登录时,会使用到Identityserver4,在查看Identityserver4 官方文档后,会觉得文档介绍的不够全面和详细,这是因为它是基于oauth2.0和OpenID connect技术之上造轮子。要明白授权许可类型还需对oauth2.0技术有所了解,而ids4能够实现所有标准的授权许可类型。在ids4文档中也有介绍几个客户端的使用场景,那么再结合oauth2.0在全面掌握下授权许可类型应用场景分析。

  授权许可类型客户端有多种应用场景包括:原生应用、web应用、浏览器应用(单页面Javascript应用)。

  (1)web应用:oauth客户端最初的应用场景就是web应用,是运行在远程服务器上,需要通过web浏览器访问,应用的配置和运行时状态由web服务器维护,通常使用会话cookie与浏览器保持连接,这类应用能充分利用前端信道和后端信道两种信道方式,web应用很容易有效的使用授权码,客户端凭据,或者断言许可流程,由于浏览器一般不会将请求url中的片断部分发送给服务器,大多数情况下隐式许可流程不适用于web应用(但ids4中mvc客户端是web应用,示例使用了隐式许可流程)。

  (2)浏览器应用:浏览器应用完全运行在浏览器内,一般使用javascript(单页面应用程序)。虽然应用的代码确实需要由web服务器提供,但代码本身不在服务器上运行,web服务器也不会维护应用的任何运行时状态。这类很容易使用前端信道,通过http重定向将用户转至另一页面。但使用后端信道就有些复杂,因为浏览器应用受限于安全限制,防止跨站攻击,因此这类应用适合隐式许可流程。

  (3)原生应用:直接在最终用户的设备(计算机或者移动设备)上运行的应用。如控制台程序,移动开发,win开发等这类应用很容易使用后端信道,直接向远程服务器发送http请求。要使用前端信道会有些困难。

 

  1.1 oauth2.0授权许可类型

    授权许可类型指定客户端如何与令牌服务交互,也叫授权流程(Oauth flow)。在oauth2.0中授权许可类型包括:隐式许可类型、授权码许可类型、客户端凭据许可类型、资源拥有者凭据许可类型、断言许可类型。

 

  1.2 ids4授权许可类型

    IdentityServer支持所有oauth 标准授权类型,但对于常见的应用程序场景,您实际上只需要知道其中两种即可(code,ClientCredentials)。参考:https://identityserver4.readthedocs.io/en/latest/topics/grant_types.html 在ids4中授权许可类型配置是授权服务器Client.AllowedGrantTypes属性中,是一个集合类型,表示一个客户端可以支持多种授权许可类型,如下所示:

  public List<ClientGrantType> AllowedGrantTypes { get; set; }

    

    下面是ids4支持的授权许可类型:  

   1.3 通信信道

    在了解授权许可类型之前,必须要了解通信信道,包括:前端信道和后端信道。这里的信道是指oauth中角色与组件之间的交互方式,oauth是一个基于htttp的协议,但是oauth中的交互并不总是通过简单的http请求和响应来完成。

    后端信道: 后端信道通信是指http的请求和响应使用常规的http机制来通信:头部,查询参数,http方法。类似于使用httpclient发送请求一样。授权服务器提供了一个授权端点 /authorize,供客户端请求访问令牌和刷新令牌,客户端直接向该端点发出请求,携带一组表单格式的参数,授权服务器解析并处理这些参数,然后授权服务器返回一个代表令牌的json对象。

    前端信道:这是一种间接通信方法,而不是后端信道的直接通信方法,它将web浏览器作为媒介,使用http请求实现两个系统间的间接通信。实现了跨安全域工作,信息隔离(身份认证在授权服务器如:OpenID connect)。前端信道需要用到web浏览器和http重定向,是交互式认证授权常用的方法,如企业网使用微信或支付宝登录,都是通过前端信道。 由于使用web浏览器数据可能被篡改,OpenID connect要求客户端或者授权服务器对前端信息中消息签名,通过这样增加安全机制。

 

二.  授权许可类型

  2.1 Implicit   

     Implicit:隐式许可类型。完全运行在浏览器中的javascript应用就属于这种,是基于浏览器的应用,只使用前端信道与授权服务器通信。客户端向授权服务器的授权端点发送请求,通知授权服务器直接生成令牌返回。所有令牌都通过浏览器传输,不可用于获取刷新令牌,因为浏览器内的应用具有短暂性的特点。这种许可类型假设资源拥有者一直在场,必要时可以对客户端重新授权。客户端response_type值为token。

    如下所示:授权服务器白名单中配置了一个可交互式的client,使用隐式许可类型。

  // OpenID Connect implicit flow client (MVC)
        new Client
        {
            ClientId = "mvc",
            ClientName = "MVC Client",
            AllowedGrantTypes = GrantTypes.Implicit,

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

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

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

 

  2.2 ClientCredentials   

    ClientCredentials:客户端凭据许可类型。这种不需要基于浏览器应用,客户端代表自己,只能使用后端信道,如使用控制台程序的HttpClient类get或post请求来与授权服务器直接通信。这种客户端需要提供ClientId(用户名)和ClientSecret (密码)来获取访问令牌。客户端凭据许可流程中不会颁发刷新令牌,因为客户端通过用户名和密码能够随时获取新令牌。

    如下所示:客户端获取令牌的代码:

var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
    Address = disco.TokenEndpoint,

    ClientId = "client",
    ClientSecret = "secret",
    Scope = "api1"
});

     

  2.3 ResourceOwnerPassword

    ResourceOwnerPassword:资源拥有者凭据许可类型。客户端使用纯文本的用户名和密码发送到授权服务器,授权服务器收到请求取出用户名和密码,并与本地存储的用户信息对比,如果匹配则授权服务器向客户端颁发令牌,这种叫密码流程,只能通过后端信道通信。这种密码流程是资源拥有者直接与客户端交互,而不是授权服务器,客户端能够存储密码并随意使用。如果可以避免,请不要在生产中使用它,这种许可类型只能作为过度方案,用于那些原本就是直接索取用户名和密码登录的客户端现转入到oauth。应尽快将这样的客户端转到授权码许可流程上来。这种许可类型还可以生成刷新令牌,为客户端提供刷新令牌之后,它就不需要再保存用户的密码了。

    如下所示:客户端将以某种方式收集用户的密码,并在令牌请求期间将其发送到令牌服务。

var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
    Address = disco.TokenEndpoint,
    ClientId = "ro.client",
    ClientSecret = "secret",

    UserName = "alice",
    Password = "password",
    Scope = "api1"
});

 

  2.4 Hybrid

    Hybrid:混合流许可类型。在Implicit隐式流中,所有令牌都是通过浏览器传输的,这对于身份令牌是完全可以的。现在,我们还想请求访问令牌。访问令牌比身份令牌更敏感,该流程使我们两全其美,身份令牌是通过浏览器通道传输的,因此客户端可以在进行更多工作之前对其进行验证。如果验证成功,则客户端将打开通向令牌服务的反向通道以检索访问令牌。客户端提供了访问offline_access范围的权限-这允许为长期的API访问请求刷新令牌。

    如下所示:授权服务器白名单配置,与隐式许可类型差不多,添加了对api资源的访问。

new Client
{
    ClientId = "mvc",
    ClientName = "MVC Client",
    AllowedGrantTypes = GrantTypes.Hybrid,

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

    RedirectUris           = { "http://localhost:5002/signin-oidc" },
    PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

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

      参考: https://identityserver4.readthedocs.io/en/latest/quickstarts/5_hybrid_and_api_access.htm

  SaveTokens:mvc客户端的属性,设置为true, 那么OpenID Connect处理程序会自动为您保存令牌在cookie中。

 

  2.5 Code

    authorization code授权码许可类型。客户端将用户代理重定向到授权服务器端点,用户登录页,带上redirect_uri,在重定向到授权端点                     在identityserver4文档中,Code类型是用在了javascriptp客户端项目中,由于是用ajax来调用api, 需要在Web API项目中配置CORS,允许javascriptp客户端的ajax来访问。支持刷新令牌。

    (1) 通过浏览器执行的前端通道步骤,其中发生所有“交互”的事情,例如登录页面,同意等。此步骤生成代表前端通道操作结果的授权代码。

    (2) 反向通道步骤,其中步骤1中的授权代码与请求的令牌交换。此时,密钥客户端需要进行身份验证。

 

 

三. 选择正确的许可类型指引图

 

 

posted on 2022-12-27 10:40  花阴偷移  阅读(50)  评论(0编辑  收藏  举报

导航