Vytvořili jste objekt klientské aplikace. Teď ho použijete k získání tokenu pro volání webového rozhraní API. V ASP.NET nebo ASP.NET Core se volání webového rozhraní API provádí v kontroleru:
Microsoft.Identity.Web přidává rozšiřující metody, které poskytují pohodlné služby pro volání Microsoft Graphu nebo podřízeného webového rozhraní API. Tyto metody jsou podrobně vysvětleny ve webové aplikaci, která volá webová rozhraní API: Volání rozhraní API. Pomocí těchto pomocných metod nemusíte token získat ručně.
Pokud ale chcete token získat ručně, následující kód ukazuje příklad použití Microsoft.Identity.Web k tomu na domovském řadiči. Volá Microsoft Graph pomocí rozhraní REST API (místo sady Microsoft Graph SDK). Obvykle nepotřebujete získat token, musíte vytvořit autorizační hlavičku, kterou přidáte do požadavku. Pokud chcete získat autorizační hlavičku, vložíte IAuthorizationHeaderProvider
službu injektáží závislostí do konstruktoru kontroleru (nebo konstruktoru stránky, pokud používáte Blazor) a použijete ji v akcích kontroleru. Toto rozhraní obsahuje metody, které vytvářejí řetězec obsahující protokol (Bearer, Pop, ...) a token. Pokud chcete získat autorizační hlavičku pro volání rozhraní API jménem uživatele, použijte (CreateAuthorizationHeaderForUserAsync
). Pokud chcete získat autorizační hlavičku pro volání podřízeného rozhraní API jménem samotné aplikace, použijteCreateAuthorizationHeaderForAppAsync
().
Metody kontroleru jsou chráněny atributem [Authorize]
, který zajišťuje, že webovou aplikaci můžou používat jenom ověření uživatelé.
[Authorize]
public class HomeController : Controller
{
readonly IAuthorizationHeaderProvider authorizationHeaderProvider;
public HomeController(IAuthorizationHeaderProvider authorizationHeaderProvider)
{
this.authorizationHeaderProvider = authorizationHeaderProvider;
}
// Code for the controller actions (see code below)
}
ASP.NET Core zpřístupňuje IAuthorizationHeaderProvider
injektáž závislostí.
Tady je zjednodušený kód akce HomeController
, který získá token pro volání Microsoft Graphu:
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Acquire the access token.
string[] scopes = new string[]{"user.read"};
string accessToken = await authorizationHeaderProvider.CreateAuthorizationHeaderForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", accessToken);
string json = await client.GetStringAsync(url);
}
Pokud chcete lépe porozumět kódu potřebnému pro tento scénář, podívejte se na krok fáze 2 (2-1-Web App Calls Microsoft Graph) kurzu ms-identity-aspnetcore-webapp-tutorial.
AuthorizeForScopes
Atribut nad akcí kontroleru (nebo na stránce Razor Page, pokud používáte šablonu Razor), poskytuje Microsoft.Identity.Web. Zajistí, že se uživateli v případě potřeby zobrazí výzva k vyjádření souhlasu a přírůstkově.
Existují i další složité varianty, například:
- Volání několika rozhraní API
- Zpracování přírůstkového souhlasu a podmíněného přístupu
Tyto pokročilé kroky jsou popsány v kapitole 3 kurzu 3-WebApp-multi-API .
Kód ASP.NET se podobá kódu zobrazenému pro ASP.NET Core:
- Akce kontroleru chráněná
[Authorize]
atributem extrahuje ID tenanta a ID ClaimsPrincipal
uživatele člena kontroleru (ASP.NET používá HttpContext.User
). Tím se zajistí, že aplikaci můžou používat jenom ověření uživatelé.
Microsoft.Identity.Web přidává do kontroleru metody rozšíření, které poskytují služby pro usnadnění volání Microsoft Graphu nebo podřízeného webového rozhraní API nebo získání autorizační hlavičky nebo dokonce tokenu. Metody používané k přímému volání rozhraní API jsou podrobně vysvětleny ve webové aplikaci, která volá webová rozhraní API: Volání rozhraní API. Pomocí těchto pomocných metod nemusíte token získat ručně.
Pokud ale chcete token získat ručně nebo vytvořit autorizační hlavičku, následující kód ukazuje, jak to udělat v kontroleru pomocí Microsoft.Identity.Web. Volá rozhraní API (Microsoft Graph) pomocí rozhraní REST API místo sady Microsoft Graph SDK.
Pokud chcete získat autorizační hlavičku, získáte IAuthorizationHeaderProvider
službu z kontroleru pomocí metody GetAuthorizationHeaderProvider
rozšíření . Pokud chcete získat autorizační hlavičku pro volání rozhraní API jménem uživatele, použijte CreateAuthorizationHeaderForUserAsync
. Pokud chcete získat autorizační hlavičku pro volání podřízeného rozhraní API jménem samotné aplikace, použijte CreateAuthorizationHeaderForAppAsync
ve scénáři démona .
Následující fragment kódu ukazuje akci HomeController
, která získá autorizační hlavičku pro volání Microsoft Graphu jako rozhraní REST API:
[Authorize]
public class HomeController : Controller
{
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Get an authorization header.
IAuthorizationHeaderProvider authorizationHeaderProvider = this.GetAuthorizationHeaderProvider();
string[] scopes = new string[]{"user.read"};
string authorizationHeader = await authorizationHeaderProvider.CreateAuthorizationHeaderForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
string json = await client.GetStringAsync(url);
}
}
Následující fragment kódu ukazuje akci HomeController
, která získá přístupový token pro volání Microsoft Graphu jako rozhraní REST API:
[Authorize]
public class HomeController : Controller
{
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Get an authorization header.
ITokenAcquirer tokenAcquirer = TokenAcquirerFactory.GetDefaultInstance().GetTokenAcquirer();
string[] scopes = new string[]{"user.read"};
string token = await tokenAcquirer.GetTokenForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
string json = await client.GetStringAsync(url);
}
}
V ukázce Javy je kód, který volá rozhraní API, v getUsersFromGraph
metodě v AuthPageController.java#L62.
Metoda se pokusí volat getAuthResultBySilentFlow
. Pokud uživatel potřebuje souhlas s více obory, kód zpracuje MsalInteractionRequiredException
objekt tak, aby uživatele vyzval.
@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
V ukázce Node.js kód, který získá token, je v acquireToken
metodě AuthProvider
třídy.
acquireToken(options = {}) {
return async (req, res, next) => {
try {
const msalInstance = this.getMsalInstance(this.msalConfig);
/**
* If a token cache exists in the session, deserialize it and set it as the
* cache for the new MSAL CCA instance. For more, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/caching.md
*/
if (req.session.tokenCache) {
msalInstance.getTokenCache().deserialize(req.session.tokenCache);
}
const tokenResponse = await msalInstance.acquireTokenSilent({
account: req.session.account,
scopes: options.scopes || [],
});
/**
* On successful token acquisition, write the updated token
* cache back to the session. For more, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/caching.md
*/
req.session.tokenCache = msalInstance.getTokenCache().serialize();
req.session.accessToken = tokenResponse.accessToken;
req.session.idToken = tokenResponse.idToken;
req.session.account = tokenResponse.account;
res.redirect(options.successRedirect);
} catch (error) {
if (error instanceof msal.InteractionRequiredAuthError) {
return this.login({
scopes: options.scopes || [],
redirectUri: options.redirectUri,
successRedirect: options.successRedirect || '/',
})(req, res, next);
}
next(error);
}
};
}
Tento přístupový token se pak použije ke zpracování požadavků na /profile
koncový bod:
router.get('/profile',
isAuthenticated, // check if user is authenticated
async function (req, res, next) {
try {
const graphResponse = await fetch(GRAPH_ME_ENDPOINT, req.session.accessToken);
res.render('profile', { profile: graphResponse });
} catch (error) {
next(error);
}
}
);
V ukázce Pythonu je kód, který volá rozhraní API, ve app.py.
Kód se pokusí získat token z mezipaměti tokenů. Pokud se mu nedaří získat token, přesměruje ho na přihlašovací trasu. Jinak může pokračovat voláním rozhraní API.
@app.route("/call_downstream_api")
def call_downstream_api():
token = auth.get_token_for_user(app_config.SCOPE)
if "error" in token:
return redirect(url_for("login"))
# Use access token to call downstream api
api_result = requests.get(
app_config.ENDPOINT,
headers={'Authorization': 'Bearer ' + token['access_token']},
timeout=30,
).json()
return render_template('display.html', result=api_result)