Du har skapat klientprogramobjektet. Nu använder du den för att hämta en token för att anropa ett webb-API. I ASP.NET eller ASP.NET Core görs anrop av ett webb-API i kontrollanten:
Microsoft.Identity.Web lägger till tilläggsmetoder som tillhandahåller bekvämlighetstjänster för att anropa Microsoft Graph eller ett underordnat webb-API. Dessa metoder beskrivs i detalj i En webbapp som anropar webb-API:er: Anropa ett API. Med de här hjälpmetoderna behöver du inte skaffa en token manuellt.
Om du däremot vill hämta en token manuellt visar följande kod ett exempel på hur du använder Microsoft.Identity.Web för att göra det i en hemstyrenhet. Den anropar Microsoft Graph med hjälp av REST-API:et (i stället för Microsoft Graph SDK). Vanligtvis behöver du inte hämta en token. Du måste skapa ett auktoriseringshuvud som du lägger till i din begäran. För att få ett auktoriseringshuvud matar du in IAuthorizationHeaderProvider
tjänsten genom beroendeinmatning i styrenhetens konstruktor (eller sidkonstruktorn om du använder Blazor) och använder den i dina kontrollantåtgärder. Det här gränssnittet har metoder som skapar en sträng som innehåller protokollet (Bearer, Pop, ...) och en token. Om du vill hämta ett auktoriseringshuvud för att anropa ett API för användarens räkning använder du (CreateAuthorizationHeaderForUserAsync
). Om du vill hämta ett auktoriseringshuvud för att anropa ett underordnat API för själva programmet använder du (CreateAuthorizationHeaderForAppAsync
) i ett daemonscenario.
Kontrollantmetoderna skyddas av ett [Authorize]
attribut som säkerställer att endast autentiserade användare kan använda webbappen.
[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 tillgängliggörs IAuthorizationHeaderProvider
genom beroendeinmatning.
Här är förenklad kod för åtgärden HomeController
, som hämtar en token för att anropa Microsoft Graph:
[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);
}
Mer information om vilken kod som krävs för det här scenariot finns i steget fas 2 (2-1-Webbapp anropar Microsoft Graph) i självstudiekursen ms-identity-aspnetcore-webapp-tutorial .
Attributet AuthorizeForScopes
ovanpå kontrollantåtgärden (eller på Razor-sidan om du använder en Razor-mall) tillhandahålls av Microsoft.Identity.Web. Det säkerställer att användaren tillfrågas om medgivande om det behövs och stegvis.
Det finns andra komplexa variationer, till exempel:
- Anropa flera API:er.
- Bearbeta inkrementellt medgivande och villkorsstyrd åtkomst.
Dessa avancerade steg beskrivs i kapitel 3 i självstudiekursen 3-WebApp-multi-API:er .
Koden för ASP.NET liknar koden som visas för ASP.NET Core:
- En kontrollantåtgärd som skyddas av ett
[Authorize]
attribut extraherar klientorganisations-ID:t och användar-ID:t för kontrollantens ClaimsPrincipal
medlem (ASP.NET använder HttpContext.User
). Detta säkerställer att endast autentiserade användare kan använda appen.
Microsoft.Identity.Web lägger till tilläggsmetoder till kontrollanten som tillhandahåller bekvämlighetstjänster för att anropa Microsoft Graph eller ett underordnat webb-API, eller för att hämta ett auktoriseringshuvud eller till och med en token. De metoder som används för att anropa ett API direkt förklaras i detalj i En webbapp som anropar webb-API:er: Anropa ett API. Med de här hjälpmetoderna behöver du inte skaffa en token manuellt.
Om du däremot vill hämta en token manuellt eller skapa en auktoriseringsrubrik visar följande kod hur du använder Microsoft.Identity.Web för att göra det i en kontrollant. Den anropar ett API (Microsoft Graph) med hjälp av REST-API:et i stället för Microsoft Graph SDK.
Om du vill hämta ett auktoriseringshuvud får du en IAuthorizationHeaderProvider
tjänst från kontrollanten med hjälp av en tilläggsmetod GetAuthorizationHeaderProvider
. Om du vill hämta ett auktoriseringshuvud för att anropa ett API åt användaren använder du CreateAuthorizationHeaderForUserAsync
. Om du vill hämta ett auktoriseringshuvud för att anropa ett underordnat API för själva programmet använder du CreateAuthorizationHeaderForAppAsync
i ett daemonscenario .
Följande kodfragment visar åtgärden HomeController
för , som hämtar ett auktoriseringshuvud för att anropa Microsoft Graph som ett 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);
}
}
Följande kodfragment visar åtgärden HomeController
för , som hämtar en åtkomsttoken för att anropa Microsoft Graph som ett 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);
}
}
I Java-exemplet finns koden som anropar ett API i getUsersFromGraph
metoden i AuthPageController.java#L62.
Metoden försöker anropa getAuthResultBySilentFlow
. Om användaren behöver godkänna fler omfång bearbetar MsalInteractionRequiredException
koden objektet för att utmana användaren.
@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
I det Node.js exemplet finns koden som hämtar en token i acquireToken
-metoden för AuthProvider
klassen.
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);
}
};
}
Den här åtkomsttoken används sedan för att hantera begäranden till /profile
slutpunkten:
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);
}
}
);
I Python-exemplet finns koden som anropar API:et i app.py.
Koden försöker hämta en token från tokencachen. Om den inte kan hämta en token omdirigeras användaren till inloggningsvägen. Annars kan det fortsätta att anropa API:et.
@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)