OpenID Connect Federation 入门指南

简介: 标准原文OpenID Connect Federation 1.0 OpenID-Connect针对跨域的身份鉴别请求的需求,提出了自己的解决方案——OIDC联盟(OpenID Connect Federation )。

标准原文OpenID Connect Federation 1.0

OpenID-Connect针对跨域的身份鉴别请求的需求,提出了自己的解决方案——OIDC联盟(OpenID Connect Federation )。和基于SAML框架的eduGAIN不同,OIDC联盟还只停留在技术方案阶段,并没有一个实体团体来维护和推进身份联盟的建设。

本文是基于OpenID-Connect的进阶内容。关于OpenID-Connect的详尽内容,请参看 OpenID Connect 协议入门指南

1. 发现与动态注册

在提出OIDC联盟之前, OpenID-Connect提供了发现Discovery)和动态注册Dynamic Registration)机制来支持服务方(Service Provider, SP)发现未知身份提供方(Identity Provider,IDP)并动态注册,其流程为:

  1. SP从IDP的特定路径中获取IDP的配置信息,如IDP的授权端点(authorization_endpoint)和令牌端点(token_endpoint)、验证ID令牌签名的公钥等;
  2. SP向IDP指定的注册端点发送他的返回重定向(redirect_uri)等信息;
  3. IDP返回的响应包括SP的ID(client_id)和口令(client_secret)等信息。

但是这样IDP动态注册SP的机制存在如下问题:

  1. 接收方不能仅凭消息本身来验证消息的完整性和消息来源的可靠性;
  2. 完整性和消息来源的可靠性保护完全依赖于TLS协议,但是TLS也可能出现问题;

如何才能实现元数据(IDP的配置信息、SP的配置信息)的可靠传输,这便是构建OIDC联盟的初衷。OIDC联盟利用唯一的可信第三方,建立一个互相信任的联盟,用于元数据的可靠传输,元数据的接收方可以验证消息的完整性和来源的可靠性,从而信任这些信息。

OIDC联盟使用OAuth2.0中规定的签名元数据(Signed Metadata),构建元数据声明(metadata statement)来安全传递元数据。

2. 元数据参数(Metadata Parameters)

为了构建联盟参与方的元数据声明,IDP和SP在注册是都需要提供联盟所要求的元数据参数。

以下为OIDC联盟在注册时IDP和SP都可配置的元数据参数:

  1. signing_keys (可选) 联盟中实体的公钥,以JSON Web Key (JWK)形式呈现。与IDP签发ID令牌的公钥不同,该公钥主要用来验证元数据的完整性和来源的可靠性,即对元数据进行验签时使用,如SP对IDP的注册响应的验签。
  2. signing_keys_uri (可选) 获取联盟中实体的公钥的URL,作用和signing_keys相同。唯一不同的是,从URL中获得的signing_keys是单独经过上级实体以 JSON Web Signature (JWS)格式签名的,而signing_keys中的公钥,会和其他元数据参数一起被上级实体签名。
  3. metadata_statements (可选) 联盟规定的元数据是嵌套的元数据,本级元数据需要加上上一级的元数据,直到最终的可信第三方,即信任锚。元数据声明参数的值是上级的元数据。本级的元数据将作为下级的元数据声明的值。最高级(Level 0)的元数据不包含该参数。
  4. metadata_statement_uris (可选)获取元数据声明的URL。
  5. signed_jwks_uri (可选) 增强版的jwks_uri。获取验证ID令牌签名的公钥的URL。公钥经过本机构的私钥签名,接收方可以使用signing_ keys进行验签。
  6. signing_keys需要对以下数据进行签名:下级的签名公钥(signing_ keys)、下级的元数据声明(metadata_statement)、和本级的ID令牌签名公钥(如果是IDP的话)。
  7. federation_usage (可选) 元数据声明的用处。由于发现、动态注册请求和动态注册响应中都会涉及元数据,这些元数据包含的参数并不相同,federation_usage规定了元数据究竟用于发现、动态注册请求还是动态注册响应。该参数的值包括:discoveryregistrationresponse

SP的元数据参数还包括redirect_uris等,本标准还规定了以下专用于SP的参数:

  1. scopes (建议) SP想要的资源范围。
  2. claims (建议) SP想要的属性声明。

IDP的元数据参数还包括issuer、authorization_endpoint、token_end point等。

3. 元数据声明(Metadata Statements)

元数据声明,即元数据参数组成的数据结构。某一机构的元数据声明包含本机构的签名公钥(signing_keys)以及本机构的元数据请求,包含本级的元数据参数。
本机构将未签名的元数据声明发送给上级机构,上级机构使用它的私钥对本机构的元数据请求和签名公钥进行签名,得到经过签名的元数据声明(metadata statement)。本机构的元数据声明将作为下级机构的元数据请求中参数metadata_ statement的值。

{
  "redirect_uris": ["https://example.com/rp1"],
  "metadata_statements": {
    'https://example.com':
      {
        "scope": "openid eduperson",
        "response_types": ["code", "code id_token"],
        "contacts": ["rp_helpdesk@example.com"],
        "redirect_uris": ["https://example.com/rp1"],
        "response_types: ["code"]
        "metadata_statements" : {
          'https://example.com':
            {
              "logo_uri": "https://example.com/logo.jpg",
              "policy_uri": "https://example.com/policy.html",
              "tos_uri": "https://example.com/tos.html"
            }
         }
      }
   }
}

元数据声明,是JWT格式的数据,如上,使用上级机构的私钥签名,JWT数据的载荷为本机构的签名公钥和其他元数据参数。

假设A、B、C是联盟中分属三个层次的机构,A是上级,B是中间级C是下级,则A对B的元参数请求和签名公钥签名,B再对C的元数据请求和签名公钥签名。C的元数据请求应当包含B的元数据声明。第0层的元数据请求不包含元数据声明的参数。第N层的请求者是第N+1层的签名者。

{
  "application_type": "web",
  "exp": 1496130898,
  "iat": 1496044498,
  "iss": "https://www.uninett.no",
  "kid": "5jl-7XNA-LaMiorIlf3qDdk35hbRaxnesdqzg1Q5rcg",
  "metadata_statements": {
    "https://swamid.sunet.se/": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjY1TUp
yRnFDeDBGUjk2SzNxWHJNZ0ZWMTkxOF9fVFc3dnVJMl9MUl9HZ28ifQ.eyJmZWRlcmF0
aW9uX3VzYWdlIjogInJlZ2lzdHJhdGlvbiIsICJzaWduaW5nX2tleXMiOiB7ImtleXMi
OiBbeyJrdHkiOiAiUlNBIiwgInVzZSI6ICJzaWciLCAia2lkIjogIjVqbC03WE5BLUxh
TWlvcklsZjNxRGRrMzVoYlJheG5lc2RxemcxUTVyY2ciLCAibiI6ICIyTmRUbXpNYThw
cWlzZU8wdFNITW1SaU1VbWVhRmQxVUNfLVUwSXJiLTdEUlBZTE92OER2VWRJRTA2OXZu
eURMWlNpM1VpbzNIMkUyNVc1c1FwUjdpZWVHeHI1bDNYWVdKZ2tpcW1EaWtIblF3anRw
RklPM1lfNWd5SHBCZHFLSHpZcnFPaDZhTWRyeUZqWkhqRF9QcDVkaF8tZG5WUjFqbHdB
M0wzSF91WG92QzAwYmVDMzBGUFk4OFByRFl2X1hDYm1KaUhtZ0FFTHlmZ1N2d0lHcUV6
a241VHc0Mk80RVlfaFB6Vm5NYkdSTEl6cy11eUlqSTJKTGpoemdWUDJBZlBkVF9zNkdB
QktmVlBrWDZvQ090enpqbVZfY2EzX2VPUGZ2MVlJQ0xlSnJ5M0pTVnRIbHFSekNDS2wy
ZFdQZC1XY09MN0lNVWlBd3hSV1hkNzFvbVEiLCAiZSI6ICJBUUFCIn1dfSwgInJlc3Bv
bnNlX3R5cGVzIjogWyJjb2RlIiwgInRva2VuIl0sICJ0b2tlbl9lbmRwb2ludF9hdXRo
X21ldGhvZCI6ICJwcml2YXRlX2tleV9qd3QiLCAic2NvcGVzIjogWyJvcGVuaWQiLCAi
ZW1haWwiXSwgImlzcyI6ICJodHRwczovL3N3YW1pZC5zdW5ldC5zZS8iLCAiaWF0Ijog
MTQ5NjA0NDQ5NywgImV4cCI6IDE0OTg2MzY0OTcsICJraWQiOiAiNjVNSnJGcUN4MEZS
OTZLM3FYck1nRlYxOTE4X19UVzd2dUkyX0xSX0dnbyIsICJqdGkiOiAiMWMzOTY0NmM0
MGExNDVkNGFkYWIwMGNlNmQ0MmRhYmMifQ.YPcpHSluei_DbOyRxDQ9PeL5FU23ZHU45
G33WTJlCT1QxqzKLYFjHdm28WVHxquQ4FrgmY49Wt9vm1cvsg5hSyxNcHJMDDL3Y4pfe
LeozTVZhDrx-wUCcPqCIxpU9WdtuWvefyvxzbuF8qMf7_4Aiw8V1TqJc7tqYpd_Ic0xd
uHEMFaF1UATztdGOKy4iISSR6qKOKGfJyW4IlNw-hLR5DImln4W7uikHFUxkKjmrXCQ-
AnKhMUub75dThKg-vIZiXD8T0KbIsi2l40bH_n9qWexnpX_BAGvCgY9LlEJ0Z8wlTpHq
HzD2mrs218ysop2tB45ICJpsW_YDqWHgvP9mQ"
  },
  "response_types": [
    "code"
  ],
  "sub": "https://foodle.uninett.no"
}

4. 信任模型(Trust Model)

OIDC联盟依靠签名公钥(signing_keys),建立起一条一条的信任链,每一条信任链都到达可信第三方(Federation Operator)。

联盟内所有成员都信任Federation Operator。Federation Operator需要公开它的公钥。联盟内成员通过HTTPS网站获得,HTTPS网站的证书应当记录在证书透明化日志中。

最内层的元数据声明由Federation Operator签名,不包含元数据声明这一参数。元数据声明的产生流程:

  1. 本机构将自身所需的元数据参数和签名公钥发送给上级机构。
  2. 本机构可以同时将上级的元数据声明发送给上级机构,也可以由上级机构直接添加,因为本机构的元数据声明当中应当包含上级机构的元数据声明(metadata statement参数的值)。
  3. 上级机构可以自主地添加或者删除某些参数,然后对元数据请求和签名公钥进行签名。
  4. 上级机构将签完名地元数据声明发送给本机构。

元数据声明的验签流程:

  1. 收到一个元数据声明,首先应当解析最内层地元数据声明。利用已知的Federation Operator的公钥验证最内层声明的正确性。
  2. 从最内层声明中提取公钥,验证次内层的声明的正确性。
  3. 以此类推。

发现和动态注册机制保持不变,但是所有的数据都应当是元数据声明。

发现和动态注册请求的参数通常是固定的,因此可以事先由各自的上级机构签完名并存储在本地,然后直接发送给相对方。

动态注册响应的参数一般是不固定的,有两种解决方案:

  1. IDP的上级机构提供实时签名的服务;
  2. IDP自己对响应进行签名:IDP需要事先获得一份只有signing_keys的、经过上级机构签名的元数据声明,然后将该声明嵌套在动态注册响应中,并使用自己的私钥签名。这样的元数据声明也能通过验证。

5. 联盟的加入

OIDC联盟标准允许IDP和SP加入多个OIDC联盟,通过发现和动态注册机制,IDP和SP协商确定彼此认可的联盟。

IDP发布配置信息的时候,可以发布多个元数据声明,各自指向不同的Federation Operator。

SP发起动态注册请求的时候选择其中若干个联盟签发的元数据声明,发送给IDP。
IDP选择其中一个联盟,返回该联盟签发的动态注册响应。

SP向IDP发送的注册请求如下:

{
  "redirect_uris": ["https://example.com/rp2/callback"],
  "metadata_statement_uris": {
      https://swamid.sunet.se/":
        "https://dev.example.com/rp1/idfed/swamid.jws",
      "https://www.incommon.org":
        "https://dev.example.com/rp1/idfed/incommon.jws"
  }
}

IDP响应SP的注册信息如下:

{
  "client_id": "abcdefgh",
  "client_secret": "0123456789",
  "client_id_issued_at": 1462375583,
  "client_secret_expires_at": 1462379183,
  "redirect_uris": ["https://example.com/rp2/callback"],
  "metadata_statement_uris": {
    "https://swamid.sunet.se/":
      "https://dev.example.com/rp1/idfed/swamid.jws",
  }
}

参考文件

  1. OAuth 2.0 Authorization Server Metadata
  2. JSON Web Key (JWK)
  3. JSON Web Signature (JWS)
相关文章
|
1月前
|
JavaScript 前端开发 开发工具
【Azure Developer】使用JavaScript通过SDK进行monitor-query的client认证报错问题
AADSTS90002: Tenant 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' not found. Check to make sure you have the correct tenant ID and are signing into the correct cloud. Check with your subscription administrator, this may happen if there are no active subscriptions for the tenant.
|
3月前
|
API 开发者
【API管理 APIM】APIM集成内部VNet后,自我访问出现(Unable to connect to the remote server)问题,而Remote Server正是APIM它自己
【API管理 APIM】APIM集成内部VNet后,自我访问出现(Unable to connect to the remote server)问题,而Remote Server正是APIM它自己
|
3月前
|
域名解析 网络协议 API
【API管理 APIM】APIM集成内部VNet时,常遇见的关于自定义DNS服务问题。
【API管理 APIM】APIM集成内部VNet时,常遇见的关于自定义DNS服务问题。
|
3月前
|
开发工具 数据安全/隐私保护 git
【Azure 应用服务】登录App Service 高级工具 Kudu站点的 Basic Auth 方式
【Azure 应用服务】登录App Service 高级工具 Kudu站点的 Basic Auth 方式
|
3月前
|
JavaScript 前端开发 Linux
【Azure 应用服务】NodeJS Express + MSAL 实现API应用Token认证(AAD OAuth2 idToken)的认证实验 -- passport.authenticate()
【Azure 应用服务】NodeJS Express + MSAL 实现API应用Token认证(AAD OAuth2 idToken)的认证实验 -- passport.authenticate()
|
3月前
|
API 开发者
【Azure API 管理】API Management service (APIM) 如何实现禁止外网访问
【Azure API 管理】API Management service (APIM) 如何实现禁止外网访问
|
3月前
|
存储 安全 API
【Azure API 管理】在APIM中使用客户端证书验证API的请求,但是一直提示错误"No client certificate received."
【Azure API 管理】在APIM中使用客户端证书验证API的请求,但是一直提示错误"No client certificate received."
|
5月前
|
存储 中间件 数据安全/隐私保护
中间件中OAuth 2.0 和 OpenID Connect
【6月更文挑战第4天】
238 5
|
存储 JSON 缓存
Elasitcsearch High Level Rest Client学习笔记(二) 基础API - 木子H的个人空间 - OSCHINA
Elasitcsearch High Level Rest Client学习笔记(二) 基础API - 木子H的个人空间 - OSCHINA
|
SQL 缓存 前端开发
Server Components:我们即将和 API 告别?
Server Components:我们即将和 API 告别?
167 0