このトピックでは、OktaからAlibaba CloudへのOpenID Connect (OIDC) ベースのシングルサインオン (SSO) の実装方法の例を示します。 その後、Oktaに登録されているアプリケーションは、Security Token Service (STS) トークンを使用してAlibaba Cloudリソースに安全にアクセスできます。
前提条件
OIDCアプリケーションはOktaに登録されています。 発行者のURLとアプリケーションのクライアントIDを取得する。 この例では、次のデータが使用されます。
発行者のURLは
https://dev-xxxxxx.okta.com
です。クライアントIDは
0oa294vi1vJo Clev ****
です。
ステップ1: Alibaba CloudでのOIDC IDプロバイダー (IdP) の作成
このステップでは、TestOidcProvider
という名前のOIDC IdPが作成されます。 発行者のURLは https://dev-xxxxxx.okta.com
で、クライアントIDは0oa294vi1vJo Clev ****
です。
にログインします。RAMコンソールAlibaba Cloudアカウントを使用します。
左側のナビゲーションウィンドウで、 .
[ロールベースSSO] タブで、[OIDC] タブをクリックします。 次に、[IdPの追加] をクリックします。
On theIdPの作成ページで、次のパラメーターを設定します。
パラメーター
説明
IdP名
名前はAlibaba Cloudアカウント内で一意である必要があります。
IdP URL
外部IdPによって提供される発行者のURL。 外部IdPによって提供される発行者のURL。 発行者のURLは
https
で始まり、有効なURLである必要があります。 URLには、疑問符 (?
) に続くクエリパラメーター、アットマーク (@
) で識別されるログオン情報、または番号記号 (#
) で識別されるフラグメントを含めることはできません。指紋
外部IdPのHTTPS証明書に基づいて生成されるフィンガープリント。 指紋を使用して、発行者のURLがハイジャックされたり改ざんされたりするのを防ぐことができます。 Alibaba Cloudはフィンガープリントを計算します。 コンピューターで指紋を計算することをお勧めします。 たとえば、OpenSSLを使用してフィンガープリントを計算できます。 次に、計算結果とAlibaba Cloudが提供する計算結果を比較できます。 OpenSSLの詳細については、OpenSSLの公式Webサイトをご覧ください。 計算結果が異なる場合、発行者のURLが攻撃された可能性があります。 有効な指紋を入力してください。
説明IdPの証明書をローテーションする場合は、新しい証明書のフィンガープリントを生成し、ローテーションの前にRAMコンソールで作成したOIDC IdPにフィンガープリントを追加することをお勧めします。 少なくとも1日後、証明書をローテーションします。 Security Token Service (STS) トークンを取得した後、以前のフィンガープリントを削除できます。
クライアントID
アプリケーションを外部IdPに登録するときに生成されるID。 外部IdPからOIDCトークンを申請するときは、クライアントIDを使用する必要があります。 クライアントIDは、発行されるOIDCトークンの
aud
フィールドで指定されます。 OIDC IdPを作成するときは、クライアントIDを設定する必要があります。 OIDCトークンを使用してSTSトークンを取得する場合、Alibaba Cloudは、aud
フィールドで指定されたクライアントIDがOIDC IdPで設定したクライアントIDと同じであるかどうかを確認します。 クライアントIDが同じである場合にのみ、RAMロールを引き受けることができます。複数のクライアントがAlibaba Cloudリソースにアクセスする必要がある場合は、複数のクライアントIDを設定できます。 最大20のクライアントIDを設定できます。
補足
OIDC IdPの説明。
クリックOK.
手順2: Alibaba CloudでOIDC IdPのRAMロールを作成する
このステップでは、testoidc
という名前のRAMロールが作成され、ステップ1で作成したTestOidcProvider
OIDC IdPが選択されます。
にログインします。RAMコンソール管理者権限を持つRAMユーザーとして
左側のナビゲーションウィンドウで、 .
On theロールページをクリックします。ロールの作成.
On theロールの作成ページを選択します。IdP[信頼できるエンティティの選択] セクションで、次へ.
を指定します。Specify theRAMロール名と注パラメーターを使用します。
IdP TypeパラメーターにOIDCを選択します。
信頼できるIdPを選択し、条件を指定します。
次の表に、サポートされる条件を示します。
条件キー
説明
必須
例
oidc:iss
発行者。 RAMロールを引き受けることができるのは、RAMロールを引き受けるために使用するOIDCトークンのissフィールドがこの条件を満たしている場合のみです。
条件演算子はStringEqualsでなければなりません。 値は、選択したOIDC IdPに指定した発行者のURLである必要があります。 この条件を指定すると、信頼できるIdPによってOIDCトークンが発行された場合にのみ、OIDCトークンを使用してRAMロールを引き受けることができます。
可
https://dev-xxxxxx.okta.com
oidc:aud
聴衆。 RAMロールを引き受けることができるのは、RAMロールを引き受けるために使用するOIDCトークンのaudフィールドがこの条件を満たしている場合のみです。
条件演算子はStringEqualsでなければなりません。 値は、選択したOIDC IdPに指定する1つ以上のクライアントIDにすることができます。 この条件を指定すると、指定したクライアントIDを使用してOIDCトークンが生成された場合にのみ、OIDCトークンを使用してRAMロールを引き受けることができます。
可
0oa294vi1vJo Clev ****
oidc: サブ
主題。 RAMロールを引き受けることができるのは、RAMロールを引き受けるために使用するOIDCトークンのサブフィールドがこの条件を満たしている場合のみです。
条件演算子は、すべての型の文字列にすることができます。 値は最大10人の被験者にすることができます。 この条件を指定して、RAMロールを引き受けるために使用できるIDをさらに制限できます。 この条件を指定しないままにすることもできます。
任意
00u294e3mzNXt4Hi ****
クリックOK.
クリック閉じる.
ステップ3: RAMロールに権限を付与する
ビジネス要件に基づいてAlibaba Cloudリソースにアクセスするために、ステップ2で作成したtestoidc
という名前のRAMロールに権限を付与できます。
にログインします。RAMコンソールRAM管理者として
左側のナビゲーションウィンドウで、 .
On theロールページで、管理するRAMロールを見つけて、をクリックします。権限付与で、アクション列を作成します。
複数のRAMロールを選択し、RAMロールリストの下部にある [権限の付与] をクリックして、一度に複数のRAMロールに権限を付与することもできます。
では、権限付与パネルで、RAMロールに権限を付与します。
Resource Scopeパラメーターを設定します。
アカウント: 権限付与は、現在のAlibaba Cloudアカウントで有効になります。
リソースグループ: 権限付与は、特定のリソースグループに対して有効になります。
説明[リソーススコープ] パラメーターで [リソースグループ] を選択した場合、必要なクラウドサービスがリソースグループをサポートしていることを確認します。 詳細については、「リソースグループで動作するサービス」をご参照ください。
Principalパラメーターを設定します。
プリンシパルは、権限を付与するRAMロールです。 現在のRAMロールが自動的に選択されます。
Policyパラメーターを設定します。
ポリシーは一連のアクセス権限です。 一度に複数のポリシーを選択できます。
システムポリシー: Alibaba Cloudによって作成されたポリシー。 これらのポリシーは使用できますが、変更することはできません。 ポリシーのバージョン更新は、Alibaba Cloudによって管理されます。 詳細については、「RAMで動作するサービス」をご参照ください。
説明システムは、AdministratorAccessやAliyunRAMFullAccessなどのリスクの高いシステムポリシーを自動的に識別します。 リスクの高いポリシーをアタッチして、不要な権限を付与しないことを推奨します。
カスタムポリシー: ビジネス要件に基づいてカスタムポリシーを管理および更新できます。 カスタムポリシーを作成、更新、削除できます。 詳細については、「カスタムポリシーの作成」をご参照ください。
[権限付与] をクリックします。
クリック閉じる.
ステップ4: OktaでOIDCトークンを発行する
OIDCを使用してAlibaba Cloud管理コンソールにログインすることはできません。 したがって、プログラムアクセスを使用してOIDCベースのSSOを実装する必要があります。 OIDCトークンを取得するには、Open authorization (OAuth) を使用して承認を完了する必要があります。 したがって、OktaなどのOIDC IdPからOIDCトークンを取得するには、OAuth 2.0を使用する必要があります。 OAuthは、承認コードフローなどのさまざまなフローをサポートします。 詳細については、「承認コードフロー」をご参照ください。 しかしながら、認証コードフローは複雑である。 次のセクションでは、暗黙のフローを使用して、OIDCトークンを取得してSSOを実装する方法を説明します。 暗黙のフローの一部の操作については、このトピックでは説明しません。 暗黙的なフローの詳細については、「暗黙的なフロー」をご参照ください。
Oktaによって発行されたOIDCトークンを受け取るwebアプリケーションをビルドします。
この例では、Java Spring BootとThymeleafを使用して構築された単純なwebアプリケーションを使用しています。 webアプリケーションはコンピューターにデプロイされ、ポート8080経由でアクセスでき、localhostは127.0.0.1に解決されます。 したがって、コンピューターのブラウザーでlocalhost:8080と入力して、webアプリケーションにアクセスできます。 次のサンプルコードを提供します。
静的ページのサンプルコード
OAuth 2.0では、Oktaがwebアプリケーションに送信するコールバック情報が、コールバックURLのフラグメントコンポーネントで渡される必要があります。 webページを作成し、フラグメントコンポーネントからOIDCトークンを取得できます。 この例では、単純な静的ページが作成されます。 次に、フラグメントコンポーネントを透過的に渡すことができます。 このページの完全なURLは、
http:// localhost:8080/accessTokenCallback
です。これは、Oktaのアプリケーション用に設定されたコールバックURLredirect_uri
でもあります。<!DOCTYPE HTML> <html xmlns:th=" http://www.thymeleaf.org "> <head> <script> window.onload = function () { let fragment = window.location.hash.substring (1); window.location.href = "/receiveAccessToken?" + フラグメント; }; </script> </head> </html>
クラスのサンプルコード
静的ページのコントローラとしてクラスが作成されます。
パッケージcom.aliyun.oauthtest; org.springframework.stereotype.Controllerをインポートします。org.springframework.web.bind.annotation.RequestMappingをインポートします。@ コントローラー public class CallbackController { @ RequestMapping("accessTokenCallback") public String callback() { "accessTokenCallback" を返します。 } }
Oktaにログインし、OktaからOIDCトークンを申請します。
Oktaにログインする必要があります。 次に、URL
https://dev-xxxxxx.okta.com/oauth2/v1/authorize?client_id=0oa294vi1vJoClev ****&scope=openid&response_type=token % 20id_token&state=testState&nonce=a_unique_nonce_1&redirect_uri=http % 3A % 2F % 2Flocalhost % 3A8080% 2FaccessTokenCallback
を構築してアクセスできます。手順1でビルドされたwebアプリケーション。次のリストは、URLのパラメーターについて説明しています。
client_id
: このパラメーターをOktaに登録されているOIDCアプリケーションのクライアントIDに設定します。scope
: このパラメーターをopenid
に設定します。response_type
: 暗黙的なフローで、このパラメーターをtoken id_token
に設定します。state
: OIDCアプリケーションの現在のステータスを指定します。 このパラメーターは、ビジネス要件に基づいて設定できます。nonce
: このパラメーターは、リプレイ攻撃を防ぐために使用されます。 このパラメーターは、ビジネス要件に基づいて設定できます。redirect_uri
: このパラメーターを、access_token
またはid_token
の受信に使用するコールバックURLに設定します。 この例では、このパラメーターを、サブステップ1で作成したwebアプリケーションのURLに設定します。
この例では、Oktaにログインしています。 したがって、指定された
redirect_uri
に基づいてコールバックURLにリダイレクトされます。 次のURLのid_token
の値は、OIDCトークンです。HTTP/1.1 302が見つかりました 場所: http:// localhost:8080/accessTokenCallback#id_token=eyJraWQiOiJ6OUV0e ****&access_token=eyJraWQiOiJseEQ3R ****&token_type=Bearer&expires_in=3600&scope=openid&state=testState
OIDCトークンを解析します。
サブステップ2で取得した結果を解析し、
ヘッダー
とペイロード
に関する詳細を照会できます。リクエストの例
パッケージcom.aliyun.oauthtest; java.util.Base64をインポートします。java.util.Base64.Decoderをインポートします。java.util.HashMapをインポートします。java.util.Mapをインポートします。java.util.TreeMapをインポートします。com.alibaba.fastjson.JSONをインポートします。com.alibaba.fastjson.JSONObjectをインポートします。org.springframework.web.bind.annotation.RequestMappingをインポートします。org.springframework.web.bind.annotation.RequestMethodをインポートします。org.springframework.web.bind.annotation.RequestParamをインポートします。org.springframework.web.bind.annotation.RestControllerをインポートします。@ RestController public class ClientAppController { @ RequestMapping(value = "/receiveAccessToken" 、method = {RequestMethod.POST、RequestMethod.GET} 、 produces = "application/json") public Map<String, Object> receiveAccessToken(@ RequestParam("access_token")) String accessToken, @ RequestParam("id_token") 文字列idToken、 @ RequestParam("token_type") 文字列tokenType、 @ RequestParam("expires_in") 長いexpireTime、 @ RequestParam("scope") 文字列スコープ、 @ RequestParam("state") String state) { Map<String, Object> result = new TreeMap<>(); result.put("access_token", accessToken); result.put("id_token", idToken); result.put("token_type", tokenType); result.put("expires_in", "+ expireTime); result.put("scope", scope); result.put("state", state); String[] jwt = idToken.split("\\."); デコーダデコーダ=Base64.getDecoder(); result.put("id token jwt header", JSON.parse(new String(decoder.de code(jwt[0])))); result.put("id token jwt payload", JSON.parse(new String(decoder.de code(jwt[1])))); result.put("id token jwt signature", jwt[2]); return result; } }
レスポンス例:
{ "id token jwt header": { "kid": "z9EtyT345d-JLIJo2-5ySDO27LG4FPeOotbwJPT ****" 、 "alg": "RS256" }, "id token jwt payload": { "at_hash": "KKsdN3prZWTvBEMn-g ****" 、 "sub": "00u294e3mzNXt4Hi ****" 、 "aud": "0oa294vi1vJo Clev ****" 、 "ver": 1、 "idp": "0oa294iehxjUCZIO ****" 、 "amr": [ "pwd" ], "auth_time": 1636373097、 "iss": " https://dev-xxxxxx.okta.com " 、 "exp": 1636377759、 "iat": 1636374159、 "nonce": "a_unique_nonce_1" 、 "jti": "ID.lmSU5AD2iKLCVu6_KLMIr52dpCprncxW38v-NCA ****" }, "id token jwt signature": "ZEJEGIv4Zoau63 ****" 、 "access_token": "eyJraWQiOiJseEQ3R ****" 、 "expires_in": "3600" 、 "id_token": "eyJraWQiOiJ6OUV0e ****" 、 "scope": "openid" 、 "state": "testState" 、 "token_type": "Bearer" }
ステップ5: OIDCトークンを使用してSTSトークンを取得する
STSトークンを取得するには、AssumeRoleWithOIDC操作を呼び出します。 リクエストで、ステップ4で取得した解析されていないOIDCトークンを指定します。
リクエストの例
public static void main(String[] args)
{
IAcsClientクライアント=初期化 ();
String jwtToken = "eyJraWQiOiJ6OUV0e ****"; // Oktaから取得した解析されていないOIDCトークン。 トークンはid_tokenの値です。
AssumeRoleWithOIDCRequest request = new AssumeRoleWithOIDCRequest();
request.setDurationSeconds(3600L);
request.setOIDCProviderArn("acs:ram::113511544585 ****:oidc-provider/TestOidcProvider");
request.setOIDCToken(jwtToken);
request.setRoleArn("acs:ram::113511544585 ****:role/testoidc");
request.setRoleSessionName("TestOidcAssumedRoleSession");
try
{
AssumeRoleWithOIDCResponse resp = client.getAcsResponse (リクエスト);
System.out.println("success requestId: " + resp.getRequestId());
System.out.println("success assume role arn: " + resp.getAssumedRoleUser().getArn());
System.out.println("success sts credential accessKey id: " + resp.getCredentials().getAccessKeyId());
System.out.println("success sts credential accessKey secret: " + resp.getCredentials().getAccessKeySecret());
System.out.println("success resp: " + JSON.toJSONString(resp));
}
catch(ClientException | SystemException e)
{
e.printStackTrace();
}
}
レスポンス例:
success requestId: 3D57EAD2-8723-1F26-B69C-F8707D8B565D
success assume role arn: acs:ram::113511544585 ****:role/testoidc/TestOidcAssumedRoleSession
success stsクレデンシャルaccessKey id: STS.NUgYrLnoC37mZZCNnAbez ****
success stsクレデンシャルaccessKey secret: CVwjCkNzTMupZ8NbTCxCBRq3K16jtcWFTJAyBEv2 ****
resp成功:
{
"AssumedRoleUser":
{
"Arn": "acs:ram::113511544585 ****:role/testoidc/TestOidcAssumedRoleSession" 、
"AssumedRoleId": "33157794895460 ****:TestOidcAssumedRoleSession"
},
「資格情報」:
{
"AccessKeyId": "STS.NUgYrLnoC37mZZCNnAbez ****" 、
"AccessKeySecret": "CVwjCkNzTMupZ8NbTCxCBRq3K16jtcWFTJAyBEv2 ****" 、
"有効期限": "2021-10-20T04:27:09Z" 、
"SecurityToken": "CAIShwJ1q6Ft5B2yfSjIr ****"
},
"OIDCTokenInfo":
{
"ClientIds": "0oa294vi1vJo Clev ****" 、
"発行者": " https://dev-xxxxxx.okta.com " 、
「件名」: 「00u294e3mzNXt4Hi **** 」
},
"RequestId": "3D57EAD2-8723-1F26-B69C-F8707D8B565D"
}
[資格情報]
の情報は、STSトークンに関する情報です。
手順6: STSトークンを使用したAlibaba Cloudリソースへのアクセス
ステップ5で取得したSTSトークンを使用して、権限を持つAlibaba Cloudリソースにアクセスします。