Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In deze handleiding wordt uitgelegd hoe u downstream-API's aanroept vanuit ASP.NET Core- en OWIN-webtoepassingen met behulp van Microsoft. Identity.Web. In web-apps verkrijgt u tokens namens de aangemelde gebruiker om API's aan te roepen met gedelegeerde machtigingen.
Inzicht in de tokenstroom
Wanneer een gebruiker zich aanmeldt bij uw webtoepassing, kunt u downstream-API's (Microsoft Graph, Azure services of aangepaste API's) namens hen aanroepen. Microsoft. Identity.Web verwerkt tokenverwerving, caching en automatisch vernieuwen.
De gebruikerstokenstroom controleren
sequenceDiagram
participant User as User Browser
participant WebApp as Your Web App
participant AzureAD as Microsoft Entra ID
participant API as Downstream API
User->>WebApp: 1. Access page requiring API data
Note over WebApp: User already signed in
WebApp->>AzureAD: 2. Request access token for API<br/>(using user's refresh token)
AzureAD->>AzureAD: 3. Validate & check consent
AzureAD->>WebApp: 4. Return access token
Note over WebApp: Cache token
WebApp->>API: 5. Call API with token
API->>WebApp: 6. Return data
WebApp->>User: 7. Render page with data
Vereisten bekijken
Controleer of uw omgeving voldoet aan de volgende vereisten voordat u begint.
- Web-app geconfigureerd met OpenID Connect-verificatie
- Aanmelden van gebruiker werkt
- App-registratie met API-machtigingen geconfigureerd
- Gebruikerstoestemming verkregen (of beheerderstoestemming verleend)
ASP.NET Core implementeren
1. Verificatie inrichten en tokens ophalen
Voeg authenticatieservices toe en schakel in uw Program.cs bestand het verkrijgen van tokens in.
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add authentication with explicit scheme
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = options.DefaultPolicy;
});
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
2. Configureer appsettings.json
Definieer uw Microsoft Entra ID-app-registratie- en downstream-API-instellingen in appsettings.json.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath": "/signout-callback-oidc",
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret": "your-client-secret"
}
]
},
"DownstreamApis": {
"GraphAPI": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": ["user.read", "mail.read"]
},
"MyAPI": {
"BaseUrl": "https://myapi.example.com",
"Scopes": ["api://my-api-id/access_as_user"]
}
}
}
Belangrijk: Voor web-apps die downstream-API's aanroepen, hebt u clientreferenties (certificaat of geheim) nodig naast de aanmeldingsconfiguratie.
3. Ondersteuning voor downstream-API toevoegen
Kies een van de volgende opties om uw downstream-API's te registreren.
Optie A: Benoemde API's registreren
Met de volgende code worden meerdere downstream-API's van de configuratie geregistreerd.
using Microsoft.Identity.Web;
// Register multiple downstream APIs
builder.Services.AddDownstreamApis(
builder.Configuration.GetSection("DownstreamApis"));
Option B: Gebruik Microsoft Graph Helper
Met de volgende code wordt de Microsoft Graph SDK-client geregistreerd bij de configuratie.
// Install: Microsoft.Identity.Web.GraphServiceClient
builder.Services.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApis:GraphAPI"));
4. Downstream-API aanroepen vanaf controller
Injecteer IDownstreamApi in uw controller en roep de API aan namens de aangemelde gebruiker.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web;
using Microsoft.Identity.Abstractions;
[Authorize]
public class ProfileController : Controller
{
private readonly IDownstreamApi _downstreamApi;
private readonly ILogger<ProfileController> _logger;
public ProfileController(
IDownstreamApi downstreamApi,
ILogger<ProfileController> logger)
{
_downstreamApi = downstreamApi;
_logger = logger;
}
public async Task<IActionResult> Index()
{
try
{
// Call downstream API on behalf of user
var userData = await _downstreamApi.GetForUserAsync<UserData>(
"MyAPI",
options => options.RelativePath = "api/profile");
return View(userData);
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
// Incremental consent required
// Redirect user to consent page
return Challenge(
new AuthenticationProperties
{
RedirectUri = "/Profile"
},
OpenIdConnectDefaults.AuthenticationScheme);
}
catch (HttpRequestException ex)
{
_logger.LogError(ex, "Failed to call downstream API");
return View("Error");
}
}
}
5. Downstream-API aanroepen vanaf Razor Page
Injecteer IDownstreamApi in uw Razor Page-model en roep de API aan.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Identity.Web;
using Microsoft.Identity.Abstractions;
[Authorize]
public class ProfileModel : PageModel
{
private readonly IDownstreamApi _downstreamApi;
public UserData UserData { get; set; }
public ProfileModel(IDownstreamApi downstreamApi)
{
_downstreamApi = downstreamApi;
}
public async Task OnGetAsync()
{
try
{
UserData = await _downstreamApi.GetForUserAsync<UserData>(
"MyAPI",
options => options.RelativePath = "api/profile");
}
catch (MicrosoftIdentityWebChallengeUserException)
{
// Handle incremental consent
// User will be redirected to consent page
throw;
}
}
}
Microsoft Graph aanroepen
Gebruik voor oproepen van de Microsoft Graph-API de toegewezen GraphServiceClient.
Pakketten installeren
Installeer het Microsoft Graph-pakket voor Microsoft. Identity.Web.
dotnet add package Microsoft.Identity.Web.GraphServiceClient
Configureer de Graph-client in uw opstartcode.
// Startup configuration
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(options =>
{
options.Scopes = "user.read mail.read";
})
.AddInMemoryTokenCaches();
De Graph API aanroepen
Injecteer GraphServiceClient in de controller om Microsoft Graph eindpunten aan te roepen.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Graph;
[Authorize]
{
private readonly GraphServiceClient _graphClient;
public HomeController(GraphServiceClient graphClient)
{
_graphClient = graphClient;
}
public async Task<IActionResult> Index()
{
// Get current user's profile
var user = await _graphClient.Me.GetAsync();
// Get user's emails
var messages = await _graphClient.Me.Messages
.GetAsync(config => config.QueryParameters.Top = 10);
return View(new { User = user, Messages = messages });
}
}
Meer informatie over Microsoft Graph integratie
Azure SDK-clients aanroepen
Gebruik MicrosoftIdentityTokenCredential voor het aanroepen van Azure-services.
Pakketten installeren
Installeer de vereiste Azure SDK pakketten.
dotnet add package Microsoft.Identity.Web.Azure
dotnet add package Azure.Storage.Blobs
Registreer de Microsoft Entra tokenreferentie in uw opstartcode.
using Microsoft.Identity.Web;
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
// Add Azure token credential
builder.Services.AddMicrosoftIdentityAzureTokenCredential();
Toegang tot Azure-services
Injecteer de tokenreferentie en gebruik deze met Azure SDK clients.
using Azure.Storage.Blobs;
using Microsoft.Identity.Web;
public class StorageController : Controller
{
private readonly MicrosoftIdentityTokenCredential _credential;
public StorageController(MicrosoftIdentityTokenCredential credential)
{
_credential = credential;
}
[Authorize]
public async Task<IActionResult> ListBlobs()
{
var blobClient = new BlobServiceClient(
new Uri("https://myaccount.blob.core.windows.net"),
_credential);
var container = blobClient.GetBlobContainerClient("mycontainer");
var blobs = new List<string>();
await foreach (var blob in container.GetBlobsAsync())
{
blobs.Add(blob.Name);
}
return View(blobs);
}
}
Meer informatie over Azure SDK integratie
Aangepaste API's aanroepen met IDownstreamApi
Voor uw eigen REST API's IDownstreamApi biedt u een eenvoudige, configuratiegestuurde benadering.
De API configureren
Definieer de downstream-API-instellingen in appsettings.json.
{
"DownstreamApis": {
"MyAPI": {
"BaseUrl": "https://myapi.example.com",
"Scopes": ["api://my-api-id/access_as_user"],
"RequestAppToken": false
}
}
}
GET-aanvragen verzenden
Gegevens ophalen uit de downstream-API met optionele queryparameters.
// Simple GET
var data = await _downstreamApi.GetForUserAsync<MyData>(
"MyAPI",
options => options.RelativePath = "api/resource");
// GET with query parameters
var results = await _downstreamApi.GetForUserAsync<SearchResults>(
"MyAPI",
options =>
{
options.RelativePath = "api/search";
options.QueryParameters = new Dictionary<string, string>
{
["query"] = "test",
["limit"] = "10"
};
});
POST-aanvragen verzenden
Maak een nieuwe resource in de downstream-API door een aanvraagbody te plaatsen.
var newItem = new CreateItemRequest
{
Name = "New Item",
Description = "Item description"
};
var created = await _downstreamApi.PostForUserAsync<CreateItemRequest, CreatedItem>(
"MyAPI",
newItem,
options => options.RelativePath = "api/items");
PUT- en DELETE-aanvragen verzenden
Resources in de downstream-API bijwerken of verwijderen.
// PUT request
var updated = await _downstreamApi.PutForUserAsync<UpdateRequest, UpdatedItem>(
"MyAPI",
updateData,
options => options.RelativePath = "api/items/123");
// DELETE request
await _downstreamApi.DeleteForUserAsync(
"MyAPI",
null,
options => options.RelativePath = "api/items/123");
Meer informatie over aangepaste API-aanroepen
IAuthorizationHeaderProvider (geavanceerd) gebruiken
Gebruik IAuthorizationHeaderProvidervoor maximale controle over HTTP-aanvragen.
De HTTP-client registreren
Registreer een benoemde HTTP-client voor uw downstream-API.
builder.Services.AddHttpClient("MyAPI", client =>
{
client.BaseAddress = new Uri("https://myapi.example.com");
});
Aangepaste HTTP-aanvragen maken
HTTP-aanvragen bouwen en verzenden met aangepaste headers en autorisatie.
using Microsoft.Identity.Abstractions;
public class CustomApiService
{
private readonly IAuthorizationHeaderProvider _authProvider;
private readonly IHttpClientFactory _httpClientFactory;
public CustomApiService(
IAuthorizationHeaderProvider authProvider,
IHttpClientFactory httpClientFactory)
{
_authProvider = authProvider;
_httpClientFactory = httpClientFactory;
}
public async Task<MyData> GetDataAsync()
{
// Get authorization header
var authHeader = await _authProvider.CreateAuthorizationHeaderForUserAsync(
new[] { "api://my-api-id/access_as_user" });
// Create HTTP request with custom logic
var client = _httpClientFactory.CreateClient("MyAPI");
var request = new HttpRequestMessage(HttpMethod.Get, "api/resource");
request.Headers.Add("Authorization", authHeader);
request.Headers.Add("X-Custom-Header", "custom-value");
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<MyData>();
}
}
Meer informatie over aangepaste HTTP-logica
Incrementele toestemming en voorwaardelijke toegang verwerken
Wanneer u downstream-API's aanroept, moet uw toepassing mogelijk scenario's afhandelen waarin gebruikersinteractie is vereist. Dit gebeurt in drie hoofdscenario's:
- Incrementele toestemming : aanvullende machtigingen aanvragen buiten wat aanvankelijk is verleend
- Voorwaardelijke toegang : voldoen aan beveiligingsvereisten zoals MFA, apparaatcompatibiliteit of locatiebeleid
- Verwijdering van tokencache : de tokencache opnieuw vullen nadat de toepassing opnieuw is opgestart of de cache is verlopen
Microsoft. Identity.Web biedt automatische verwerking van deze scenario's met minimale code vereist.
Inzicht in de flow
Wanneer Microsoft. Identity.Web detecteert dat gebruikersinteractie nodig is en genereert een MicrosoftIdentityWebChallengeUserException. Het framework verwerkt dit automatisch via het [AuthorizeForScopes] kenmerk of de MicrosoftIdentityConsentAndConditionalAccessHandler service (voor Blazor), die:
- Hiermee wordt de gebruiker omgeleid naar Microsoft Entra ID voor toestemming/verificatie
- De oorspronkelijke aanvraag-URL behouden
- Retourneert de gebruiker naar de beoogde bestemming nadat het proces is voltooid
- Slaat de zojuist verkregen tokens in de cache op
Vereisten bekijken
Als u automatische verwerking van toestemming wilt inschakelen, moet u ervoor zorgen dat uw Program.cs configuratie de volgende configuratie bevat.
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("MyAPI", builder.Configuration.GetSection("MyAPI"))
.AddInMemoryTokenCaches();
// For MVC applications - enables the account controller
builder.Services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
// Ensure routes are mapped
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers(); // Required for AccountController
[AuthorizeForScopes] toepassen in MVC-controllers
Het [AuthorizeForScopes] kenmerk, ingesteld op controllers of controlleracties, behandelt automatisch MicrosoftIdentityWebChallengeUserException door de gebruiker uit te dagen wanneer er extra machtigingen nodig zijn.
Bereiken inline declareren
Geef de vereiste bereiken rechtstreeks in het kenmerk op.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web;
using Microsoft.Identity.Abstractions;
[Authorize]
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public class ProfileController : Controller
{
private readonly IDownstreamApi _downstreamApi;
public ProfileController(IDownstreamApi downstreamApi)
{
_downstreamApi = downstreamApi;
}
public async Task<IActionResult> Index()
{
// AuthorizeForScopes automatically handles consent challenges
var userData = await _downstreamApi.GetForUserAsync<UserData>(
"MyAPI",
options => options.RelativePath = "api/profile");
return View(userData);
}
// Different action requires additional scopes
[AuthorizeForScopes(Scopes = new[] { "user.read", "mail.read" })]
public async Task<IActionResult> Emails()
{
var emails = await _downstreamApi.GetForUserAsync<EmailList>(
"GraphAPI",
options => options.RelativePath = "me/messages");
return View(emails);
}
}
Scopes configureren vanuit appsettings
Bewaar bereiken in appsettings.json voor betere onderhoudbaarheid:
appsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "common",
"ClientId": "[Your-Client-ID]",
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret": "[Your-Client-Secret]"
}
]
},
"DownstreamApis": {
"TodoList": {
"BaseUrl": "https://localhost:5001",
"Scopes": [ "api://[API-Client-ID]/access_as_user" ]
},
"GraphAPI": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": [ "https://graph.microsoft.com/Mail.Read", "https://graph.microsoft.com/Mail.Send" ]
}
}
}
Controller:
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "DownstreamApis:TodoList:Scopes:0")]
public class TodoListController : Controller
{
private readonly IDownstreamApi _downstreamApi;
public TodoListController(IDownstreamApi downstreamApi)
{
_downstreamApi = downstreamApi;
}
public async Task<IActionResult> Index()
{
var todos = await _downstreamApi.GetForUserAsync<IEnumerable<TodoItem>>(
"TodoList",
options => options.RelativePath = "api/todolist");
return View(todos);
}
[AuthorizeForScopes(ScopeKeySection = "DownstreamApis:GraphAPI:Scopes:0")]
public async Task<IActionResult> EmailTodos()
{
// If user hasn't consented to Mail.Send, they'll be prompted
await _downstreamApi.PostForUserAsync<EmailMessage, object>(
"GraphAPI",
new EmailMessage { /* ... */ },
options => options.RelativePath = "me/sendMail");
return RedirectToAction("Index");
}
}
Microsoft Entra Externe id configureren met gebruikersstromen
Geef voor B2C-toepassingen (External ID) met meerdere gebruikersstromen de gebruikersstroom op in het kenmerk.
[Authorize]
public class AccountController : Controller
{
private const string SignUpSignInFlow = "b2c_1_susi";
private const string EditProfileFlow = "b2c_1_edit_profile";
private const string ResetPasswordFlow = "b2c_1_reset";
[AuthorizeForScopes(
ScopeKeySection = "DownstreamApis:TodoList:Scopes:0",
UserFlow = SignUpSignInFlow)]
public async Task<IActionResult> Index()
{
var data = await _downstreamApi.GetForUserAsync<UserData>(
"TodoList",
options => options.RelativePath = "api/data");
return View(data);
}
[AuthorizeForScopes(
Scopes = new[] { "openid", "offline_access" },
UserFlow = EditProfileFlow)]
public async Task<IActionResult> EditProfile()
{
// This triggers the B2C edit profile flow
return RedirectToAction("Index");
}
}
[AuthorizeForScopes] toepassen in Razor Pages
Toepassen [AuthorizeForScopes] op de paginamodelklasse:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Identity.Web;
using Microsoft.Identity.Abstractions;
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "DownstreamApis:MyAPI:Scopes:0")]
public class IndexModel : PageModel
{
private readonly IDownstreamApi _downstreamApi;
public UserData UserData { get; set; }
public IndexModel(IDownstreamApi downstreamApi)
{
_downstreamApi = downstreamApi;
}
public async Task OnGetAsync()
{
// Automatically handles consent challenges
UserData = await _downstreamApi.GetForUserAsync<UserData>(
"MyAPI",
options => options.RelativePath = "api/profile");
}
}
Toestemming verwerken in Blazor Server
Blazor Server-toepassingen vereisen expliciete verwerking van uitzonderingen met behulp van de MicrosoftIdentityConsentAndConditionalAccessHandler service.
Program.cs configureren
Registreer de toestemmingshandler voor Blazor Server in uw opstartcode.
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApis("TodoList", builder.Configuration.GetSection("DownstreamApis"))
.AddInMemoryTokenCaches();
// Register the consent handler for Blazor
builder.Services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
Het Blazor-onderdeel maken
Verpakt API-aanroepen in try-catch-blokken en gebruik ConsentHandler.HandleException() om toestemmingsproblemen af te handelen.
@page "/todolist"
@using Microsoft.Identity.Web
@using Microsoft.Identity.Abstractions
@using MyApp.Models
@inject MicrosoftIdentityConsentAndConditionalAccessHandler ConsentHandler
@inject IDownstreamApi DownstreamApi
<h3>My Todo List</h3>
@if (todos == null)
{
<p><em>Loading...</em></p>
}
else
{
<ul>
@foreach (var todo in todos)
{
<li>@todo.Title</li>
}
</ul>
}
@code {
private IEnumerable<TodoItem> todos;
protected override async Task OnInitializedAsync()
{
await LoadTodosAsync();
}
[AuthorizeForScopes(ScopeKeySection = "DownstreamApis:TodoList:Scopes:0")]
private async Task LoadTodosAsync()
{
try
{
todos = await DownstreamApi.GetForUserAsync<IEnumerable<TodoItem>>(
"TodoList",
options => options.RelativePath = "api/todolist");
}
catch (Exception ex)
{
// Handles MicrosoftIdentityWebChallengeUserException
// and initiates user consent/authentication flow
ConsentHandler.HandleException(ex);
}
}
private async Task AddTodoAsync(string title)
{
try
{
await DownstreamApi.PostForUserAsync<TodoItem, TodoItem>(
"TodoList",
new TodoItem { Title = title },
options => options.RelativePath = "api/todolist");
await LoadTodosAsync();
}
catch (Exception ex)
{
ConsentHandler.HandleException(ex);
}
}
}
Uitzonderingen handmatig verwerken (geavanceerd)
Als u aangepaste logica voor toestemmingsstromen nodig hebt, moet u het volgende expliciet afhandelen MicrosoftIdentityWebChallengeUserException :
[Authorize]
public class AdvancedController : Controller
{
private readonly IDownstreamApi _downstreamApi;
private readonly ILogger<AdvancedController> _logger;
public AdvancedController(
IDownstreamApi downstreamApi,
ILogger<AdvancedController> logger)
{
_downstreamApi = downstreamApi;
_logger = logger;
}
public async Task<IActionResult> SendEmail()
{
try
{
await _downstreamApi.PostForUserAsync<EmailMessage, object>(
"GraphAPI",
new EmailMessage
{
Subject = "Test",
Body = "Test message"
},
options => options.RelativePath = "me/sendMail");
return RedirectToAction("Success");
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
// Log the consent requirement
_logger.LogWarning(
"Consent required for scopes: {Scopes}. Challenging user.",
string.Join(", ", ex.Scopes));
// Custom properties for redirect
var properties = new AuthenticationProperties
{
RedirectUri = Url.Action("SendEmail", "Advanced"),
};
// Add custom state if needed
properties.Items["consent_attempt"] = "1";
return Challenge(properties, OpenIdConnectDefaults.AuthenticationScheme);
}
catch (HttpRequestException ex)
{
_logger.LogError(ex, "Failed to send email");
return View("Error");
}
}
}
Scenario's voor voorwaardelijke toegang verwerken
Beleidsregels voor voorwaardelijke toegang kunnen aanvullende verificatiefactoren vereisen. De verwerking is identiek aan incrementele toestemming:
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "DownstreamApis:SecureAPI:Scopes:0")]
public class SecureDataController : Controller
{
private readonly IDownstreamApi _downstreamApi;
public SecureDataController(IDownstreamApi downstreamApi)
{
_downstreamApi = downstreamApi;
}
public async Task<IActionResult> Index()
{
// If conditional access requires MFA, AuthorizeForScopes
// automatically challenges the user
var sensitiveData = await _downstreamApi.GetForUserAsync<SensitiveData>(
"SecureAPI",
options => options.RelativePath = "api/sensitive");
return View(sensitiveData);
}
}
Veelvoorkomende triggers voor voorwaardelijke toegang:
- Multifactorverificatie (MFA)
- Compatibele apparaatvereiste
- Vertrouwde netwerklocatie
- Acceptatie van gebruiksvoorwaarden
- Wachtwoordwijzigingsvereiste
Best practices volgen
Pas deze aanbevelingen toe bij het implementeren van toestemming en voorwaardelijke toegang.
Gebruiken [AuthorizeForScopes] - Eenvoudigste aanpak voor MVC-controllers en Razor Pages
Scopes opslaan in configuratie - Gebruik ScopeKeySection = "DownstreamApis:ApiName:Scopes:0" om naar de scopes in appsettings.json te verwijzen
Toepassen op controllerniveau - Standaardbereiken instellen op de controller, overschrijven op specifieke acties
Uitzonderingen verwerken in Blazor - Pak API-aanroepen altijd in met try-catch en gebruik ConsentHandler.HandleException()
Uitzonderingen opnieuw gooien - Als u MicrosoftIdentityWebChallengeUserException opvangt, gooi het opnieuw zodat [AuthorizeForScopes] het kan verwerken
Voorwaardelijke toegang testen - Controleer of uw app MFA en ander CA-beleid correct verwerkt
Uitzonderingen niet onderdrukken - Het vangen zonder opnieuw gooien onderbreekt de toestemmingsstroom
Sla reacties niet voor onbepaalde tijd in de cache op : tokens verlopen; ontwerp voor opnieuw verificatie
Statische machtigingen en incrementele toestemming vergelijken
Statische machtigingen (beheerderstoestemming)
Alle machtigingen worden aangevraagd tijdens de app-registratie en toestemming van een tenantbeheerder:
Voordelen:
- Gebruikers zien nooit toestemmingsprompts
- Vereist voor Microsoft apps van derden
- Eenvoudigere gebruikerservaring
nadelen:
- Vereist betrokkenheid van tenantbeheerders
- Overgeprivilegieerd vanaf het begin
- Minder flexibel voor scenario's met meerdere tenants
Configuration:
// Request all pre-approved scopes for Microsoft Graph
var scopes = new[] { "https://graph.microsoft.com/.default" };
var userData = await _downstreamApi.GetForUserAsync<UserData>(
"GraphAPI",
options =>
{
options.RelativePath = "me";
options.Scopes = scopes; // Use .default scope
});
Incrementele toestemming (dynamisch)
Tijdens runtime worden machtigingen aangevraagd:
Voordelen:
- Betere beveiliging (principe van minimale bevoegdheden)
- Gebruikers geven toestemming voor wat ze daadwerkelijk gebruiken
- Werkt voor apps met meerdere tenants
nadelen:
- Gebruikers kunnen worden onderbroken met toestemmingsprompts
- Verwerking vereist
MicrosoftIdentityWebChallengeUserException
Aanbeveling: Incrementele toestemming gebruiken voor toepassingen met meerdere tenants; statische machtigingen gebruiken voor zakelijke apps van derden waarbij beheerderstoestemming wordt gegarandeerd
Tokencaching configureren
Microsoft. Identity.Web slaat tokens in de cache op om de prestaties te verbeteren en aanroepen tot Microsoft Entra te verminderen.
Cache in het geheugen gebruiken (standaard)
Voeg een in-memory tokencache toe voor ontwikkelings- of scenario's met één server.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches(); // In-memory cache
Gebruiken voor:
- Ontwikkeling
- Implementaties met één server
- Kleine gebruikersbasis
Limitations:
- Niet gedeeld tussen instanties
- Verloren bij opnieuw opstarten van de app
- Geheugenverbruik groeit met gebruikers
Gedistribueerde cache gebruiken (aanbevolen voor productie)
Configureer een gedistribueerde cache, zoals Redis of SQL Server voor productie-implementaties.
// Install: Microsoft.Identity.Web.TokenCache
// Redis
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration["Redis:ConnectionString"];
options.InstanceName = "MyApp_";
});
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
// SQL Server
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration["SqlCache:ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TokenCache";
});
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
Gebruiken voor:
- Implementaties met meerdere servers (taakverdeling)
- Scenario's voor hoge beschikbaarheid
- Grote gebruikersbasis
- Permanente cache bij herstarten
Fouten bij het verkrijgen van tokens afhandelen
Veelvoorkomende uitzonderingen afhandelen
De volgende code laat zien hoe u de meest voorkomende uitzonderingen voor het verkrijgen van tokens kunt ondervangen en afhandelen.
try
{
var data = await _downstreamApi.GetForUserAsync<MyData>(
"MyAPI",
options => options.RelativePath = "api/resource");
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
// User needs to consent or reauthenticate
_logger.LogWarning($"User consent required: {ex.Message}");
return Challenge(new AuthenticationProperties { RedirectUri = Request.Path });
}
catch (MsalUiRequiredException ex)
{
// User interaction required (sign-in again, MFA, etc.)
_logger.LogWarning($"User interaction required: {ex.Message}");
return Challenge(OpenIdConnectDefaults.AuthenticationScheme);
}
catch (MsalServiceException ex)
{
// Service error (Microsoft Entra ID unavailable, etc.)
_logger.LogError(ex, "Microsoft Entra ID service error");
return StatusCode(503, "Authentication service temporarily unavailable");
}
catch (HttpRequestException ex)
{
// Downstream API unreachable
_logger.LogError(ex, "Downstream API call failed");
return StatusCode(503, "Downstream service unavailable");
}
Gecontroleerde degradatie implementeren
Laad optionele gegevens van downstream-API's en ga terug naar de standaardinstellingen wanneer aanroepen mislukken.
public async Task<IActionResult> Dashboard()
{
var model = new DashboardModel();
// Try to load optional data from downstream API
try
{
model.EnrichedData = await _downstreamApi.GetForUserAsync<EnrichedData>(
"MyAPI",
options => options.RelativePath = "api/enriched");
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to load enriched data, using defaults");
model.EnrichedData = new EnrichedData { /* defaults */ };
}
return View(model);
}
OWIN (.NET Framework) implementeren
Volg deze stappen voor webtoepassingen op basis van OWIN in .NET Framework.
1. Pakketten installeren
Installeer de vereiste NuGet-pakketten.
Install-Package Microsoft.Identity.Web.OWIN
Install-Package Microsoft.Owin.Host.SystemWeb
2. Opstartproces configureren
Configureer Microsoft Entra authenticatie en tokenverwerving in de OWIN-startklasse.
using Microsoft.Identity.Web;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Owin;
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.AddMicrosoftIdentityWebApp(
Configuration,
configSectionName: "AzureAd",
openIdConnectScheme: "OpenIdConnect",
cookieScheme: CookieAuthenticationDefaults.AuthenticationType,
subscribeToOpenIdConnectMiddlewareDiagnosticsEvents: true);
app.EnableTokenAcquisitionToCallDownstreamApi();
app.AddDistributedTokenCaches();
}
}
3. Downstream-API aanroepen
Een token verkrijgen en de downstream-API aanroepen vanaf een MVC-controller.
using Microsoft.Identity.Web;
using System.Threading.Tasks;
using System.Web.Mvc;
[Authorize]
public class ProfileController : Controller
{
public async Task<ActionResult> Index()
{
var downstreamApi = TokenAcquirerFactory.GetDefaultInstance()
.GetTokenAcquirer()
.GetDownstreamApi();
var userData = await downstreamApi.GetForUserAsync<UserData>(
"MyAPI",
options => options.RelativePath = "api/profile");
return View(userData);
}
}
Note: OWIN-ondersteuning verschilt van ASP.NET Core. Zie de OWIN-documentatie voor meer informatie.
Best practices voor beveiliging volgen
Bereiken beheren
Pas het principe van minimale bevoegdheden toe bij het aanvragen van API-machtigingen.
Do:
- Alleen de scopes vragen die u nodig hebt
- Incrementele toestemming gebruiken voor geavanceerde functies
- Vereiste bereiken documenteer in uw app
Don't:
- Onnodige bereiken vooraf aanvragen
- Admin-only scopes aanvragen zonder rechtvaardiging
- Stel dat alle toegangsniveaus zullen worden toegekend
Tokens veilig verwerken
Volg deze richtlijnen om toegangstokens in uw toepassing te beveiligen.
Do:
- Laat Microsoft.Identity.Web de tokens beheren
- Gedistribueerde cache gebruiken in productie
- Fouten bij het verkrijgen van tokens soepel afhandelen
Don't:
- Tokens zelf opslaan
- Toegangstokens voor logboeken
- Tokens verzenden naar client-side code
Afhandeling van fouten
Implementeer robuuste foutafhandeling voor verificatie- en API-aanroepfouten.
Do:
- Uitzonderingen voor toestemming ondervangen en afhandelen
- Duidelijke foutberichten voor gebruikers opgeven
- Fouten loggen voor foutopsporing
Don't:
- Tokenfouten beschikbaar maken voor gebruikers
- Api-aanroepen op de achtergrond mislukken
- Verificatie-uitzonderingen negeren
Veelvoorkomende problemen oplossen
Bekijk deze oplossingen voor veelvoorkomende verificatiefouten.
Probleem: 'AADSTS65001: De gebruiker of beheerder heeft geen toestemming gegeven'
Oorzaak: De gebruiker heeft geen toestemming gegeven voor vereiste machtigingen.
Solution:
catch (MicrosoftIdentityWebChallengeUserException ex)
{
// Redirect to consent page
return Challenge(
new AuthenticationProperties { RedirectUri = Request.Path },
OpenIdConnectDefaults.AuthenticationScheme);
}
Probleem: 'AADSTS50076: Multi-Factor Authentication vereist'
Oorzaak: De gebruiker moet MFA voltooien.
Solution:
catch (MsalUiRequiredException)
{
// Redirect user to sign in with MFA
return Challenge(OpenIdConnectDefaults.AuthenticationScheme);
}
Probleem: Tokens blijven niet behouden tijdens het opnieuw opstarten van de app
Oorzaak: In-memory cache gebruiken.
Solution: Overschakelen naar gedistribueerde cache (Redis, SQL Server of Cosmos DB).
Probleem: 401 Niet geautoriseerd vanuit downstream-API
Mogelijke oorzaken:
- Verkeerde bereiken aangevraagd
- API-machtiging niet verleend in app-registratie
- Token is verlopen
Solution:
- Toepassingsbereiken in appsettings.json controleren op overeenstemming met API-vereisten
- Controleren of app-registratie API-machtigingen heeft
- Zorg ervoor dat tokens in de cache worden opgeslagen en vernieuwd.
Voor gedetailleerde diagnostische gegevens: Zie de handleiding logboekregistratie en diagnostische gegevens voor correlatie-id's, foutopsporing in tokencache en uitgebreide patronen voor probleemoplossing.
Prestaties optimaliseren
Strategie voor tokencaching plannen
Selecteer een cachestrategie die overeenkomt met uw implementatietopologie.
- Gedistribueerde cache gebruiken voor implementaties met meerdere servers
- De juiste verlooptijd van de cache configureren
- Cacheprestaties bewaken
Tokenaanvragen minimaliseren
Microsoft. Identity.Web slaat tokens automatisch in de cache op. Beide aanroepen in het volgende voorbeeld gebruiken hetzelfde token in de cache.
// Bad: Multiple token acquisitions
var profile = await _downstreamApi.GetForUserAsync<Profile>(
"API",
options => options.RelativePath = "profile");
var settings = await _downstreamApi.GetForUserAsync<Settings>(
"API",
options => options.RelativePath = "settings");
// Good: Single token, multiple calls (token is cached)
// Both calls use the same cached token
var profile = await _downstreamApi.GetForUserAsync<Profile>(
"API",
options => options.RelativePath = "profile");
var settings = await _downstreamApi.GetForUserAsync<Settings>(
"API",
options => options.RelativePath = "settings");
Parallelle API-aanroepen uitvoeren
Roep meerdere downstream-API's gelijktijdig aan om de totale latentie te verminderen.
// Call multiple APIs in parallel
var profileTask = _downstreamApi.GetForUserAsync<Profile>(
"API1",
options => options.RelativePath = "profile");
var settingsTask = _downstreamApi.GetForUserAsync<Settings>(
"API2",
options => options.RelativePath = "settings");
await Task.WhenAll(profileTask, settingsTask);
var profile = profileTask.Result;
var settings = settingsTask.Result;
Verwante inhoud verkennen
Aanvullende richtlijnen voor gerelateerde scenario's zoeken.