クライアント アプリケーション オブジェクトは構築済みです。 次はこれを使って Web API を呼び出すトークンを取得します。 ASP.NET または ASP.NET Core では、Web API の呼び出しはコントローラーで実行されます。
Microsoft.Identity.Web には、Microsoft Graph またはダウンストリーム Web API を呼び出す便利なサービスを提供する拡張メソッドが追加されています。 これらのメソッドの詳細については、「Web API を呼び出す Web アプリ: API を呼び出す」を参照してください。 これらのヘルパー メソッドを使用すれば、トークンを手動で取得する必要はありません。
ただし、トークンを手動で取得する場合は、ホーム コントローラーで取得することを目的とした Microsoft.Identity.Web の使用の例が、次のコードによって示されています。 これにより、REST API (Microsoft Graph SDK ではなく) を使用した、Microsoft Graph の呼び出しが行われます。 ダウンストリーム API を呼び出すためのトークンを取得するには、コントローラーのコンストラクター (Blazor を使用する場合はページ コンストラクター) に依存関係を挿入して、ITokenAcquisition サービスを挿入し、コントローラー アクションで使用します。これにより、ユーザーのトークン (GetAccessTokenForUserAsync)、またはデーモン シナリオでのアプリケーション自体 (GetAccessTokenForAppAsync) のトークンが取得されます。
コントローラー メソッドは、認証されたユーザーのみが Web アプリを使用できるようにする [Authorize] 属性によって保護されます。
[Authorize]
public class HomeController : Controller
{
readonly ITokenAcquisition tokenAcquisition;
public HomeController(ITokenAcquisition tokenAcquisition)
{
this.tokenAcquisition = tokenAcquisition;
}
// Code for the controller actions (see code below)
}
ITokenAcquisition サービスは、依存関係の挿入を使用して ASP.NET によって挿入されます。
Microsoft Graph を呼び出すトークンを取得する HomeController のアクションの簡略化されたコードを次に示します。
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Acquire the access token.
string[] scopes = new string[]{"user.read"};
string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
string json = await client.GetStringAsync(url);
}
このシナリオに必要なコードをさらに理解したい場合は、ms-identity-aspnetcore-Webapp-tutorial チュートリアルのフェーズ 2 (2-1-Web App Calls Microsoft Graph) の手順を参照してください。
コントローラー アクションの上 (または Razor テンプレートを使用する場合は Razor ページ) の AuthorizeForScopes 属性は、Microsoft.Identity.Web によって提供されます。 これにより、必要に応じて、かつ段階的にユーザーに同意が求められます。
次のような複雑なバリエーションもあります。
- 複数の API の呼び出し。
- 増分同意と条件付きアクセスの処理。
このような高度な手順については、3-WebApp-multi-APIs チュートリアルの第 3 章を参照してください。
ASP.NET のコードは、ASP.NET Core 用に示したコードと似ています。
- [Authorize] 属性によって保護されたコントローラー アクションは、コントローラーの
ClaimsPrincipal メンバーのテナント ID とユーザー ID を抽出します。 (ASP.NET は HttpContext.User を使用します。)
- そこから、MSAL.NET
IConfidentialClientApplication オブジェクトを構築します。
- 最後に、機密クライアント アプリケーションの
AcquireTokenSilent メソッドを呼び出します。
- 対話型操作が必要な場合は、Web アプリでユーザーをチャレンジ (再サインイン) し、追加の要求を求める必要があります。
注意
スコープは完全修飾スコープ名にする必要があります。 例: ({api_uri}/scope)。
次のコード スニペットは、ms-identity-aspnet-webapp-openidconnect ASP.NET MVC コード サンプルの HomeController.cs#L157-L192 から抜粋したものです。
public async Task<ActionResult> ReadMail()
{
IConfidentialClientApplication app = MsalAppBuilder.BuildConfidentialClientApplication();
AuthenticationResult result = null;
var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId());
string[] scopes = { "Mail.Read" };
try
{
// try to get token silently
result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false);
}
catch (MsalUiRequiredException)
{
ViewBag.Relogin = "true";
return View();
}
// More code here
return View();
}
詳細については、コード サンプルの BuildConfidentialClientApplication() と GetMsalAccountId のコードを参照してください
Java のサンプルでは、API を呼び出すコードは getUsersFromGraph メソッド (AuthPageController.java#L62) にあります。
メソッドから getAuthResultBySilentFlow の呼び出しが試行されます。 ユーザーがより多くのスコープに同意する必要がある場合、コードでは MsalInteractionRequiredException オブジェクトが処理され、ユーザーがチャレンジされます。
@RequestMapping("/msal4jsample/graph/me")
public ModelAndView getUserFromGraph(HttpServletRequest httpRequest, HttpServletResponse response)
throws Throwable {
IAuthenticationResult result;
ModelAndView mav;
try {
result = authHelper.getAuthResultBySilentFlow(httpRequest, response);
} catch (ExecutionException e) {
if (e.getCause() instanceof MsalInteractionRequiredException) {
// If the silent call returns MsalInteractionRequired, redirect to authorization endpoint
// so user can consent to new scopes.
String state = UUID.randomUUID().toString();
String nonce = UUID.randomUUID().toString();
SessionManagementHelper.storeStateAndNonceInSession(httpRequest.getSession(), state, nonce);
String authorizationCodeUrl = authHelper.getAuthorizationCodeUrl(
httpRequest.getParameter("claims"),
"User.Read",
authHelper.getRedirectUriGraph(),
state,
nonce);
return new ModelAndView("redirect:" + authorizationCodeUrl);
} else {
mav = new ModelAndView("error");
mav.addObject("error", e);
return mav;
}
}
if (result == null) {
mav = new ModelAndView("error");
mav.addObject("error", new Exception("AuthenticationResult not found in session."));
} else {
mav = new ModelAndView("auth_page");
setAccountInfo(mav, httpRequest);
try {
mav.addObject("userInfo", getUserInfoFromGraph(result.accessToken()));
return mav;
} catch (Exception e) {
mav = new ModelAndView("error");
mav.addObject("error", e);
}
}
return mav;
}
// Code omitted here
Python のサンプルでは、Microsoft Graph を呼び出すコードは app.py#L53-L62 にあります。
このコードでは、トークン キャッシュからのトークンの取得が試行されます。 次に、authorization ヘッダーが設定された後、Web API が呼び出されます。 トークンを取得できない場合は、ユーザーのサインインが再実行されます。
@app.route("/graphcall")
def graphcall():
token = _get_token_from_cache(app_config.SCOPE)
if not token:
return redirect(url_for("login"))
graph_data = requests.get( # Use token to call downstream service.
app_config.ENDPOINT,
headers={'Authorization': 'Bearer ' + token['access_token']},
).json()
return render_template('display.html', result=graph_data)