计算机系统应用教程网站

网站首页 > 技术文章 正文

Kong认证插件OAuth 2.0认证详解

btikc 2024-09-18 08:40:20 技术文章 19 ℃ 0 评论

概述

向服务或者路由、消费者添加一个OAuth 2.0身份验证层,使其具有授权码授权、客户端凭证、隐式授权或资源所有者密码授权流程。

注意:按照OAuth2规范,此插件要求底层服务通过HTTPS提供。为了避免混淆,我们建议您在配置用于底层服务的路由时,使其仅接受HTTPS流量(通过其“protocols”属性)。

该示例配置内容如下:

  • kong的代理信息

IP地址:192.168.0.90(根据自己的部署情况调整为自己的ip)

代理服务端口:80、443(根据自己的部署情况调整为自己的端口)

  • 后端服务

地址:http://192.168.1.196/oauth2(根据实际情况,自己定义)

浏览访问效果:


  • Kong管理API工具

konga作为示例配置kong的管理工具。关于konga 的安装请参考,Linux 下源码安装Kong管理工具konga。

访问地址:http://192.168.0.90:1337

  • 上游请求头

在启用JWT认证插件之后,当客户端通过身份验证后,插件会在请求被代理到上游服务之前附加一些请求头信息,这样你就可以在代码中识别消费者:

  1. X-Consumer-ID:Kong中消费者的ID。
  2. X-Consumer-Custom-ID:Kong中消费者的custom_id(如果消费者设置了此值)。
  3. X-Consumer-Username:Kong中消费者的username(如果消费者设置了此值)。
  4. X-Credential-Identifier:凭证的标识符(只要消费者不是“匿名”消费者时有效)。
  5. X-Authenticated-Scope:以逗号分隔的最终用户已验证的作用域列表(仅当消费者不是“匿名”消费者时有效)。
  6. X-Authenticated-Userid:已向客户端授予权限的登录用户ID(仅当客户端不是“匿名”客户端时有效)。
  7. X-Anonymous-Consumer:基本身份认证中设置了匿名的消费者,在客服端认证失败是,此值为true。

您可以使用以上信息来实现相关的业务逻辑。您可以使用X-Consumer-ID值来获取有关该消费者的更多信息。

端点介绍

默认情况下,当客户端通过代理端口使用底层服务时,OAuth 2.0插件侦听以下端点:

  • /oauth2/authorize:授权服务器的端点,在授权码流程中提供授权代码或隐式授权流程中提供访问令牌。只支持POST方式请求。
  • /oauth2/token:提供访问令牌的授权服务器的端点。用于客户端凭证和密码授权流程的唯一端点。只支持POST方式请求。
  • /oauth2_tokens:创建新令牌的授权服务器的端点。
  • /oauth2_tokens/:token_id:允许读取、修改和删除访问令牌的授权服务器的端点。

尝试授权和请求访问令牌的客户端必须使用这些端点。请记住,上面的端点必须与正确的URI路径或请求头相结合,您通常使用它们来匹配通过Kong的已配置路由。

其中URI的路径解析为:

服务:如果配置在服务下则为服务访问路径+上面的端点路径

路由:如果配置在路由下则为路由访问的路径+上面的端点路径

消费者:如果配置在消费者下则为kong的代理服务的路径+上面的端点路径

创建服务及路由

  • 创建服务

通过konga的管理菜单SERVICES,添加一个服务。


维护对应的name及url即可。其中name为:outh2_auth_example、url的地址为http://192.168.1.196/。

  • 创建路由

通过konga的管理菜单SERVICES,可以看到上面添加的“outh2_auth_example”服务。然后点击此服务,进入服务的详情页面。


在服务的详情页面点击左侧导航的“Routes”,进行服务下路由的管理操作,按如下操作创建一个新路由。


把属性Paths设置为/oauth2然后回车(记得一定要回车,不然值添加不上),Path handling设置v0,Strip Path设置:NO,Protocols的值为https,因为OAuth 2.0的服务必须通过HTTPS提供服务。这些属性的详解,请参考Kong 管理API详解之八——路由对象 。

添加SSL证书

在完成路由的添加操作之后,由于OAuth 2.0的服务必须通过HTTPS提供。所以需要提供对应域名及证书。

域名解析过程这里不再赘述,SSL证书可以通过阿里云来申请。

示例域名为:xxxx.com

  • 通过阿里云下载SSL证书

在阿里云申请完SSL证书以后,在下载中选择Apache的证书进行下载。

  • 维护SSL证书

通过konga的管理菜单CERTIFICATES,添加一个证书。


属性介绍

Certificate:下载的阿里云ssl证书里面以_public.crt结尾的证书内容。

Key:下载的阿里云ssl证书里面以.key结尾的证书内容。

Server Name Indications:申请SSL证书的域名。

已上操作完成之后,即完成了一个通过路由代理转发后端服务的配置。可以通过上面提供的kong代理服务的信息访问代理后的效果地址为:https://xxxx.com/oauth2。


可以看到跟直接访问后端服务页面效果一样。

在服务或路由上添加插件Oauth2

根据实际场景选择是在服务或路由上添加插件,只是插件作用域的范围不一样,如果在服务上添加插件,则对服务下的所有路由都生效。如果在路由上添加插件,则只作用该路由本身。该示例演示通过在路由上添加插件。

  • Oauth2插件参数介绍
  1. name(必须):插件的名称,值为oauth2。数据类型:string。
  2. service.id(半可选,即:与route.id两者有一个必须):插件目标服务的ID(通过管理api配置时指定)。数据类型:string。
  3. route.id(半可选,即:与service.id两者有一个必须):插件目标路由的ID(通过管理api配置时指定)。数据类型:string。
  4. enabled(必须):是否应用此插件。数据类型:boolean,默认值:true。
  5. config.scopes(必须):描述将供最终用户使用的范围名称数组。
  6. config.mandatory_scope(可选):布尔值,告诉插件至少需要一个作用域才能得到最终用户的授权。默认值:false。
  7. config.token_expiration(可选):整数值,告诉插件一个令牌应该持续多少秒,之后客户端需要刷新令牌。设置为0则永远不过期。默认值:7200。
  8. config.enable_authorization_code(可选):布尔值,是否启用授权码授权流程。默认值:false。
  9. config.enable_client_credentials(可选):布尔值,是否启用客户端凭证授权流程。默认值:false。
  10. config.enable_implicit_grant(可选):布尔值,是否启用隐私授权授权流程。默认值:false。
  11. config.enable_password_grant(可选):布尔值,是否启用密码授权授权流程。默认值:false。
  12. config.auth_header_name(可选):携带访问令牌的请求头名称。默认值:authorization。
  13. config.hide_credentials(可选):插件显示或隐藏来自上游服务的凭据。如果值为true,插件将在代理之前从请求中删除凭证(即授权相关的请求头),即是否把客户端请求头中的认证凭证发送至后端服务。数据类型:boolean,默认值:false。
  14. config.accept_http_if_already_terminated(可选):接受已被代理或负载平衡器终止且已将x-forwarded-proto: https请求头添加到请求中的HTTPS请求。只有当Kong服务器不能被公开访问并且唯一的入口点是这样的代理或负载均衡器时才启用此选项。
  15. config.anonymous(可选):一个可选的字符串(消费者uuid)值,在身份验证失败时用作“匿名”的消费者。如果为空,在请求将失败时,身份验证失败则提示4xx相关内容。请注意,这个值必须引用Kong内部的消费者id属性,而不是它的custom_id。数据类型:string。默认值:kong。
  16. config.global_credentials(可选):布尔值,允许使用其他服务配置为config.global_credentials=true的OAuth 2.0的插件生成相同OAuth认证凭证。默认值:false。
  17. config.refresh_token_ttl(可选):整数值,用于生成一个新的访问令牌,标识一个令牌/刷新令牌对在多少秒内有效。如果值为0,则令牌/刷新令牌对无限期有效。默认值:1209600。
  18. config.reuse_refresh_token(可选):布尔值,指示刷新访问令牌时是否持久化OAuth刷新令牌。默认值:false。
  19. config.hash_secret(可选):布尔值,指示OAuth client_secret是否将以散列格式存储。如果在现有的插件实例上启用,客户端秘钥会在第一次使用时被快速散列。默认值:false。
  20. config.pkce(可选):指定插件处理代码交换的证明键(PKCE)的模式。可能的模式是none,lax和strict。strict模式在所有客户端的授权和令牌端点上强制实施PKCE。lax模式对公共客户端强制执行PKCE,但对客户端凭证不强制执行。none模式不会在任何客户端强制PKCE。在任何情况下,如果客户端在授权端点上请求PKCE,也会在令牌端点上强制执行PKCE。

选项' config.refresh_token_ttl '只在版本' 0.12.0 '及更高版本中可用。

一旦应用此插件,任何具有有效凭证的用户都可以访问该服务。要将使用限制为只有一些经过身份验证的用户,还需要添加ACL插件并创建允许或拒绝的用户组

  • 在路由上添加插件

通konga菜单ROUTES可以获取所有路由的列表,找到刚才添加的路由。然后点击进去可以看到该路由的详情页面。


通过该路由左侧的导航菜单中的“Plugins”管理该路由的插件。通过添加插件,选择插件导航中的“Authentication”,然后选择其列表中的“Oauth2”,不用填写任何内容直接添加即可。这样就完成了基本身份证认证插件的添加操作。


添加Oauth2插件。

默认全部使用缺省值,添加完成之后可以看到插件列表里面包含了此插件。


当您再次访问https://xxxx.com/oauth2,则会提示相应的错误信息。


此时要访问页面则需要提供有效的认证凭证。所以需要为该插件配置对应的认证凭证,而有效认证凭证信息是需要通过安全插件的ACL插件进行添加。

  • 维护及配置认证凭证(消费者)

1.添加消费者

通过konga的菜单CONSUMERS,添加一个消费者。


在属性usernamne中输入consumers,然后添加即可。

消费者参数介绍

username(半可选即:与custom_id两者有一个必须):消费者的用户名。

custom_id(半可选即:与username两者有一个必须):用于将使用者映射到另一个数据库的自定义标识符。

2.添加消费者下工作组

在消费者详情页面上面的导航中点击“Groups”,添加工作组。


在Group name 属性值中输入工作组名称:consumer_group,一定要记住此工作组的名称,作为后面维护ACL插件时使用。

3.添加消费者下面的OAUTH2身份认证的凭证

在消费者详情页面上面的导航中点击“Credentials”,然后通过左侧导航中的OAUTH2完成身份证认证凭证的添加操作。


添加认证凭证。


记住这里维护的name的值为oauth2_auth,client_id的值为auth_client_id,client_secret的值为auth_client_secret,redirect_uris根据自己的实际情况维护,作为后面认证的凭证。

属性介绍:

name(必须):要关联到凭证的名称。在OAuth 2.0中,这将是应用程序的名称。

client_id(可选):设置自己的唯一client_id。如果缺少,插件将生成一个。

client_secret(可选):设置自己的唯一client_secret。如果缺少,插件将生成一个。

redirect_uris(必须):应用程序中的一个或多个url数组,授权后用户将被发送到该数组。

4.通过插件ACL为路由添加认证凭证

进入上面维护的路由的详情中的路由列表,添加ACL插件。选择插件导航中的“Security”,然后选择其列表中的Acl。


维护Acl插件信息。


在allow的属性上输入上面维护的消费者下工作组的名称consumer_group回车即可。

OAuth 2.0认证授权流程

  • 客户端凭证授权

客户端凭证认证流程开箱即用,不需要构建任何授权页面。客户端需要使用/oauth2/token端点来请求访问令牌。

例如通过Postman获取访问令牌。

因为示例是插件时配置路由下,路由路径为/oauth2,则获取访问令牌的路径为:/oauth2/oauth2/token


请求地址:https://xxx.com/oauth2/oauth2/token

请求参数信息:?client_id=auth_client_id&client_secret=auth_client_secret&grant_type=client_credentials

响应结果信息:

{

"token_type": "bearer",

"access_token": "KAoMLyYIHUe6vixoxPxn6IE409jZ7bMz",

"expires_in": 7200

}

发送认证请求


请求地址:https://xxx.com/oauth2

请求头信息:Authorization=KAoMLyYIHUe6vixoxPxn6IE409jZ7bMz

  • 授权码授权

该授权访问令牌获取分为两步,第一步先获取授权码,第二步通过授权码获取访问令牌。

因为示例是插件时配置路由下,路由路径为/oauth2,则获取访问令牌的路径为:/oauth2/oauth2/authorize

首先获取一个授权码。


请求地址:https://xxx.com/oauth2oauth2/authorize

请求参数信息:

client_id:auth_client_id

provision_key:NcmgDkwYS6TvwNg1H3HrO4MErP5bpx6U

response_type:code

scope:user

authenticated_userid:custom_userid

参数详解:

client_id:创建消费者Oauth2中认证凭证的client id的值。

provision_key:在服务或路由添加Oauth2插件时,手动指定或系统自动生成的值。

response_type:固定值code。

scope:在服务或路由添加Oauth2插件时,设置的对应作用域列表。根据配置config.mandatory_scope的值是否为true,确定是否设置此参数,如果config.mandatory_scope的值为fase可以省略此参数。后端服务可通过请求头x-authenticated-scope获取该值。

authenticated_userid:授权登录的用户id,根据实际情况进行自定义设置,作为授权登录应用的授权用户信息。后端服务可通过请求头x-authenticated-userid获取该值。

响应结果:

{

"redirect_uri": "https://auth.zzstxx.com/?code=CUodSWUBkrpRdUtMr1QePpL0YSq2Ob6g"

}

通过授权码获取访问令牌。


请求地址:https://xxx.com/oauth2/oauth2/token

请求参数信息:

client_id:auth_client_id

client_secret:auth_client_secret

grant_type:authorization_code

code:ZVZLUa9rdg3EPwq8PrivTnfPxJrUzINR

参数详解:

client_id:创建消费者Oauth2中认证凭证的client id的值。

client_secret:创建消费者Oauth2中认证凭证的client_secret的值。

grant_type:固定值authorization_code

code:上一步获取的返回内容中的参数code的值,只能使用一次。

响应结果:

{

"refresh_token": "gtNtATBJ2HjUnMZi9MHUhRMG3EISMBF8",

"token_type": "bearer",

"access_token": "EKWRtszXHiMZ9hrE6BjW1w289yvsDxdn",

"expires_in": 7200

}

发送认证请求


请求地址:https://xxx.com/oauth2

请求头信息:Authorization=EKWRtszXHiMZ9hrE6BjW1w289yvsDxdn

  • 密码授权

因为示例是插件时配置路由下,路由路径为/oauth2,则获取访问令牌的路径为:/oauth2/oauth2/token


请求地址:https://xxx.com/oauth2/oauth2/token

请求参数信息:

client_id:auth_client_id

client_secret:auth_client_secret

grant_type:password

scope:user

authenticated_userid:custom_userid

参数详解:

client_id:创建消费者Oauth2中认证凭证的client id的值。

client_secret:创建消费者Oauth2中认证凭证的client_secret的值。

grant_type:固定值password

scope:在服务或路由添加Oauth2插件时,设置的对应作用域列表。根据配置config.mandatory_scope的值是否为true,确定是否设置此参数,如果config.mandatory_scope的值为fase可以省略此参数。后端服务可通过请求头x-authenticated-scope获取该值。

authenticated_userid:授权登录的用户id,根据实际情况进行自定义设置,作为授权登录应用的授权用户信息。后端服务可通过请求头x-authenticated-userid获取该值。

响应结果:

{

"refresh_token": "HuzyVcUXbVFbpAiYtFM5EQfqC2TClyle",

"token_type": "bearer",

"access_token": "waUJRK3JgBzgE7wFP9yd2k45pEgPQ55R",

"expires_in": 7200

}

发送认证请求


请求地址:https://xxx.com/oauth2

请求头信息:Authorization=waUJRK3JgBzgE7wFP9yd2k45pEgPQ55R

迁移访问令牌

如果您正在迁移您现有的OAuth 2.0应用程序并通过令牌访问Kong,那么您可以:

  • 通过创建OAuth 2.0应用程序迁移消费者和应用程序。
  • 使用Kong的管理API中的/oauth2_tokens端点迁移访问令牌。例如:
curl -X POST http://kong:8001/oauth2_tokens \
    --data 'credential.id=KONG-APPLICATION-ID' \
    --data "token_type=bearer" \
    --data "access_token=SOME-TOKEN" \
    --data "refresh_token=SOME-TOKEN" \
    --data "expires_in=3600"

参数介绍:

credential(必须):包含在Kong上创建的OAuth 2.0应用程序的ID。

token_type(可选):令牌类型。默认值:bearer。

access_token(可选):您可以选择设置自己的访问令牌值,否则将生成一个随机字符串。

refresh_token(可选):您可以选择设置自己唯一的刷新令牌值,否则将生成一个随机字符串。

expires_in(必须):访问令牌的过期时间(以秒为单位)。

scope(可选):与令牌关联的授权范围。

authenticated_userid(可选):授权应用程序的用户的自定义ID。

查看和销毁访问令牌

可以使用管理API列出和修改活动令牌。通过GET 访问/oauth2_tokens端点返回以下内容:

curl -sX GET http://kong:8001/oauth2_tokens/
{
  "total": 2,
  "data": [
    {
      "expires_in": 7200,
      "created_at": 1523386491000,
      "access_token": "FOEtUHwg0das9PhsasVmgMGbZn7nWSgK",
      "credential_id": "2c74324f-fa2d-434b-b6de-bd138652158f",
      "scope": "email",
      "id": "610740e5-700a-45f0-889a-5c7f0422c48d",
      "api_id": "898dfc5f-20f9-4315-a028-2ecb0193f834",
      "token_type": "bearer"
    },
    {
      "expires_in": 7200,
      "created_at": 1523386680000,
      "access_token": "58eat7UHEiPOmjNb16uQAxt4vu3fbu95",
      "credential_id": "2c74324f-fa2d-434b-b6de-bd138652158f",
      "scope": "email",
      "id": "edff2fc7-1634-4fb5-b714-de9435531e10",
      "api_id": "898dfc5f-20f9-4315-a028-2ecb0193f834",
      "token_type": "bearer"
    }
  ]
}

credential_id是kong:8001/consumers/{consumer_id}/oauth2和有效令牌的API或服务的api_id或service_id的OAuth应用程序的ID。

注意:expires_in是静态的,不会根据间进行递减:您必须将其添加到created_at以计算该令牌何时到期。

通过DELETE http://kong:8001/oauth2_tokens/<token ID>跨域删除令牌,立即使令牌无效。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表