はじめに
溜まっていた下書きの棚卸しです🤦♂️
Azure API Managementを触っていく中で、認証方法に関するチュートリアルを見つけ自己流にアレンジしてみました。
今回、React(ローカル)からAPI Managementを通してAzure FunctionsにAPIを投げたいと思います。
(Azure Functionsは事前にデプロイ済みのものを使います。)
※チュートリアル
環境
- Windows11
- Visual Studio Code
- 事前にデプロイ済みのAzure Functions
- 事前にリソース作成済みのAPI Management
①API ManagementにAzure Functionsを追加する
- API Managementのリソースに移動します
- 左側の【API】タブをクリックします
- 【+Add API】をクリックし、【Function App】を選択します
- 【Browser】をクリックします
- 事前に準備したFunctionをインポートします
- 【Create】ボタンを押して完了します
②Azure Functionsで認証プロバイダーを追加する
6.追加後に作成されたクライアントIDをメモリします 7. 認証を追加したことでAPI実行に認証情報が含まれていないとエラーが出ることを確認します③API Managementに要求を事前承認する検証ポリシーを構成する
APIManagementのJWT検証とReactアプリからAPIを投げるためCORSを構成します
APIデザインのコードにインバウンドタグを以下のように編集します
テナントIDとクライアントIDはご自身のものに書き換えてください
<inbound>
<base />
<set-backend-service id="apim-generated-policy" backend-id="{FunctionID}" />
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<openid-config url="https://login.microsoftonline.com/{テナントID}/.well-known/openid-configuration" />
<required-claims>
<claim name="aud" match="all">
<value>api://{②で作成されたクライアントID}</value>
</claim>
</required-claims>
</validate-jwt>
<cors allow-credentials="false">
<allowed-origins>
<origin>http://localhost:3000</origin>
</allowed-origins>
<allowed-methods>
<method>GET</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
</cors>
</inbound>
④ReactアプリをAzure ActiveDirectoryに登録します
- Azure Active Directoryに移動し、【アプリケーションの登録】をクリックします
- 項目を埋め【登録】をクリックします
- 【認証】タブに移動しプラットフォームの追加でSPAを選択し、リダイレクトURLに「http://localhost:3000」を入力します
- APIのアクセス許可に②で追加したFunctionsの認証を許可するように設定します
⑤Reactアプリを作成します
- 「npx create-react-app app --template typescript」でReactアプリを作成します
- axiosと@azure/msal-browserをインストールします
- App.tsxを編集します
import React from 'react';
import './App.css';
import axios from 'axios';
import { PublicClientApplication } from "@azure/msal-browser";
const msalConfig = {
auth: {
clientId: 'クライアントID',
redirectUri: 'http://localhost:3000',
authority: 'https://login.microsoftonline.com/{テナントID}',
}
};
const msalInstance = new PublicClientApplication(msalConfig);
function App() {
const getAPI = async () => {
try
{
const accounts = await msalInstance.getAllAccounts();
const silentRequest = {
scopes: ['api://{FunctionのクライアントID}/user_impersonation'],
account: accounts[0]
};
const result = await msalInstance.acquireTokenPopup(silentRequest);
await axios.get('https://{APIManangementのリソース名}.azure-api.net/{表示名}/{API名}', {
headers: {
'Authorization': `Bearer ${result.accessToken}`,
}
})
.then(res => {
console.log(`Response:\t${res.status}`);
console.log(`Content:\t${res.data}`);
})
}
catch (error)
{
console.log(error);
}
}
return (
<div className="App">
<button className="btn btn-primary" onClick={() => getAPI()}>Click me</button>
</div>
);
}
export default App;
- 「npm start」でアプリを実行し、画面上のボタンをクリックするとAPIが実行され実行結果がコンソールに表示されると思います
所感
MSのチュートリアルを自己流に変換してみました。
現状だとReactからFunctionにもリクエストを送れる状態になってしまっているため、機会があればAPI Management経由しか受け付けないように構成をしてみたいと思いました。
※IPのアクセス制御方法は以下