サード パーティの OAuth IdP 認証を構成する
注:
モバイル クライアントのタブで認証を機能させるには、Microsoft Teams JavaScript クライアント ライブラリ (TeamsJS) のバージョン 1.4.1 以降を使用していることを確認します。
Microsoft Teams アプリは、Facebook、Twitter、Teams など、さまざまなサービスと対話する必要がある場合があります。 これらのサービスのほとんどは、アクセスに認証と承認を必要とします。 Teams は、Microsoft Graph を使用してユーザー プロファイル情報を Microsoft Entra ID に格納します。 この記事では主に、この情報にアクセスするための認証に Microsoft Entra ID を使用することに重点を置いています。
Microsoft Entra ID やその他の多数のサービス プロバイダーは、認証のオープン標準である OAuth 2.0 を使用しています。 Teams と Microsoft Entra ID で認証を処理する場合は、OAuth 2.0 を理解することが不可欠です。 提供される例では、OAuth 2.0 の暗黙的な許可フローを使用します。このフローでは、Microsoft Entra ID と Microsoft Graph からユーザーのプロファイル情報を取得します。
この記事のコードは、Teams サンプル アプリ Microsoft Teams Authentication Sample (Node) からのものです。 これには、Microsoft Graph のアクセス トークンを要求し、現在のユーザーの基本的なプロファイル情報を Microsoft Entra ID から表示する静的タブが含まれています。
タブの認証フローの概要については、「タブ 内の認証フロー」を参照してください。
タブの認証フローは、ボットの認証フローとは異なります。
注:
このトピックでは、Microsoft Teams JavaScript クライアント ライブラリ (TeamsJS) のバージョン 2.0.x を反映しています。 以前のバージョンを使用している場合は、 最新の TeamsJS と以前のバージョンの違いに関するガイダンスについては、TeamsJS ライブラリの概要を参照してください。
Microsoft Entra ID を ID プロバイダーとして使用するようにアプリを構成する
OAuth 2.0 サポート ID プロバイダーは、登録されていないアプリケーションからの要求を認証しません。 そのため、事前にアプリケーションを登録することが重要です。 Microsoft Entra ID でアプリケーションを登録するには、次の手順に従います。
アプリケーション登録ポータルを開きます。
アプリを選択してそのプロパティを表示するか、[新しい登録] ボタンを選択します。 アプリの [リダイレクト URI ] セクションを見つけます。
ドロップダウン メニューから [ Web ] を選択し、認証エンドポイントへの URL を更新します。 GitHub で使用できる TypeScript/Node.js および C# サンプル アプリでは、リダイレクト URL も同様のパターンに従います。
リダイレクト URL:
https://<hostname>/bot-auth/simple-start
<hostname>
を実際のホストに置き換えます。 このホストには、Azure、Glitch などの専用ホスティング サイト、または開発マシン上の localhost への ngrok トンネル ( abcd1234.ngrok.io
など) を指定できます。 この情報がない場合は、アプリ (またはサンプル アプリ) を完了またはホストしていることを確認します。 この情報がある場合は、このプロセスを再開します。
注:
LinkedIn、Google など、任意のサード パーティの OAuth プロバイダーを選択できます。 これらのプロバイダーの認証を有効にするプロセスは、サード パーティの OAuth プロバイダーとして Microsoft Entra ID を使用するのと似ています。 サード パーティの OAuth プロバイダーの使用の詳細については、特定のプロバイダーの Web サイトを参照してください。
認証フローを開始する
注:
試験的なサード パーティ製ストレージのパーティション分割が有効になっている場合、サード パーティの認証は失敗します。 アプリは、値がローカルに格納されないため、認証を繰り返し求めます。
ユーザー アクションによって認証フローをトリガーします。 ブラウザーのポップアップ ブロックをトリガーし、ユーザーを混乱させる可能性が高く、認証ポップアップを自動的に開かないようにします。
構成ページまたはコンテンツ ページにボタンを追加して、必要に応じてユーザーがサインインできるようにします。 これは、タブ 構成 ページまたは 任意のコンテンツ ページで実行できます。
Microsoft Entra ID は、ほとんどの ID プロバイダーと同様に、そのコンテンツを iframe
に配置することを許可しません。 つまり、Teams クライアントがポップアップ ウィンドウ内に表示する ID プロバイダーをホストするページを追加する必要があります。 次の例では、ページが /tab-auth/simple-start
されています。 ボタンが選択されている場合は、TeamsJS ライブラリの authentication.authenticate()
関数を使用して、このページを起動します。
import { authentication } from "@microsoft/teams-js";
authentication.authenticate({
url: window.location.origin + "/tab-auth/simple-start-v2",
width: 600,
height: 535})
.then((result) => {
console.log("Login succeeded: " + result);
let data = localStorage.getItem(result);
localStorage.removeItem(result);
let tokenResult = JSON.parse(data);
showIdTokenAndClaims(tokenResult.idToken);
getUserProfile(tokenResult.accessToken);
})
.catch((reason) => {
console.log("Login failed: " + reason);
handleAuthError(reason);
});
メモ
authenticate()
に渡す URL は、認証フローの開始ページです。 この例では、/tab-auth/simple-start
。 これは、 Microsoft Entra アプリケーション登録ポータルで登録した内容と一致する必要があります。認証フローは、ドメイン上のページから開始する必要があります。 このドメインは、マニフェストの [
validDomains
] セクションにも一覧表示する必要があります。 実行に失敗すると、空のポップアップが表示されます。authenticate()
を使用できない場合は、サインイン プロセスの最後にポップアップが閉じず、問題が発生する可能性があります。
ポップアップ ページから承認ページに移動します
ポップアップ ページ (/tab-auth/simple-start
) が表示されると、次のコードが実行されます。 ページの主な目標は、ユーザーがサインインできるように ID プロバイダーにリダイレクトすることです。 このリダイレクトは、HTTP 302 を使用してサーバー側で行うことができますが、この場合は、 window.location.assign()
の呼び出しを使用してクライアント側で行われます。 これにより、 app.getContext()
を使用してヒント情報を取得し、Microsoft Entra ID に渡すこともできます。
app.getContext().then((context) => {
// Generate random state string and store it, so we can verify it in the callback
let state = _guid(); // _guid() is a helper function in the sample
localStorage.setItem("simple.state", state);
localStorage.removeItem("simple.error");
// Go to the Azure AD authorization endpoint
let queryParams = {
client_id: "{{appId}}",
response_type: "id_token token",
response_mode: "fragment",
scope: "https://graph.microsoft.com/User.Read openid",
redirect_uri: window.location.origin + "/tab/simple-end",
nonce: _guid(),
state: state,
// The context object is populated by Teams; the loginHint attribute
// is used as hinting information
login_hint: context.user.loginHint,
};
let authorizeEndpoint = `https://login.microsoftonline.com/${context.user.tenant.id}/oauth2/v2.0/authorize?${toQueryString(queryParams)}`;
window.location.assign(authorizeEndpoint);
});
ユーザーが承認を完了すると、ユーザーは /tab-auth/simple-end
でアプリ用に指定したコールバック ページにリダイレクトされます。
メモ
- 認証要求と URL の構築に関するヘルプについては、「 ユーザー コンテキスト情報を取得 する」を参照してください。 たとえば、Microsoft Entra サインインの
login_hint
値としてユーザーのログイン名を使用できます。つまり、ユーザーが入力する必要が少なくなる可能性があります。 攻撃者が悪意のあるブラウザーにページを読み込み、必要な情報を提供する可能性があるため、ID の証明としてこのコンテキストを直接使用しないでください。 - タブ コンテキストはユーザーに関する有用な情報を提供しますが、この情報を使用して、タブ コンテンツ URL の URL パラメーターとして取得するか、Microsoft Teams JavaScript クライアント ライブラリ (TeamsJS) で
app.getContext()
関数を呼び出してユーザーを認証しないでください。 悪意のあるアクターが独自のパラメーターを使用してタブ コンテンツ URL を呼び出す可能性があり、Microsoft Teams偽装している Web ページは、iframe にタブ コンテンツ URL を読み込み、独自のデータをgetContext()
関数に返す可能性があります。 タブ コンテキストの ID 関連の情報は、単にヒントとして扱い、使用する前に検証する必要があります。 -
state
パラメーターは、コールバック URI を呼び出すサービスが呼び出したサービスであることを確認するために使用されます。 コールバックのstate
パラメーターが、呼び出し中に送信したパラメーターと一致しない場合、戻り値の呼び出しは検証されないため、終了する必要があります。 - アプリの manifest.json ファイルの
validDomains
リストに ID プロバイダーのドメインを含める必要はありません。
コールバック ページ
最後のセクションでは、Microsoft Entra 承認サービスを呼び出し、Microsoft Entra ID がユーザーに独自のモノリシック承認エクスペリエンスを提供できるように、ユーザーとアプリの情報を渡しました。 アプリでは、このエクスペリエンスで何が起こるかを制御できなくなります。 Microsoft Entra ID が指定したコールバック ページ (/tab-auth/simple-end
) を呼び出したときに返される内容は、すべて認識されます。
このページでは、Microsoft Entra ID によって返される情報に基づいて成功または失敗を判断し、 authentication.notifySuccess()
または authentication.notifyFailure()
を呼び出す必要があります。 ログインが成功した場合は、サービス リソースにアクセスできます。
// Split the key-value pairs passed from Azure AD
// getHashParameters is a helper function that parses the arguments sent
// to the callback URL by Azure AD after the authorization call
let hashParams = getHashParameters();
if (hashParams["error"]) {
// Authentication/authorization failed
localStorage.setItem("simple.error", JSON.stringify(hashParams));
} else if (hashParams["access_token"]) {
// Get the stored state parameter and compare with incoming state
let expectedState = localStorage.getItem("simple.state");
if (expectedState !== hashParams["state"]) {
// State does not match, report error
localStorage.setItem("simple.error", JSON.stringify(hashParams));
authentication.notifyFailure("StateDoesNotMatch");
} else {
// Success -- return token information to the parent page.
// Use localStorage to avoid passing the token via notifySuccess; instead we send the item key.
let key = "simple.result";
localStorage.setItem(key, JSON.stringify({
idToken: hashParams["id_token"],
accessToken: hashParams["access_token"],
tokenType: hashParams["token_type"],
expiresIn: hashParams["expires_in"]
}));
authentication.notifySuccess(key);
}
} else {
// Unexpected condition: hash does not contain error or access_token parameter
localStorage.setItem("simple.error", JSON.stringify(hashParams));
authentication.notifyFailure("UnexpectedFailure");
}
このコードでは、getHashParameters()
ヘルパー関数を使用して、window.location.hash
で Microsoft Entra ID から受信したキーと値のペアを解析します。
access_token
が検出され、state
値が認証フローの開始時に指定されたものと同じである場合は、notifySuccess()
を呼び出してタブにアクセス トークンを返します。それ以外の場合は、notifyFailure()
でエラーを報告します。
メモ
NotifyFailure()
には、次の定義済みのエラー理由があります。
CancelledByUser
ユーザーは、認証フローを完了する前にポップアップ ウィンドウを閉じました。注:
ログイン ページで
Cross-Origin-Opener-Policy
応答ヘッダーにsame-origin
値またはsame-origin-allow-popups
値を使用しないことをお勧めします。これは、親ウィンドウへの接続が中断され、認証 API 呼び出しがCancelledByUser
エラーで途中で返されるためです。FailedToOpenWindow
ポップアップ ウィンドウを開くことができませんでした。 ブラウザーでMicrosoft Teamsを実行する場合、これは通常、ポップアップ ブロックによってウィンドウがブロックされたことを意味します。
成功した場合は、ページを更新または再読み込みし、現在認証されているユーザーに関連するコンテンツを表示できます。 認証が失敗すると、エラー メッセージが表示されます。
アプリは、ユーザーが現在のデバイスのタブに戻ったときに再びサインインする必要がないように、独自のセッション Cookie を設定できます。
注:
- Chrome 80 (2020 年初頭にリリース予定) では、新しい Cookie 値を紹介し、既定で Cookie ポリシーを設定します。 既定のブラウザーの動作を利用するのではなく、Cookie に対して使用する目的を設定することをお勧めします。 SameSite cookie 属性 (2020 update)を参照してください。
- 無料ユーザーとゲスト ユーザー Microsoft Teams適切なトークンを取得するには、アプリがテナント固有のエンドポイント
https://login.microsoftonline.com/**{tenantId}**
を利用していることを確認します。 tenantId は、ボット メッセージまたはタブ コンテキストから取得できます。 アプリでhttps://login.microsoftonline.com/common
を使用している場合、ユーザーが正しくないトークンを受け取り、サインインしているテナントではなく "ホーム" テナントにログインする可能性があります。
シングル サインオン (SSO) の詳細については、 サイレント認証に関する記事を参照してください。
コード サンプル
Microsoft Entra ID を使用したタブ認証プロセスを示すサンプル コード:
サンプルの名前 | 説明 | .NET | Node.js | マニフェスト |
---|---|---|---|---|
タブ SSO | このサンプル アプリは、Teams のタブに対する Microsoft Entra SSO を示しています。 | 表示 |
表示、 Teams Toolkit |
該当なし |
タブ、ボット、メッセージ拡張機能 (ME) SSO | このサンプルでは、Tab、Bot、ME- search、action、link unfurl の SSO を示します。 | 表示 | 表示 | 表示 |
関連項目
Platform Docs