全部產品
Search
文件中心

Resource Access Management:通過OIDC擷取使用者資訊

更新時間:May 09, 2025

OIDC(OpenID Connect)是建立在OAuth 2.0基礎上的一個認證協議,本文為您介紹應用如何使用OIDC擷取阿里雲登入使用者的資訊。

前提條件

擷取使用者登入資訊前,您需要建立應用,設定應用程式名稱、OAuth範圍和回調地址等關鍵資訊,並為應用產生應用密鑰。具體操作,請參見建立應用添加應用範圍建立應用密鑰

基本概念

概念

說明

身份令牌

OIDC可以給應用下發代表登入使用者的身份令牌。身份令牌用於擷取姓名、登入名稱等使用者資訊,不能用於訪問阿里雲服務。

OIDC Discovery Endpoint

OIDC協議包含了不同的Endpoint用於不同的目的,Discovery Endpoint中包含OIDC協議所需要的所有配置資訊,方便開發人員使用。

說明

Discovery Endpoint是通過JSON文檔來提供一系列索引值,其中包含主要的提供者資訊,例如:協議支援的響應類型、令牌頒發者的取值、身份令牌簽名公開金鑰的地址和簽名演算法等。

阿里雲作為OIDC服務提供者,提供了一個Discovery Endpoint:https://oauth.alibabacloud.com/.well-known/openid-configuration來簡化配置流程。

Discovery Endpoint包含的內容樣本如下:

{
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ],
  "subject_types_supported": [
    "public"
  ],
  "response_types_supported": [
    "code"
  ],
  "issuer": "https://oauth.alibabacloud.com",
  "jwks_uri": "https://oauth.alibabacloud.com/v1/keys",
  "revocation_endpoint": "https://oauth.alibabacloud.com/v1/revoke",
  "token_endpoint": "https://oauth.alibabacloud.com/v1/token",
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "scopes_supported": [
    "openid",
    "aliuid",
    "profile"
  ],
  "authorization_endpoint": "https://signin.alibabacloud.com/oauth2/v1/auth"
}

基本流程

IODC基本流程

  1. 使用者通過瀏覽器登入應用。

  2. 應用重新導向到阿里雲OIDC服務並將URL返回給瀏覽器。

    說明

    如果使用者還未登入,則會進一步重新導向到阿里雲登入服務。

  3. 使用者通過瀏覽器登入阿里雲OIDC服務並申請授權碼。

  4. 阿里雲OIDC服務重新導向到應用並返回授權碼給瀏覽器。

  5. 瀏覽器通過應用使用授權碼向阿里雲OIDC服務申請身份令牌。

  6. 阿里雲OIDC服務嚮應用返回身份令牌和存取權杖,應用通過身份令牌或存取權杖便可以擷取使用者資訊。

    具體的使用情境如下:

樣本一:應用擷取OAuth服務身份令牌的簽名公開金鑰

請求樣本如下:

private List getSignPublicKey() {
  HttpResponse response = HttpClientUtils.doGet("https://oauth.alibabacloud.com/v1/keys");
  List rsaKeyList = new ArrayList();
  if (response.getCode() == 200 && response.isSuccess()) {
    String keys = JSON.parseObject(response.getData()).getString("keys");
    try {
      JSONArray publicKeyList = JSON.parseArray(keys);
      for (Object object : publicKeyList) {
        RSAKey rsaKey = RSAKey.parse(JSONObject.toJSONString(object));
        rsaKeyList.add(rsaKey);
      }
      return rsaKeyList;
    } catch (Exception e) {
      LOG.info(e.getMessage());
    }
  }
  LOG.info("GetSignPublicKey failed:{}", response.getData());
  throw new AuthenticationException(response.getData());
}                    

樣本二:驗證身份令牌的JWT簽名

阿里雲頒發的身份令牌是帶有簽名的JWT(JSON Web Token),簽名演算法為JWS標準RS256。當應用請求擷取使用者資訊時,需要應用對身份令牌進行驗證,包含以下幾個方面:

  • 簽名驗證:請務必通過樣本一擷取OAuth服務公布的簽名公開金鑰,驗證身份令牌的真實性和完整性。

    OAuth服務的公開金鑰會定期輪轉,擷取公開金鑰請注意以下兩點:

    • 確保每次請求重新擷取服務簽名公開金鑰,請不要緩衝或長期儲存公開金鑰並使用。

    • OAuth服務的簽名公開金鑰輪轉期間會擷取到多個有效簽名公開金鑰,需要依次進行驗證,請不要固定驗證公開金鑰的數量。

    請求樣本如下:

    public boolean verifySign(SignedJWT signedJWT) {
      List publicKeyList = getSignPublicKey();
      RSAKey rsaKey = null;
      for (RSAKey key : publicKeyList) {
        if (signedJWT.getHeader().getKeyID().equals(key.getKeyID())) {
          rsaKey = key;
        }
      }
      if (rsaKey != null) {
        try {
          RSASSAVerifier verifier = new RSASSAVerifier(rsaKey.toRSAPublicKey());
          if (signedJWT.verify(verifier)) {
            return true;
          }
        } catch (Exception e) {
          LOG.info("Verify exception:{}", e.getMessage());
        }
      }
      throw new AuthenticationException("Can't verify signature for id token");
    }
  • 有效期間驗證:檢查令牌頒發時間和令牌到期時間的有效性。

  • 檢查令牌接收者:防止頒發給其他應用的身份令牌被傳遞給本應用。

樣本三:解析身份令牌擷取使用者資訊

  • 返回參數

    • Header返回參數

      參數名稱

      描述

      需要的OAuth範圍

      alg

      簽名演算法。

      openid

      kid

      驗證身份令牌簽名使用的公開金鑰,使用者需要使用此公開金鑰驗證簽名,防止身份令牌被篡改。

      openid

    • Body返回參數

      參數名稱

      描述

      需要的OAuth範圍

      exp

      令牌到期時間戳記。

      openid

      sub

      唯一代表登入使用者的字串,但並不包含阿里雲UID、使用者名稱等資訊。

      說明

      當登入使用者為RAM角色時,sub將根據角色扮演者<RoleId:RoleSessionName>產生,每個扮演者都有獨立的sub

      openid

      aud

      令牌接收者,OAuth應用ID。

      openid

      iss

      令牌頒發者。取值為https://oauth.alibabacloud.com

      openid

      iat

      令牌頒發時間戳記。

      openid

      type

      登入使用者類型。取值:

      • account:阿里雲帳號(主帳號)。

      • user:RAM使用者。

      • role:RAM角色。

      profile

      name

      登入使用者的顯示名稱。取值:

      • RAM使用者:RAM使用者的顯示名稱。

      • RAM角色:<RoleName:RoleSessionName>

      說明

      RAM使用者和RAM角色請求時才會返回該參數。

      profile

      upn

      RAM使用者的登入名稱稱。

      說明

      RAM使用者請求時才會返回該參數。

      profile

      login_name

      阿里雲帳號(主帳號)的登入名稱稱。

      說明

      阿里雲帳號(主帳號)請求時才會返回該參數。

      profile

      aid

      登入使用者所屬的阿里雲帳號(主帳號)ID。

      aliuid

      uid

      登入使用者的ID。取值:

      • 阿里雲帳號(主帳號):阿里雲帳號(主帳號)ID,與aid相同。

      • RAM使用者:RAM使用者ID。

      • RAM角色:RAM角色ID。

      aliuid

  • 返回樣本

    • Header返回樣本

      {
        "alg": "RS256",
        "kid": "JC9wxzrhqJ0gtaCEt2QLUfevEUIwltFhui4O1bh****"
      }
    • Body返回樣本

      為了閱讀方便,以下展示的是未編碼的身份令牌的返回樣本。實際返回為編碼後的身份令牌,更多資訊,請參見樣本二:驗證身份令牌的JWT簽名

      • 阿里雲帳號請求時的Body返回樣本

        {
          "exp": 1517539523,
          "sub": "123456789012****",
          "aud": "4567890123456****",
          "iss": "https://oauth.alibabacloud.com",
          "iat": 1517535923,
          "type": "account",
          "login_name":"alice@example.com", //阿里雲帳號的登入名稱稱
          "aid": "123456789012****", //阿里雲帳號ID
          "uid": "123456789012****" //阿里雲帳號ID
        }
      • RAM使用者請求時的Body返回樣本

        {
          "exp": 1517539523,
          "sub": "123456789012****",
          "aud": "4567890123456****",
          "iss": "https://oauth.alibabacloud.com",
          "iat": 1517535923,
          "type": "user",
          "name": "alice", //RAM使用者的顯示名稱
          "upn": "alice@example.onaliyun.com", //RAM使用者的登入名稱稱
          "aid": "123456789012****", //RAM使用者所屬的阿里雲帳號ID
          "uid": "234567890123****" //RAM使用者ID
        }
      • RAM角色請求時的Body返回樣本

        {
          "exp": 1517539523,
          "sub": "123456789012****",
          "aud": "4567890123456****",
          "iss": "https://oauth.aliyun.com",
          "iat": 1517535923,
          "type": "role",
          "name": "NetworkAdministrator:alice", //RAM角色的顯示名稱
          "aid": "123456789012****", //RAM角色所屬的阿里雲帳號ID
          "uid": "300800165472****" //RAM角色ID
        }

樣本四:通過存取權杖和UserInfo介面擷取使用者資訊

除了直接擷取身份令牌,您也可以在擷取存取權杖後通過調用UserInfo介面擷取使用者資訊,該介面必須使用存取權杖才能訪問,返回資訊不編碼。

說明

OIDC情境下,即只有openidaliuidprofile這幾個範圍的時候,也會返回存取權杖,此時的存取權杖只能用於調用UserInfo介面。

UserInfo介面請求地址:https://oauth.alibabacloud.com/v1/userinfo

請求樣本如下:

GET v1/userinfo HTTP/1.1
Host: oauth.alibabacloud.com
Authorization: Bearer SIAV32hkKG

返回參數如下表所示:

參數名稱

描述

需要的OAuth範圍

sub

唯一代表登入使用者的字串,但並不包含阿里雲UID、使用者名稱等資訊。

openid

type

登入使用者類型。

profile

name

登入使用者的顯示名稱。

說明

RAM使用者和RAM角色請求時才會返回該參數。

profile

upn

RAM使用者的登入名稱稱。

說明

RAM使用者請求時才會返回該參數。

profile

login_name

阿里雲帳號(主帳號)的登入名稱稱。

說明

阿里雲帳號(主帳號)請求時才會返回該參數。

profile

aid

登入使用者所屬的阿里雲帳號(主帳號)ID。

aliuid

uid

登入使用者的ID。

aliuid

Body返回樣本如下:

  • 阿里雲帳號請求時的Body返回樣本

    HTTP/1.1 200 OK
    Content-Type: application/json
    {
      "sub": "123456789012****", 
      "type": "account",
      "login_name":"alice@example.com", //阿里雲帳號的登入名稱稱
      "aid": "123456789012****", //阿里雲帳號ID
      "uid": "123456789012****" //阿里雲帳號ID
    }
  • RAM使用者請求時的Body返回樣本

    HTTP/1.1 200 OK
    Content-Type: application/json
    {
      "sub": "123456789012****", 
      "type": "user",  
      "name": "alice", //RAM使用者的顯示名稱
      "upn": "alice@example.onaliyun.com", //RAM使用者的登入名稱稱
      "aid": "123456789012****", //RAM使用者所屬的阿里雲帳號ID
      "uid": "234567890123****" //RAM使用者ID
    }
  • RAM角色請求時的Body返回樣本

    HTTP/1.1 200 OK
    Content-Type: application/json
    {
      "sub": "123456789012****", 
      "type": "role",
      "name": "NetworkAdministrator:alice", //RAM角色的顯示名稱
      "aid": "123456789012****", //RAM角色所屬的阿里雲帳號ID
      "uid": "300800165472****" //RAM角色ID
    }