前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于Keycloak的Grafana SSO身份认证过程剖析

基于Keycloak的Grafana SSO身份认证过程剖析

原创
作者头像
qugeppl
修改2021-09-17 10:29:40
7.2K1
修改2021-09-17 10:29:40
举报
文章被收录于专栏:PulseLine

Keycloak是一款主流的IAM(Identity and Access Management 的缩写,即“身份识别与访问管理”)开源实现,它具有单点登录、强大的认证管理、基于策略的集中式授权和审计、动态授权、企业可管理性等功能。

结合我们项目内的过往使用经验,本篇文章,将介绍:

1、一键式Keycloak安装;

2、配置Grafana,使接入Keycloak进行单点登录;

3、分析Grafana SSO登录过程,从而帮助用户更理解OAuth2的交互过程;

下图就是最终的过程图示:

1、一键式Keycloak安装

基于项目需要,我们在使用Keycloak时,需要外接企业微信的认证方式,鉴于Keycloak已有的Social Login并不支持企业微信,我们对此作出了扩展, https://github.com/qugeppl/keycloak-social-wecom ,并基于官方的12.0.4镜像做了无感扩展,可直接以容器方式启动:

代码语言:javascript
复制
docker run -it --name keycloak-wecom -p 80:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin qugeppl/keycloak-social-wecom:12.0.4.1

2、配置Keycloak

2.1 Grafana的OAuth接入

这里我们重点以Grafana的通用OAuth2接入能力https://grafana.com/docs/grafana/latest/auth/generic-oauth/

可以看到,对Grafana来说,天生支持了OAuth协议的sso过程,只需要添加一些配置(其他非必填,我们先只关注基础的部分)

代码语言:javascript
复制
[auth.generic_oauth]
enabled = true
client_id = YOUR_APP_CLIENT_ID
client_secret = YOUR_APP_CLIENT_SECRET
scopes =
empty_scopes = false
auth_url =
token_url =
api_url =
root_url =

Grafana或者其他任意需要SSO登录的组件,其实都是Keycloak(或者其他IAM)里的一个Client,所以需要去Keycloak创建出这个client,并且拿到对应的信息;

2.2 Keycloak配置

  1. 访问

上述步骤安装后的Keycloak ip,例如可以是http://localhost, 会自动打开如下页面,从管理员界面进行登录,账号密码如步骤1中的环境变量所设置 admin/admin

2. 创建新域Test (Master是顶级域,一般不建议使用)

3.在Test域创建Client,命名为grafana

补充其他必须信息,保存

拿到client secret

2.3 填充Grafana配置信息

几个url信息从哪里得到?参照Keycloak官方文档的指引, https://www.keycloak.org/docs/latest/server_admin/index.html

发现有endpoint现成提供

代码语言:javascript
复制
<root>/auth/realms/{realm-name}/.well-known/openid-configuration

like:
http://localhost/auth/realms/Test/.well-known/openid-configuration

访问得到的结果在这里啦

代码语言:javascript
复制
{
    "issuer":"http://local/auth/realms/Test",
    "authorization_endpoint":"http://localhost/auth/realms/Test/protocol/openid-connect/auth",
    "token_endpoint":"http://localhost/auth/realms/Test/protocol/openid-connect/token",
    "introspection_endpoint":"http://localhost/auth/realms/Test/protocol/openid-connect/token/introspect",
    "userinfo_endpoint":"http://localhost/auth/realms/Test/protocol/openid-connect/userinfo",
    "end_session_endpoint":"http://localhost/auth/realms/Test/protocol/openid-connect/logout",
    "jwks_uri":"http://localhost/auth/realms/Test/protocol/openid-connect/certs",
    "check_session_iframe":"http://localhost/auth/realms/Test/protocol/openid-connect/login-status-iframe.html",
    "grant_types_supported":[
        "authorization_code",
        "implicit",
        "refresh_token",
        "password",
        "client_credentials"
    ],
    ...省略了其他无关信息
}

所以,这里基本的配置都有了

代码语言:javascript
复制
[auth.generic_oauth]
enabled = true
name = Test
allow_sign_up = true
client_id = grafana
client_secret = ******  #这个在keycloak->client id=grafana->credential找到
scopes = openid email   #这里要注意,openid这个是一定要有的,email的话,表示登录成功后,可以授权拿到用户的email信息
auth_url = http://localhost/auth/realms/Test/protocol/openid-connect/auth  #第一步登录
token_url = http://localhost/auth/realms/Test/protocol/openid-connect/token #第二步获取token
api_url = http://localhost/auth/realms/Test/protocol/openid-connect/userinfo #第三部获取user信息

root_url = http://grafanaip:port #这里是grafana的地址一定要注意,grafana 认证成功并且存入grafana session后,会将用户redirect这个地址,就是grafana首页
role_attribute_path = role #这里是读取用户Atrribute里的某个字段来解析用户登录到Grafana的角色
  

上面的role_attribute_path 可以更近一步在官方文档中找到说明:

https://grafana.com/docs/grafana/latest/auth/generic-oauth/#role-mapping

对应的keycloak里grafana client需要配置在userinfo时候,返回用户的role属性

用户的属性信息里role是哪里来的呢,其实可以配置给用户登录的时使用的IDP Mapper,如下图的意思是,用户登录后,自动给用户匹配被硬编码的“Admin”字符串

当然既然都是管理员,那可不可以不这么麻烦,直接在grafana配置不就好了么,于是参照grafana文档及测试,得到了如下配置,节省了keycloak的用户角色配置

代码语言:javascript
复制
role_attribute_path ='True'&&'Admin'

3. Grafana SSO登录过程分析

按照上述的步骤,你的grafana配置好后,已经能够使用keycloak进行登录了(需要在Keycloak创建用户):

当然你需要在Keycloak的Test域下创建一个用户,或者直接使用企业微信扫码登录(这里需要企业应用的一些信息)

一般情况下,第三方软件以oauth2接入keycloak时,都需要提供三个url

代码语言:javascript
复制
auth_url = http://localhost/auth/realms/PulseLine/protocol/openid-connect/auth  #第一步登录
token_url = http://localhost/auth/realms/PulseLine/protocol/openid-connect/token #第二步获取token
api_url = http://localhost/auth/realms/PulseLine/protocol/openid-connect/userinfo #第三部获取user信息

(第三方软件外部用)auth_url:浏览器访问时,第三方软件(Grafana)靠此url使用户浏览器转向Keycloak的认证登录界面,用户在Keycloak登录成功后,keycloak会生成一个针对该用户的code(这个code只能使用一次,用于换取token),并返回给浏览器,并指定下一跳的url.(这个url是用户指定的第三方软件中能够处理code的url,即callback)

(第三方软件内部用)token_url:浏览器按照上一步第三方软件转向地址,携带code进行访问,第三方软件内部收到请求后使用token_url以及code,和keycloak通信交换出这个用户的access_token。

(第三方软件内部用)api_url:第三方软件内部使用api_url,以及上一步的access_token与keycloak通信,获取这个用户的详细信息后,内部注册用户并存储session,最后将浏览器重定向到第三方软件首页(因为已经存储了第三方软件的session,所以直接保持登录态)

第一个请求authenticate,请求keycloak登录授权

代码语言:javascript
复制
http://localhost/auth/realms/Test/login-actions/authenticate?session_code=TqvBA9opgD0HDGZIgKIo3bRHa6k9kCmB_pBu1ISuOGE&execution=3b27c26c-883e-47f1-b999-c6f003f7f4ec&client_id=grafana&tab_id=FymTJ3TfBXA
​
#此时用户输入账号密码,点击登录,认证成功后

#该请求的responseHeader看出,keycloak登录成功,客户端可以转向grafana了,并给予了keycloak的code
http://localhost:3000/login/generic_oauth?state=dFgc4PlQAA_7f8b6D6g-N4lWn8fWI-EnEVpcy1sJ-o8%3D&session_state=c78927fc-37bd-4d00-8cc8-c23c8f5d1989&code=9d4a337c-83f2-4940-a079-4185020c883a.c78927fc-37bd-4d00-8cc8-c23c8f5d1989.27cb44d1-7d6b-46a9-966b-cdaa49a7f9f5

第二个请求则为第一个请求中keycloak让客户端登录keycloak登录成功后转向

代码语言:javascript
复制
http://localhost:3000/login/generic_oauth?state=dFgc4PlQAA_7f8b6D6g-N4lWn8fWI-EnEVpcy1sJ-o8%3D&session_state=c78927fc-37bd-4d00-8cc8-c23c8f5d1989&code=9d4a337c-83f2-4940-a079-4185020c883a.c78927fc-37bd-4d00-8cc8-c23c8f5d1989.27cb44d1-7d6b-46a9-966b-cdaa49a7f9f5
​
#这里grafana会拿到code,并和keycloak通信,用code换回accesstoken

#有了accesstoken后,遂向keycloak,发起api_url的请求,获取用户身份

#此时存入自己管理的用户session

#然后返回
#response header里,设置浏览器的grafana cookie,说明grafana已经将keycloak的code验证登录后,生成了该客户端的grafana_session
Set-Cookie: oauth_state=; Path=/; Max-Age=0; HttpOnly; SameSite=Lax
Set-Cookie: grafana_session=d08672d2f9a27fa5d760d8a44bb8fc73; Path=/; Max-Age=2595600; HttpOnly; SameSite=Lax
Set-Cookie: redirect_to=; Path=/; Max-Age=0; HttpOnly; SameSite=Lax
​
Location: /

第三个请求为第二个请求的客户端强制转向,即Grafana里配置的root_url

代码语言:javascript
复制
http://localhost:3000/
​
#请求头
Cookie: grafana_session=d08672d2f9a27fa5d760d8a44bb8fc73

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、一键式Keycloak安装
  • 2、配置Keycloak
    • 2.1 Grafana的OAuth接入
      • 2.2 Keycloak配置
        • 2.3 填充Grafana配置信息
        • 3. Grafana SSO登录过程分析
        相关产品与服务
        访问管理
        访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档