本文提供一个Okta与阿里云进行OIDC角色SSO的示例,使Okta中的应用通过临时身份凭证(STS Token)安全访问阿里云资源。
前提条件
请提前在Okta中注册一个OIDC应用,并获取应用的颁发者URL和客户端ID(Client ID)。本示例中使用的数据如下:
颁发者URL:https://dev-xxxxxx.okta.com
客户端ID:0oa294vi1vJoClev****
步骤一:在阿里云创建OIDC身份提供商
本步骤中将创建一个名为TestOidcProvider的OIDC身份提供商。颁发者URL为https://dev-xxxxxx.okta.com,客户端ID为0oa294vi1vJoClev****。
使用RAM管理员登录RAM控制台。
在左侧导航栏,选择。
在角色SSO页签,先单击OIDC页签,然后单击创建身份提供商。
在创建身份提供商页面,设置身份提供商信息。
参数
说明
身份提供商名称
同一个阿里云账号下必须唯一。
颁发者URL
颁发者URL由外部IdP提供。颁发者URL必须以
https开头,符合标准URL格式,但不允许带有query参数(以?标识)、fragment片段(以#标识)和登录信息(以@标识)。验证指纹
为了防止颁发者URL被恶意劫持或篡改,您需要配置外部IdP的HTTPS CA证书生成的验证指纹。
填写完颁发者URL后,您可以单击获取指纹,阿里云会辅助您自动计算出验证指纹,但是建议您在本地自己计算一次(例如:通过OpenSSL获取OIDC IdP的指纹),与阿里云计算的指纹进行对比。如果对比发现不同,则说明该颁发者URL可能已经受到攻击,请您务必再次确认,并填写正确的指纹。
说明当您的IdP计划进行证书轮转时,请在轮转前生成新证书的指纹并添加到阿里云OIDC身份提供商信息中,一段时间(至少一天)以后再进行证书轮转,证书轮转确认可以换取到STS Token后再删除旧的指纹。
客户端ID
您的应用在外部IdP注册的时候,会生成一个客户端ID(Client ID)。当您从外部IdP申请签发OIDC令牌(OIDC Token)时必须使用该客户端ID,签发出来的OIDC Token也会通过
aud字段携带该客户端ID。在创建OIDC身份提供商时配置该客户端ID,然后在使用OIDC Token换取STS Token时,阿里云会校验OIDC Token中aud字段所携带的客户端ID与OIDC身份提供商中配置的客户端ID是否一致。只有一致时,才允许扮演角色。如果您有多个应用需要访问阿里云,您可以配置多个客户端ID,但最多不能超过50个。
最早颁发时间限制
在该限制时间之前颁发的OIDC Token不允许换取STS Token。
默认值:12小时。取值范围:1~168小时。
备注
身份提供商的描述信息。
单击创建身份提供商。
步骤二:在阿里云创建可信实体为OIDC身份提供商的RAM角色
本步骤中将创建一个名为testoidc的RAM角色,身份提供商选择步骤一创建的TestOidcProvider。
使用RAM管理员登录RAM控制台。
在左侧导航栏,选择。
在角色页面,单击创建角色。

在创建角色页面的右上角,单击切换编辑器。

在编辑器中指定具体的OIDC身份提供商。
编辑器支持可视化编辑和脚本编辑两种模式,您可以任选其一。
可视化编辑
在主体中指定具体的OIDC身份提供商。


脚本编辑
在
Principal的Federated字段中指定具体的OIDC提供商,同时配置Condition。{ "Version": "1", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "acs:ram::100*******0719:oidc-provider/xiyun****" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "oidc:iss": [ "https://dev-xxxxxx.okta.com" ], "oidc:aud": [ "0oa294vi1vJoClev****" ] } } } ] }
在编辑器中设置限制条件。
支持的服务级限制条件如下表所示:
限制条件关键字
说明
是否必选
示例
oidc:issOIDC颁发者(Issuer)。用来扮演角色的OIDC令牌中的iss字段值必须满足该限制条件要求,角色才允许被扮演。
该限定条件必须使用StringEquals作为条件操作类型,条件值只能是您在OIDC身份提供商中填写的颁发者URL。该限制条件用于确保只有受信颁发者颁发的OIDC令牌才能扮演角色。
是
https://dev-xxxxxx.okta.com
oidc:audOIDC受众(Audience)。用来扮演角色的OIDC令牌中的aud字段值必须满足该限制条件要求,角色才允许被扮演。
该限定条件必须使用StringEquals作为条件操作类型,您可选择在OIDC身份提供商中配置的一个或多个客户端ID(Client ID)作为条件值。该限制条件用于确保只有您设置的Client ID生成的OIDC令牌才能扮演角色。
是
0oa294vi1vJoClev****
oidc:subOIDC主体(Subject)。用来扮演角色的OIDC令牌中的sub字段值必须满足该限制条件要求时,角色才允许被扮演。
该限定条件可以使用任何String类的条件操作类型,且您可以最多设置10个OIDC主体作为条件值。该限制条件用于进一步限制允许扮演角色的身份主体,您也可以不指定该限制条件。
否
00u294e3mzNXt4Hi****
在创建角色对话框,输入角色名称,然后单击确定。
步骤三:为RAM角色授权
您可以根据实际需要,为步骤二创建的RAM角色testoidc授予访问阿里云资源的权限。
步骤四:在Okta签发OIDC令牌(OIDC Token)
阿里云不支持使用OIDC登录控制台,所以您需要使用程序访问的方式完成OIDC SSO流程。由于生成OIDC Token本质上是个OAuth流程,所以您需要通过标准的OAuth 2.0流程从OIDC IdP(例如:Okta)获取OIDC Token。OAuth支持多种流程,例如:比较常见的Authorization Code Flow。
下文以Okta官方教程使用AuthJS登录单页应用(SPA)为例,演示如何从Okta获取OIDC Token。
按照Okta的教程创建应用并完成项目配置。
在浏览器中测试项目,应用将自动重定向到Okta登录页面。完成登录和MFA认证后,页面将重定向至
index.html。页面会显示当前登录用户的ID Token及其解析后的Claims信息。如下所示:{ "idToken": "eyJraWQiOiItbUF****", "claims": { "sub": "00uxbq0z40UYy9bm****", "name": "ssotest01", "email": "ssotest01@exampledomain.com", "ver": 1, "iss": "https://dev-xxxxxx.okta.com", "aud": "0oaxbqhfrfBl5lk2****", "iat": 1762841679, "exp": 1762845279, "jti": "ID.WYtCLmLKOlMcEh0uIe1jWH9T6M1JmotCvX3hIgLK6mA", "amr": [ "mfa", "otp", "pwd", "okta_verify" ], "idp": "00oxbpgns1TnfLFg****", "nonce": "Xp0PTyQzw9ltYBY7SfhxG2ijt1wgi2jK6XLZOGbeQJQ79d0ScWYoHE5twl0QAklA", "preferred_username": "ssotest01@exampledomain.com", "auth_time": 1762841677, "at_hash": "wztv8ALAo2Au56Om3dya7w" }, "expiresAt": 1762845279, "scopes": [ "openid", "profile", "email" ], "authorizeUrl": "https://dev-xxxxxx.okta.com/oauth2/v1/authorize", "issuer": "https://dev-xxxxxx.okta.com", "clientId": "0oaxbqhfrfBl5lk2****" }说明在页面展示的claims信息中,找到以下属性,并确保它们与在步骤一:在阿里云创建OIDC身份提供商中配置的OIDC身份提供商信息匹配,否则在调用AssumeRoleWithOIDC API时将会失败。
iss:必须与颁发者URL完全匹配
aud:必须与客户端ID完全匹配
复制页面中所展示的
idToken并保存。
步骤五:使用OIDC Token换取STS Token
您可以直接调用AssumeRoleWithOIDC API,使用从步骤四中获取的OIDC Token(ID token)换取STS Token。
请求示例:
package demo;
import com.aliyun.auth.credentials.provider.AnonymousCredentialProvider;
import com.aliyun.sdk.service.sts20150401.models.*;
import com.aliyun.sdk.service.sts20150401.*;
import com.google.gson.Gson;
import darabonba.core.client.ClientOverrideConfiguration;
import java.util.concurrent.CompletableFuture;
public class AssumeRoleWithOIDC {
public static void main(String[] args) throws Exception {
// Anonymous access method (requires API support)
AnonymousCredentialProvider provider = AnonymousCredentialProvider.create();
// Configure the Client
AsyncClient client = AsyncClient.builder()
.region("cn-hangzhou") // Region ID
.credentialsProvider(provider)
// Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.
.overrideConfiguration(
ClientOverrideConfiguration.create()
// Endpoint 请参考 https://api.aliyun.com/product/Sts
.setEndpointOverride("sts.cn-hangzhou.aliyuncs.com")
)
.build();
String idToken = "eyJraWQiOiItbUF****"; // OIDC id token
// Parameter settings for API request
AssumeRoleWithOIDCRequest assumeRoleWithOIDCRequest = AssumeRoleWithOIDCRequest.builder()
.OIDCToken(idToken)
.roleArn("acs:ram::173305794806****:role/testoidc")
.OIDCProviderArn("acs:ram::173305794806****:oidc-provider/Okta")
.roleSessionName("test-oidc-session")
.build();
// Asynchronously get the return value of the API request
CompletableFuture<AssumeRoleWithOIDCResponse> response = client.assumeRoleWithOIDC(assumeRoleWithOIDCRequest);
// Synchronously get the return value of the API request
AssumeRoleWithOIDCResponse resp = response.get();
System.out.println("RequestId: " + resp.getBody().getRequestId());
System.out.println("Assume role ARN: " + resp.getBody().getAssumedRoleUser().getArn());
System.out.println("Credentials AccessKeyId: " + resp.getBody().getCredentials().getAccessKeyId());
System.out.println("Credentials AccessKeySecret: " + resp.getBody().getCredentials().getAccessKeySecret());
System.out.println("Success response: " + new Gson().toJson(resp.getBody()));
// Finally, close the client
client.close();
}
}
返回示例:
RequestId: 5EB6E605-15EA-5D96-941D-2C62DC99****
Assume role ARN: acs:ram::173305794806****:role/testoidc/test-oidc-session
Credentials AccessKeyId: STS.NZXMTBGTTHLW74AMVYKou****
Credentials AccessKeySecret: FdrYjJwTCfFfMdY4APdHsjGL9fH5RSZCtRyYMJED****
Success response:
{
"assumedRoleUser": {
"arn": "acs:ram::173305794806****:role/testoidc/test-oidc-session",
"assumedRoleId": "30048007026011****:test-oidc-session"
},
"credentials": {
"accessKeyId": "STS.NZXMTBGTTHLW74AMVYKou****",
"accessKeySecret": "FdrYjJwTCfFfMdY4APdHsjGL9fH5RSZCtRyYMJED****",
"expiration": "2025-11-11T08:01:03Z",
"securityToken": "CAISwwJ1q6Ft5B2yfSjI****"
},
"OIDCTokenInfo": {
"clientIds": "0oaxbqhfrfBl5lk2****",
"expirationTime": "2025-11-11T07:14:39Z",
"issuanceTime": "2025-11-11T06:14:39Z",
"issuer": "https://dev-xxxxxx.okta.com",
"subject": "00uxbq0z40UYy9bm****",
"verificationInfo": "Success"
},
"requestId": "5EB6E605-15EA-5D96-941D-2C62DC99****"
}其中Credentials中的信息即为STS Token。
步骤六:使用STS Token访问阿里云资源
使用从步骤五获取的STS Token访问有权限的阿里云资源。
