OAuth 単一ページアプリを使用した OpenAPI ベースのAEM API の呼び出し
- トピック:
- 開発
作成対象:
- 中級
- 開発者
- リーダー
OAuth シングルページアプリ認証 を使用して、AEM as a Cloud Serviceで OpenAPI ベースのAEM API を呼び出す方法を説明します。 これは、シングルページアプリケーション(SPA)でのユーザーベースの認証の OAuth 2.0 PKCE (Proof Key for Code Exchange)フローに従います。
OAuth シングルページアプリ認証は、ブラウザーで実行されるJavaScript ベースのアプリケーションに最適です。 バックエンドサーバーがない場合も、ユーザーの代わりにAEM API とやり取りするためにアクセストークンを取得する必要がある場合も同様です。
PKCE フローは、OAuth 2.0 authorization_code 付与タイプを拡張し、認証コードの傍受を防いでセキュリティを強化します。 詳しくは、OAuth サーバー間資格情報と web アプリ間資格情報とシングルページアプリ資格情報の違いを参照してください。
学習内容
このチュートリアルでは、次の方法を学びます。
-
Adobe Developer Console(ADC)プロジェクトを設定し、OAuth シングルページアプリ 認証、または一般的に OAuth 2.0 PKCE フロー と呼ばれる)を使用して、OpenAPI ベースのAEM API にアクセスします。
-
カスタム SPA で OAuth 単一ページアプリ認証フローを実装します。
- IMS ユーザー認証とアプリ認証。
- OAuth 2.0 PKCE フローを使用したアクセストークン取得。
- アクセストークンを使用して、OpenAPI ベースのAEM API を呼び出します。
開始する前に、次の点を確認してください。
- Adobe API へのアクセスと関連概念節を参照してください。
- OpenAPI ベースのAEM API の設定記事
WKND SPA の概要と機能フロー
WKND SPA とは何か、WKND SPA の構築方法、WKND SPA の機能を見てみましょう。
WKND SPA は、ユーザー固有のアクセストークンを安全に取得し、クライアントサイドから直接AEM API とやり取りする方法を示す React ベースのシングルページアプリケーション です。 Adobe IMSを通じた OAuth 2.0 PKCE 認証フローを実装し、次の 2 つの主要なAEM API と統合されています。
- Sites API:コンテンツフラグメントモデルへのアクセス用
- Assets API: DAM フォルダーの管理用
Adobe Developer Console(ADC)プロジェクトは、OAuth シングルページアプリ認証を有効にするように設定されており、OAuth 2.0 PKCE フローを開始するために必要な client_id を提供します。
次の図に、WKND SPA の機能フローを示します OpenAPI ベースのAEM API を呼び出すためのユーザー固有のアクセストークンを取得する。
- SPA が認証フローを開始するには、認証リクエストを使用してAdobe Identity Management System (IMS)にユーザーを誘導します。
- 認証リクエストの一環として、SPA は、OAuth 2.0 PKCE フローに従って、client_id、redirect_uri および code_challenge を IMS に送信します。 SPA はランダムな code_verifier を生成し、SHA-256 を使用してハッシュ化し、Base64 がその結果をエンコードして code_challenge を作成します。
- IMS がユーザーを認証し、認証に成功すると、authorization_code を発行し、redirect_uri 経由で SPA に返されます。
- SPA は、IMS トークンエンドポイントに POST リクエストを送信することで、authorization_code と access token を交換します。 これには、前に送信した code_challenge を検証するリクエストに code_verifier が含まれます。 これにより、認証リクエスト(手順 2)とトークンリクエスト(手順 4)が同じ認証フローにリンクされ、傍受の攻撃を防ぐことができます。
- IMS は code_verifier を検証し、ユーザー固有の アクセストークン を返します。
- SPA では、AEMに対する API リクエストに アクセストークン を含めて、ユーザー固有のコンテンツを認証および取得します。
WKND SPA は React ベースのアプリケーションであり、認証状態の管理には React コンテキストを使用し、ナビゲーションには React ルーターを使用します。
Angular、Vue、vanilla JavaScriptなどの他の SPA フレームワークを使用して、このチュートリアルで示すアプローチに従ってAdobe API と統合する SPA を作成できます。
このチュートリアルの使用方法
このチュートリアルには、次の 2 つの方法があります。
- SPA の主要なコードスニペットの確認:OAuth 単一ページアプリ認証フローを理解し、WKND SPA での主要な API 呼び出し実装について説明します。
- SPA の設定と実行:段階的な手順に従って、ローカルマシンに WKND SPA を設定し実行します。
ニーズに合ったパスを選択
SPA キーコードスニペットの確認
次の方法を示す WKND SPA の主要なコードスニペットについて説明します。
-
OAuth 単一ページアプリ認証フローを使用して、ユーザー固有のアクセストークンを取得します。
-
クライアント側から直接 OpenAPI ベースのAEM API を呼び出します。
これらのスニペットは、SPA 内の認証プロセスと API のインタラクションを理解するのに役立ちます。
SPA コードのダウンロード
-
WKND SPA およびAEM API - デモアプリzip ファイルをダウンロードして抽出します。
-
抽出したフォルダーに移動し、お気に入りのコードエディターで
.env.example
ファイルを開きます。 必要な設定パラメーターを確認します。######################################################################## # Adobe IMS, Adobe Developer Console (ADC), and AEM as a Cloud Service Information ######################################################################## # Adobe IMS OAuth endpoints REACT_APP_ADOBE_IMS_AUTHORIZATION_ENDPOINT=https://ims-na1.adobelogin.com/ims/authorize/v2 REACT_APP_ADOBE_IMS_TOKEN_ENDPOINT=https://ims-na1.adobelogin.com/ims/token/v3 # Adobe Developer Console (ADC) Project's OAuth Single-Page App credential REACT_APP_ADC_CLIENT_ID=<ADC Project OAuth Single-Page App credential ClientID> REACT_APP_ADC_SCOPES=<ADC Project OAuth Single-Page App credential Scopes> # AEM Assets Information REACT_APP_AEM_ASSET_HOSTNAME=<AEMCS Hostname, e.g., https://author-p63947-e1502138.adobeaemcloud.com/> ################################################ # Single Page Application Information ################################################ # Enable HTTPS for local development HTTPS=true PORT=3001 # SSL Certificate and Key for local development SSL_CRT_FILE=./ssl/server.crt SSL_KEY_FILE=./ssl/server.key # The URL to which the user will be redirected after the OAuth flow is complete REACT_APP_REDIRECT_URI=https://localhost:3000/callback
プレースホルダーを、Adobe Developer Console(ADC)プロジェクトおよびAEM as a Cloud Service Assets インスタンスからの実際の値に置き換える必要があります。
IMS ユーザー認証と SPA 認証
IMS ユーザー認証と SPA 認証を処理するコードを見てみましょう。 コンテンツフラグメントモデルと DAM フォルダーを取得するには、Adobe IMSによる認証を行い、WKND SPA に対して、AEM API へのアクセス権限を付与する必要があります。
最初のログイン中に、ユーザーは同意を入力するように求められ、WKND SPA が必要なリソースに安全にアクセスできるようになります。
-
ファイル
src/context/IMSAuthContext.js
は、login
関数が IMS ユーザー認証およびアプリ承認フローを開始します。 ランダムなcode_verifier
とcode_challenge
を生成して、code
とアクセストークンを安全に交換します。code_verifier
は、後で使用するためにローカルストレージに保存されます。 前述のように、SPA はclient_secret
を保存または使用せず、その場で 1 つを生成し、authorize
リクエストとtoken
リクエストの 2 つの手順で使用します。... const login = async () => { try { const codeVerifier = generateCodeVerifier(); const codeChallenge = generateCodeChallenge(codeVerifier); localStorage.setItem(STORAGE_KEYS.CODE_VERIFIER, codeVerifier); const params = new URLSearchParams( getAuthParams(AUTH_METHODS.S256, codeChallenge, codeVerifier) ); window.location.href = `${ APP_CONFIG.adobe.ims.authorizationEndpoint //https://ims-na1.adobelogin.com/ims/authorize/v2 }?${params.toString()}`; } catch (error) { console.error("Login initialization failed:", error); throw error; } }; ... // Generate a random code verifier export function generateCodeVerifier() { const array = new Uint8Array(32); window.crypto.getRandomValues(array); const wordArray = CryptoJS.lib.WordArray.create(array); return base64URLEncode(wordArray); } // Generate code challenge using SHA-256 export function generateCodeChallenge(codeVerifier) { const hash = CryptoJS.SHA256(codeVerifier); return base64URLEncode(hash); } // Get authorization URL parameters const getAuthParams = useCallback((method, codeChallenge, codeVerifier) => { const baseParams = { client_id: APP_CONFIG.adobe.adc.clientId, // ADC Project OAuth Single-Page App credential ClientID scope: APP_CONFIG.adobe.adc.scopes, // ADC Project OAuth Single-Page App credential Scopes response_type: "code", redirect_uri: APP_CONFIG.adobe.spa.redirectUri, // SPA redirect URI https://localhost:3000/callback code_challenge_method: method, // S256 or plain }; return { ...baseParams, code_challenge: method === AUTH_METHODS.S256 ? codeChallenge : codeVerifier, }; }, []); ...
ユーザーがユーザーに対して認証されていない場合は、Adobe IMSの認証を求めるAdobe ID ログインページが表示されます。
既に認証されている場合、ユーザーは authorization_code を使用して WKND SPA の指定された redirect_uri にリダイレクトされます。
OAuth 2.0 PKCE フローを使用したアクセストークン取得
WKND SPA は、client_id および code_verifier を使用して、authorization_code をAdobe IMSとユーザー固有のアクセストークンのために安全に交換します。
-
src/context/IMSAuthContext.js
ファイルで、exchangeCodeForToken
関数は authorization_code をユーザー固有のアクセストークンと交換します。... // Handle the callback from the Adobe IMS authorization endpoint const handleCallback = async (code) => { if (authState.isProcessingCallback) return; try { updateAuthState({ isProcessingCallback: true }); const data = await exchangeCodeForToken(code); if (data.access_token) { handleStorageToken(data.access_token); localStorage.removeItem(STORAGE_KEYS.CODE_VERIFIER); } } catch (error) { console.error("Error exchanging code for token:", error); throw error; } finally { updateAuthState({ isProcessingCallback: false }); } }; ... // Exchange the authorization code for an access token const exchangeCodeForToken = useCallback(async (code) => { const codeVerifier = localStorage.getItem(STORAGE_KEYS.CODE_VERIFIER); if (!codeVerifier) { throw new Error("No code verifier found"); } //https://ims-na1.adobelogin.com/ims/token/v3 const response = await fetch(APP_CONFIG.adobe.ims.tokenEndpoint, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "authorization_code", client_id: APP_CONFIG.adobe.adc.clientId, // ADC Project OAuth Single-Page App credential ClientID code_verifier: codeVerifier, // Code verifier generated during login code, // Authorization code received from the IMS redirect_uri: `${window.location.origin}/callback`, }), }); if (!response.ok) { throw new Error("Token request failed"); } return response.json(); }, []); const handleStorageToken = useCallback( (token) => { if (token) { localStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token); updateAuthState({ isLoggedIn: true, accessToken: token }); } }, [updateAuthState] ); ...
アクセストークンはブラウザーのローカルストレージに保存され、AEM API への後続の API 呼び出しで使用されます。
アクセストークンを使用した OpenAPI ベースのAEM API へのアクセス
WKND SPA では、ユーザー固有のアクセストークンを使用して、コンテンツフラグメントモデルと DAM フォルダー API エンドポイントを呼び出します。
src/components/InvokeAemApis.js
ファイルでは、fetchContentFragmentModels
関数は、アクセストークンを使用して、OpenAPI ベースのAEM API をクライアント側から呼び出す方法を示しています。
...
// Fetch Content Fragment Models
const fetchContentFragmentModels = useCallback(async () => {
try {
updateState({ isLoading: true, error: null });
const data = await makeApiRequest({
endpoint: `${API_PATHS.CF_MODELS}?cursor=0&limit=10&projection=summary`,
});
updateState({ cfModels: data.items });
} catch (err) {
updateState({ error: err.message });
console.error("Error fetching CF models:", err);
} finally {
updateState({ isLoading: false });
}
}, [makeApiRequest, updateState]);
// Common API request helper
const makeApiRequest = useCallback(
async ({ endpoint, method = "GET", passAPIKey = false, body = null }) => {
// Get the access token from the local storage
const token = localStorage.getItem("adobe_ims_access_token");
if (!token) {
throw new Error("No access token available. Please login again.");
}
const headers = {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
...(passAPIKey && { "x-api-key": APP_CONFIG.adobe.adc.clientId }),
};
const response = await fetch(
`${APP_CONFIG.adobe.aem.hostname}${endpoint}`,
{
method,
headers,
...(body && { body: JSON.stringify(body) }),
}
);
if (!response.ok) {
throw new Error(`API request failed: ${response.statusText}`);
}
return method === "DELETE" ? null : response.json();
},
[]
);
...
SPA のセットアップと実行
OAuth 単一ページアプリ認証フローと API 呼び出しを理解するために、WKND SPA をローカルマシンで設定して実行します。
前提条件
このチュートリアルを完了するには、次が必要になります。
-
AEM as a Cloud Service環境を最新化し、次の機能を実現しました。
- AEM リリース
2024.10.18459.20241031T210302Z
以降。 - 新しいスタイルの製品プロファイル(2024 年 11 月より前に環境が作成された場合)
詳しくは、OpenAPI ベースのAEM API のセットアップの記事を参照してください。
- AEM リリース
-
サンプルの WKND Sites プロジェクトをこのプロジェクトにデプロイする必要があります。
-
Adobe Developer Console にアクセスします。
-
Node.js をローカルマシンにインストールして、サンプルの NodeJS アプリケーションを実行します。
開発手順
大まかな開発手順は次のとおりです。
-
ADC プロジェクトの設定
- Assets API と Sites API を追加します。
- OAuth 単一ページアプリの資格情報を設定します。
-
AEM インスタンスの設定
- ADC プロジェクト通信を有効にするには
- CORS を設定して SPA がAEM API にアクセスできるようにします。
-
ローカルマシンでの WKND SPA の設定と実行
-
エンドツーエンドフローの検証
ADC プロジェクトの設定
ADC プロジェクトの設定手順が、OpenAPI ベースのAEM API の設定から 繰り返し されます。 Assetsと Sites API を追加し、その認証方法を OAuth 単一ページアプリとして設定する手順は繰り返されます。
-
Adobe Developer Console から目的のプロジェクトを開きます。
-
AEM API を追加するには、「API を追加」ボタンをクリックします。
-
API を追加 ダイアログで、Experience Cloudでフィルタリングし 「AEM CS Sites コンテンツ管理」カードを選択して、「次へ」をクリックします。
-
次に、API を設定 ダイアログで「ユーザー認証 認証オプションを選択し、「次へ」をクリックします。
-
次の API を設定 ダイアログで、OAuth 単一ページアプリ 認証オプションを選択し、次へ をクリックします。
-
OAuth 単一ページアプリを設定 ダイアログで、次の詳細を入力し、「次へ」をクリックします。
- 既定のリダイレクト URI:
https://localhost:3001/callback
- リダイレクト URI パターン:
https://localhost:3001/callback
- 既定のリダイレクト URI:
-
使用可能なスコープを確認し、「設定済み API を保存」をクリックします。
-
上記の手順を繰り返して、AEM Assets オーサー API を追加します。
-
AEM API と認証設定を確認します。
ADC プロジェクト通信を有効にする AEM インスタンスの設定
OpenAPI ベースのAEM API の設定の記事の手順に従って、AEM インスタンスを設定し、ADC プロジェクト通信を有効にします。
AEMの CORS 設定
AEM as a Cloud Serviceのクロスオリジンリソース共有(CORS)は、AEM以外の web プロパティが、AEM API へのブラウザーベースのクライアントサイド呼び出しを行うのを容易にします。
-
AEM プロジェクトで、
/ui.config/src/main/content/jcr_root/apps/wknd/osgiconfig/config.author/
フォルダーからcom.adobe.granite.cors.impl.CORSPolicyImpl~wknd-graphql.cfg.json
ファイルを見つけるか作成します。 -
次の設定をファイルに追加します。
{ "alloworigin":[ "" ], "alloworiginregexp":[ "https://localhost:.*", "http://localhost:.*" ], "allowedpaths": [ "/adobe/sites/.*", "/graphql/execute.json.*", "/content/_cq_graphql/wknd-shared/endpoint.json", "/content/experience-fragments/.*" ], "supportedheaders": [ "Origin", "Accept", "X-Requested-With", "Content-Type", "Access-Control-Request-Method", "Access-Control-Request-Headers", "Authorization" ], "supportedmethods":[ "GET", "HEAD", "POST" ], "maxage:Integer": 1800, "supportscredentials": true, "exposedheaders":[ "" ] }
-
設定変更をコミットし、Cloud Manager パイプラインが接続されているリモート Git リポジトリに変更をプッシュします。
-
Cloud Managerでフルスタックパイプラインを使用して、上記の変更をデプロイします。
SPA の設定と実行
-
WKND SPA およびAEM API - デモアプリzip ファイルをダウンロードして抽出します。
-
抽出されたフォルダーに移動し、
.env.example
ファイルを.env
にコピーします。 -
Adobe Developer Console(ADC)プロジェクトおよびAEM as a Cloud Service環境の必要な設定パラメーターを使用して、
.env
ファイルを更新します。 例:######################################################################## # Adobe IMS, Adobe Developer Console (ADC), and AEM as a Cloud Service Information ######################################################################## # Adobe IMS OAuth endpoints REACT_APP_ADOBE_IMS_AUTHORIZATION_ENDPOINT=https://ims-na1.adobelogin.com/ims/authorize/v2 REACT_APP_ADOBE_IMS_TOKEN_ENDPOINT=https://ims-na1.adobelogin.com/ims/token/v3 REACT_APP_ADOBE_IMS_USERINFO_ENDPOINT=https://ims-na1.adobelogin.com/ims/userinfo/v2 # Adobe Developer Console (ADC) Project's OAuth Single-Page App credential REACT_APP_ADC_CLIENT_ID=ddsfs455a4a440c48c7474687c96945d REACT_APP_ADC_SCOPES=AdobeID,openid,aem.folders,aem.assets.author,aem.fragments.management # AEM Assets Information REACT_APP_AEM_ASSET_HOSTNAME=https://author-p69647-e1453424.adobeaemcloud.com/ ################################################ # Single Page Application Information ################################################ # Enable HTTPS for local development HTTPS=true PORT=3001 # SSL Certificate and Key for local development SSL_CRT_FILE=./ssl/server.crt SSL_KEY_FILE=./ssl/server.key # The URL to which the user will be redirected after the OAuth flow is complete REACT_APP_REDIRECT_URI=https://localhost:3000/callback
-
ターミナルを開き、抽出されたフォルダーに移動します。 必要な依存関係をインストールし、次のコマンドを使用して WKND SPA を開始します。
$ npm install $ npm start
エンドツーエンドフローの検証
-
ブラウザーを開き、
https://localhost:3001
に移動して WKND SPA にアクセスします。 自己署名証明書の警告を受け入れます。 -
「Adobe IMSログイン」ボタンをクリックして、OAuth シングルページアプリ認証フローを開始します。
-
Adobe IMSに対して認証を行い、WKND SPA がユーザーに代わってリソースにアクセスすることを許可するための同意を得ます。
-
認証が成功すると、WKND SPA の
/invoke-aem-apis
ルートにリダイレクトされ、アクセストークンがブラウザーのローカルストレージに保存されます。 -
https://localhost:3001/invoke-aem-apis
ルートで、「コンテンツフラグメントモデルを取得」ボタンをクリックして、コンテンツフラグメントモデル API を呼び出します。 SPA にコンテンツフラグメントモデルのリストが表示されます。 -
同様に、「Assets - フォルダー API」タブでは、DAM フォルダーの一覧表示、作成および削除を行うことができます。
-
ブラウザーの開発者ツールで、ネットワークリクエストと応答を調べて、API 呼び出しを理解できます。
SPA コードを確認する
WKND SPA の全体的なコード構造と主なエントリポイントを確認してみましょう。 SPA は、React フレームワークを使用して構築され、認証と状態管理に React コンテキスト API を使用します。
-
src/App.js
ファイルは、WKND SPA の主なエントリポイントです。 アプリコンポーネントは、アプリケーション全体をラップし、IMSAuthProvider
コンテキストを初期化します。 -
src/context/IMSAuthContext.js
は、子コンポーネントに認証状態を提供するAdobe IMSAuthContext を作成します。 OAuth 単一ページアプリ認証フローを開始するための login、logout、handleCallback 関数が含まれます。 -
src/components
フォルダーには、AEM API への API 呼び出しを示す様々なコンポーネントが含まれています。InvokeAemApis.js
コンポーネントは、アクセストークンを使用してAEM API を呼び出す方法を示しています。 -
src/config/config.js
ファイルは、.env
ファイルから環境変数を読み込み、アプリケーションで使用するために書き出します。 -
src/utils/auth.js
ファイルには、OAuth 2.0 PKCE フローのコードベリファイアおよびコードチャレンジを生成するユーティリティ関数が含まれています。 -
ssl
フォルダーには、ローカル SSL HTTP プロキシを実行するための自己署名証明書とキーファイルが含まれています。
このチュートリアルに示すアプローチを使用して、既存の SPA をAdobe API と統合することができます。
概要
このチュートリアルでは、OAuth 2.0 PKCE フローを介してシングルページアプリ(SPA)からユーザーベースの認証を使用して、AEM as a Cloud Serviceで OpenAPI ベースのAEM API を呼び出す方法を学びました。