Skip to content

获取代理访问令牌

每个已上线代理都需要获取访问令牌才能使用 MindSphere MindSphere 使用 OAuth 2.0 授权框架向客户授予访问令牌。

令牌请求

MindSphere 从客户端接收令牌请求 (HTTP POST) 并返回访问令牌 (HTTP 200 OK)。在授予访问令牌之前,访问令牌服务将执行以下检查:

  1. 令牌请求包含强制性和预期的消息头。
  2. 客户端是已知客户端(存在于数据库中)。
  3. 客户端状态为 ONBOARDED

授权访问令牌由 Agent Management Servicetoken 端点执行。客户端访问令牌的请求示例:

POST /api/agentmanagement/v3/oauth/token HTTP/1.1
Content-Type:application/x-www-form-urlencoded
Host:localhost:8061
content-length:510
Connection:keep-alive
grant_type=client_credentials&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhN2VhYjA5MTEzOTg0OGJiOWU0Mzg5ZDIzZTkzNzhiOCIsInN1YiI6ImE3ZWFiMDkxMTM5ODQ4YmI5ZTQzODlkMjNlOTM3OGI4IiwiYXVkIjpbInNvdXRoZ2F0ZSJdLCJpYXQiOjE1MTM2OTAzNzQsIm5iZiI6MTUxMzY5MDM3NCwiZXhwIjoxNTE0Mjk1MTc0LCJqdGkiOiI1NzIzZDg2NWNlNTMxMzM1Iiwic2NoZW1hcyI6WyJ1cm46c2llbWVuczptaW5kc3BoZXJlOnYxIl0sInRlbiI6ImNvbm50ZW5hbnRvbmVxYSJ9.cli8RKPIUCt7VcP1yGjJvTA8dMR+kdBHotrLDvo4PqXCd1h71jlT3TPSoEAUjbwlm5YTu8RjJwq3cKobq18U7z7AVo+BmSopUIAO/ugyXWHNTpde0V9u8eDMVa3csZrOFwocQVTkI9zehXV81x++fI4hyLF004tUukLNsSglwYiogslhuK1qL8kmdgmTbdAu+ABE68VZe83pyyPJ2iHXZ83oxNElFx/lRZvzQC8B91yRQVO6+kUkDTj9wSr/Mf59DZ1HjpvZn1G0tYt43S4CEjtJSMfseg+kBx+uoqjSYOIVnq5bQYP+UctJRAMtUZJfgInltQGUKXvnqiKo9+RMaeeJTveNvq8EcHHHzeTuEwH3w9cUWGAk8zXax/T6kmTNorMBqQrATG3/UXyhI22x9ji8cY/NCydPVAK8t6+kSDn90znhJ3+S5ubTpx4frv8GG6CbxSaRh5SVJQdg2mG3XJcupxHljj9kQJmnEaP5kepU1LDp5GEHVhfRb0AKpWCG
参数 描述
grant_type 定义客户端请求的 OAuth 2.0 访问令牌流。
MindSphere 仅支持 client_credentials
client_assertion_type 定义断言类型(断言在 RFC 7521 中定义)。
MindSphere 仅支持断言类型 jwt-bearer urn:ietf:params:oauth:client-assertion-type:jwt-bearer(有关详细信息,请参见 RFC 7523, Section 2.2 "Using JWTs for Client Authentication")。
client_assertion 包含由客户端根据客户端的安全配置文件使用客户端密钥或客户端公钥签名的断言(自签名 JWT)。

请求文本参数 grant_typeclient_assertion_typeclient_assertion body 和消息头 Host 以及 Content-Type 都是必需的。如果其中一个不存在,将返回 HTTP 响应 400 Bad Request。有关错误的更多信息,请参见日志。根据 Siemens 安全规则的规定,返回给代理的响应中不提供任何详细信息。

客户端请求包含一个自签名 JWT,使用主体参数 client_assertion 传送。此客户端断言需要进行签名(使用客户端凭证):

  • 如果在注册期间向 MindSphere 提供了公钥,则需要使用私钥对客户端断言进行签名。
  • 如果在注册期间使用共享密钥,则客户端需要使用共享密钥对客户端断言进行签名。

以下为 client_assertion 参数示例值:

client_assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhN2VhYjA5MTEzOTg0OGJiOWU0Mzg5ZDIzZTkzNzhiOCIsInN1YiI6ImE3ZWFiMDkxMTM5ODQ4YmI5ZTQzODlkMjNlOTM3OGI4IiwiYXVkIjpbInNvdXRoZ2F0ZSJdLCJpYXQiOjE1MTM2OTAzNzQsIm5iZiI6MTUxMzY5MDM3NCwiZXhwIjoxNTE0Mjk1MTc0LCJqdGkiOiI1NzIzZDg2NWNlNTMxMzM1Iiwic2NoZW1hcyI6WyJ1cm46c2llbWVuczptaW5kc3BoZXJlOnYxIl0sInRlbiI6ImNvbm50ZW5hbnRvbmVxYSJ9.cli8RKPIUCt7VcP1yGjJvTA8dMR+kdBHotrLDvo4PqXCd1h71jlT3TPSoEAUjbwlm5YTu8RjJwq3cKobq18U7z7AVo+BmSopUIAO/ugyXWHNTpde0V9u8eDMVa3csZrOFwocQVTkI9zehXV81x++fI4hyLF004tUukLNsSglwYiogslhuK1qL8kmdgmTbdAu+ABE68VZe83pyyPJ2iHXZ83oxNElFx/lRZvzQC8B91yRQVO6+kUkDTj9wSr/Mf59DZ1HjpvZn1G0tYt43S4CEjtJSMfseg+kBx+uoqjSYOIVnq5bQYP+UctJRAMtUZJfgInltQGUKXvnqiKo9+RMaeeJTveNvq8EcHHHzeTuEwH3w9cUWGAk8zXax/T6kmTNorMBqQrATG3/UXyhI22x9ji8cY/NCydPVAK8t6+kSDn90znhJ3+S5ubTpx4frv8GG6CbxSaRh5SVJQdg2mG3XJcupxHljj9kQJmnEaP5kepU1LDp5GEHVhfRb0AKpWCG

这是客户端断言的解码版本:

{
 "alg""RS256",
 "typ":"JWT"
}
{
 "iss": "a7eab091139848bb9e4389d23e9378b8",
 "sub": "a7eab091139848bb9e4389d23e9378b8",
 "aud": [
 "southgate"
 ],
 "iat":1513690374,
 "nbf":1513690374,
 "exp":1514295174,
 "jti":"5723d865ce531335",
 "schemas": [
 "urn:siemens:mindsphere:v1"
 ],
 "ten": "conntenantoneqa"
}

自签名 JWT

JWT 是一种紧凑型声明的表示格式,适用于空间受限的环境,如 HTTP 授权消息头和 URI 查询参数 (RFC-7519)。 客户端会创建 JWT 并使用其凭证(在注册期间获得,“共享密钥”或“私钥”)来计算签名。 MindSphere 要求客户端 JWT 采用以下格式:

  • BASE64URL(UTF8(消息头))+ '.' + BASE64URL(有效载荷)+ '.' + BASE64URL(签名)

消息头

消息头必须有 typalg 声明。typ 声明必须设置为 JWT。必须根据客户的安全配置文件设置 alg 声明。

  • 如果客户端安全配置文件是 SHARED_SECRET,则 alg 必须是 HS256
  • 如果客户端安全配置文件是 RSA_3072,则 alg 必须是 RS256

消息头对象示例如下所示:

{
 "typ":"JWT",
 "alg""RS256"
}

有效载荷

有效载荷必须包含 isssubtenschemasiatexpaudjti 声明。nbf 声明是可选项。如果存在所列声明以外的其它声明,则 MindSphere 会将其忽略。 下表描述了声明及其预期值。

参数 描述 预期值
iss 签发方声明 agentId
sub 主题声明 agentId
ten 租户声明 tenantId
schemas 架构声明 架构数组 ["urn:siemens:mindsphere:v1"]
iat 签发时间声明 客户签发 JWT 的时期时间(以秒为单位)
nbf 开始时间声明 时期时间(以秒为单位),标识在此时间之前不得接受 JWT 进行处理。
exp 过期时间声明 JWT 令牌保持有效的时期时间(以秒为单位)
aud 接收人声明 接收人,必须等于“southgate”
jti json 令牌 ID 声明 JWT ID,唯一标识符

主体对象示例如下:

{
 "iss": "d9341cbff41144abaf690b22e16b87d2",
 "sub": "d9341cbff41144abaf690b22e16b87d2",
 "aud": [
 "southgate"
 ],
 "iat":1532690970,
 "nbf":1532690970,
 "exp":1533295770,
 "jti": "ed35d144e2742f93",
 "schemas": [
 "urn:siemens:mindsphere:v1"
 ],
 "ten": "connint1"
}

签名

使用签名输入生成 JWT 签名。使用以下算法计算签名输入:

  • ASCII(BASE64URL(UTF8(消息头)+ '.' + BASE64URL(有效载荷))

必须在 JOSE 消息头中提供 alg(算法)消息头参数。其值必须等于上面给出的计算 JWT 签名的算法。

自签名 JWT 的结构

在创建消息头、有效载荷和签名之后,客户端可以创建自签名 JWT,如下所示:

  • BASE64URL(UTF8(消息头)) || '.' || BASE64URL(有效载荷) || '.' || BASE64URL(签名)

有关更多详细信息,请参见 RFC-7515。

token 端点上接收到客户端访问令牌请求后,MindSphere 会检查传入请求的以下信息:

检查 错误情况
请求包含 Host 消息头。 返回 HTTP 响应 400 Bad Request,文本如下:

{"error": "invalid_request"}
请求包含 Content-Type 消息头,内容类型等于application/x-www-form-urlencoded(不区分大小写)。 返回 HTTP 响应 400 Bad Request,文本如下:

{"error": "invalid_request"}
请求包含 grant_type 文本参数,授予类型等于 client_credentials(不区分大小写)。 向代理返回 HTTP 响应 400 Bad Request,文本如下:

{"error": "invalid_request"}
请求包含 client_assertion_type 文本参数,客户端断言类型等于 urn:ietf:params:oauth:client-assertion-type:jwt-bearer(不区分大小写)。 返回 HTTP 响应 400 Bad Request,文本如下:

{"error": "invalid_request"}
请求包含 client_assertion 文本参数及其值。 返回 HTTP 响应 400 Bad Request,文本如下:

{"error": "invalid_request"}

说明

RFC 6749, Section 5 "Issuing An Access Token" 中所述,错误响应中必须包含 PragmaCache-Control 消息头。

如果上述所有检查都成功,则验证请求。MindSphere 将继续验证请求参数:

检查 错误情况
使用参数 client_assertion 调用方法 TokenRequestJwtValidatorService.validateJwt

此方法将检查提供的客户端断言是否为有效 JWT。

该方法还将检查以下 JWT 有效载荷声明是否存在且其值是否为预期值:

iss:检查声明是否存在。
sub:检查声明是否存在。
aud:检查声明是否存在,且等于 southgate
iat:检查声明是否存在,且小于或等于当前时间。
nbf:可选声明。检查声明是否存在,且小于或等于当前时间。
exp:检查声明是否存在,且过期时间不在当前时间之前。
schemas:检查消息头是否存在,且等于urn:siemens:mindsphere:v1(自从客户端发出时起)。
如果 JWT 验证失败,则会抛出 InvalidJwtException

将生成一个日志,其中包含说明 JWT 验证失败原因的消息。

此异常将被处理为 HTTP 响应 400 Bad Request,文本如下:

{“error”: “invalid_request”}
使用客户端断言和代理实体记录调用方法TokenRequestJwtValidatorService.checkJwtSignature

此方法检查 JWT 签名是否正确,以及代理的存储密钥是否过期。
如果客户端密钥已过期,则抛出 AgentSecretExpiredException 并将其映射到 HTTP 响应 400 Bad Request,文本如下:

{"error": "invalid_grant"}

。如果 JWT 签名不正确,则抛出 InvalidSignatureException 并将其映射到 HTTP 响应 400 Bad Request

{"error": "invalid_client"}
使用客户端断言调用方法 AgentEntityRetrievalService.retrieveAgentEntity

该方法从客户端断言中提取 sub 声明,并在代理实体数据库中查询相关记录并检索。
如果未找到提取的 sub 声明的代理实体记录,则抛出 AgentNotFound

如果找到代理实体记录,但代理实体的上线状态不是 ONBOARDED,则抛出 “AgentNotOnboardedException”。

这两个异常均被处理为 HTTP 响应 400 Bad Request,文本如下:

{"error": "invalid_client"}
使用代理 ID 和租户 ID 调用方法 AccessTokenService.createAccessToken

该方法将创建签名的 JWT(使用 Agent Management 的私钥签名)并返回访问令牌。
如果控制器无法访问其私钥,则抛出 NoSuchAlgorithmExceptionIOExceptionInvalidKeySpecificationException

所有异常均被处理为 HTTP 响应 500 Internal Error

如果所有测试均成功,MindSphere 将返回包含访问令牌的 HTTP 响应 200 OK。返回的访问令牌是签名的 JWT,默认有效时间为 1 小时。

HTTP/1.1 200 OK
Content-Type:application/json
Cache-Control:no-store
Pragma:no-cache
{
 "access_token": "eyJraWQiOiJrZXktaWQtMSIsImFsZyI6IlJTMjU2IiwidHlwIjoiSldUIn0.eyJqdGkiOiJjYmIwMGFhZS0yMTU5LTQwNWMtOGZhZC0xOWQ1YWE4ZTQxMWMiLCJzY29wZSI6WyJ0ZW5hbnQtc2NvcGUiLCJtZHNwOmNvcmU6RGVmYXVsdEFnZW50Il0sImlzcyI6Imh0dHBzOi8vc291dGhnYXRlLmV1LWNlbnRyYWwtcmMubWluZHNwaGVyZS5pby9hcGkvYWdlbnRtYW5hZ2VtZW50LyIsInN1YiI6ImE3ZWFiMDkxMTM5ODQ4YmI5ZTQzODlkMjNlOTM3OGI4IiwiemlkIjoiYWdlbnRpYW0iLCJhdWQiOlsic291dGhnYXRlIl0sImlhdCI6MTUxMzY5MDM3NiwiZXhwIjoxNTEzNjkzOTc2LCJzY2hlbWFzIjpbInVybjpzaWVtZW5zOm1pbmRzcGhlcmU6aWFtOnYxIl0sInRlbiI6ImNvbm50ZW5hbnRvbmVxYSIsImNhdCI6ImFnZW50LXRva2VuOnYxIiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyJ9.LzuA10P8Wy_pGr3s_gCiTaCd82Oc6ts0CJNG5n8MK31Dk5bRDd9hESPP5CUQ0V3pb504HLwBSGL1dg_AF48CdI9Dv8iZ5z667ZCiWptTsfPMdCaLtEWr09S5XA1TZtnLE_hg-v5NeMOmQJOc4xK3aSBmup3Qjw_RFpIeImPHLgCdavp06pdOSIrZ8qPXhi6qBxSAqWOho0DoCAmWO8zp_d55AwdXxeVVudieG9GrQVgGhjQtoIpP8R_pZtJ1nvr6b59nazk1fGsVcGyP-mavQ3Snp9kI7EsT96EBtKLbjuUmsa2bi8ju8LRB0fo_TkIWdnU02vLDfzlx4ftETHm8zg",
 "token_type":"Bearer",
 "expires_in":3600,
 "scope": [
 "tenant-scope",
 "mdsp:core:DefaultAgent"
 ],
 "jti": "cbb00aae-2159-405c-8fad-19d5aa8e411c"
}
参数 描述 备注
access_token 由 MindMindSphereSphere 本身签名的 JWT 使用此令牌,允许代理使用 MindSphere 服务。
token_type 令牌类型 MindSphere 仅支持 Bearer
expires_in 令牌的有效期限(以秒为单位)
scope 此令牌有效的范围。
jti JWT 令牌 ID

这是访问令牌的解码版本:

{
 "kid": "key-id-1",
 "alg""RS256",
 "typ":"JWT"
}
{
 "jti": "cbb00aae-2159-405c-8fad-19d5aa8e411c",
 "scope": [
 "tenant-scope",
 "mdsp:core:DefaultAgent"
 ],
 "iss": "https://southgate.eu-central-rc.mindsphere.io/api/agentmanagement/",
 "sub": "a7eab091139848bb9e4389d23e9378b8",
 "zid": "agentiam",
 "aud": [
 "southgate"
 ],
 "iat":1513690376,
 "exp":1513693976,
 "schemas": [
 "urn:siemens:mindsphere:iam:v1"
 ],
 "ten": "conntenantoneqa",
 "cat": "agent-token:v1",
 "grant_type": "client_credentials"
}

相关链接


Last update: March 22, 2023