Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här guiden beskriver hur du anropar underordnade API:er från ASP.NET Core- och OWIN-webbprogram med hjälp av Microsoft. Identity.Web. I webbappar hämtar du token för den inloggade användarens räkning för att anropa API:er med delegerade behörigheter.
Förstå tokenflödet
När en användare loggar in på din webbapp kan du anropa underordnade API:er (Microsoft Graph, Azure tjänster eller anpassade API:er) för deras räkning. Microsoft. Identity.Web hanterar tokenförvärv, cachelagring och automatisk uppdatering.
Granska användartokenflödet
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
Förutsättningar för granskning
Kontrollera att din miljö uppfyller följande krav innan du börjar.
- Webbapp som konfigurerats med OpenID Connect-autentisering
- Användarinloggning fungerar
- Appregistrering med konfigurerade API-behörigheter
- Användarmedgivande erhållet (eller administratörsmedgivande beviljat)
Implementera ASP.NET Core
1. Konfigurera autentisering och tokenförvärv
Lägg till autentiseringstjänster och aktivera tokenförvärv i filen Program.cs .
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. Konfigurera appsettings.json
Definiera din Microsoft Entra ID appregistrering och underordnade API-inställningar i 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"]
}
}
}
Viktigt: För webbappar som anropar underordnade API:er behöver du klientautentiseringsuppgifter (certifikat eller hemlighet) utöver inloggningskonfigurationen.
3. Lägg till underordnat API-stöd
Välj något av följande alternativ för att registrera dina underordnade API:er.
Alternativ A: Registrera namngivna API:er
Följande kod registrerar flera underordnade API:er från konfigurationen.
using Microsoft.Identity.Web;
// Register multiple downstream APIs
builder.Services.AddDownstreamApis(
builder.Configuration.GetSection("DownstreamApis"));
Option B: Använd Microsoft Graph Helper
Följande kod registrerar Microsoft Graph SDK-klienten från konfigurationen.
// Install: Microsoft.Identity.Web.GraphServiceClient
builder.Services.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApis:GraphAPI"));
4. Anropa nedströms-API:et från kontrollanten
Mata IDownstreamApi in i kontrollanten och anropa API:et för den inloggade användarens räkning.
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. Anropa underordnat API från Razor-sidan
Mata IDownstreamApi in i razor-sidmodellen och anropa API:et.
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;
}
}
}
Anropa Microsoft Graph
För Microsoft Graph API-anrop använder du den dedikerade GraphServiceClient.
Installera paket
Installera Microsoft Graph-paketet för Microsoft. Identity.Web.
dotnet add package Microsoft.Identity.Web.GraphServiceClient
Konfigurera Graph-klienten i startkoden.
// Startup configuration
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(options =>
{
options.Scopes = "user.read mail.read";
})
.AddInMemoryTokenCaches();
Anropa Graph API
Mata in GraphServiceClient i kontrollanten för att anropa Microsoft Graph slutpunkter.
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 });
}
}
Läs mer om Microsoft Graph integrering
Anropa Azure SDKs klientbibliotek
För att anropa Azure tjänster använder du MicrosoftIdentityTokenCredential.
Installera paket
Installera de nödvändiga Azure SDKs paketen.
dotnet add package Microsoft.Identity.Web.Azure
dotnet add package Azure.Storage.Blobs
Registrera Microsoft Entra tokenautentiseringsuppgifter i startkoden.
using Microsoft.Identity.Web;
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
// Add Azure token credential
builder.Services.AddMicrosoftIdentityAzureTokenCredential();
Åtkomst Azure tjänster
Mata in tokenautentiseringsuppgifterna och använd den med Azure SDKs klienter.
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);
}
}
Läs mer om Azure SDKs integrering
Anropa anpassade API:er med IDownstreamApi
För dina egna REST-API:er IDownstreamApi tillhandahåller en enkel, konfigurationsdriven metod.
Konfigurera API:et
Definiera de underordnade API-inställningarna i appsettings.json.
{
"DownstreamApis": {
"MyAPI": {
"BaseUrl": "https://myapi.example.com",
"Scopes": ["api://my-api-id/access_as_user"],
"RequestAppToken": false
}
}
}
Skicka GET-begäranden
Hämta data från det underordnade API:et med valfria frågeparametrar.
// 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"
};
});
Skicka POST-begäranden
Skapa en ny resurs i det underordnade API:et genom att publicera en begärandetext.
var newItem = new CreateItemRequest
{
Name = "New Item",
Description = "Item description"
};
var created = await _downstreamApi.PostForUserAsync<CreateItemRequest, CreatedItem>(
"MyAPI",
newItem,
options => options.RelativePath = "api/items");
Skicka PUT- och DELETE-begäranden
Uppdatera eller ta bort resurser i det underordnade API:et.
// 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");
Läs mer om anpassade API-anrop
Använda IAuthorizationHeaderProvider (avancerat)
För maximal kontroll över HTTP-begäranden använder du IAuthorizationHeaderProvider.
Registrera HTTP-klienten
Registrera en namngiven HTTP-klient för ditt underordnade API.
builder.Services.AddHttpClient("MyAPI", client =>
{
client.BaseAddress = new Uri("https://myapi.example.com");
});
Skapa anpassade HTTP-begäranden
Skapa och skicka HTTP-begäranden med anpassade huvuden och auktorisering.
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>();
}
}
Läs mer om anpassad HTTP-logik
Hantera inkrementellt medgivande och villkorlig åtkomst
När du anropar underordnade API:er kan ditt program behöva hantera scenarier där användarinteraktion krävs. Detta sker i tre huvudscenarier:
- Inkrementellt medgivande – Begära ytterligare behörigheter utöver vad som ursprungligen beviljades
- Villkorlig åtkomst – Uppfylla säkerhetskrav som MFA, enhetsefterlevnad eller platsprinciper
- Utrensning av tokencache – Återskapa tokencacheminnet efter programomstart eller cacheminnets utgång
Microsoft. Identity.Web tillhandahåller automatisk hantering av dessa scenarier med minimal kod som krävs.
Förstå flödet
När Microsoft. Identity.Web identifierar att användarinteraktion behövs, den genererar en MicrosoftIdentityWebChallengeUserException. Ramverket hanterar detta automatiskt via [AuthorizeForScopes] attributet eller MicrosoftIdentityConsentAndConditionalAccessHandler tjänsten (för Blazor), som:
- Omdirigerar användaren till Microsoft Entra ID för medgivande/autentisering
- Bevarar den ursprungliga begärande-URL:en
- Returnerar användaren till sitt avsedda mål när flödet har slutförts
- Cachelagrar de nyligen förvärvade tokens
Förutsättningar för granskning
Om du vill aktivera automatisk medgivandehantering kontrollerar du att du Program.cs har följande konfiguration.
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
Använd [AuthorizeForScopes] i MVC-styrenheter
Attributet [AuthorizeForScopes] , som anges för kontrollanter eller kontrollantåtgärder, hanterar MicrosoftIdentityWebChallengeUserException automatiskt genom att utmana användaren när ytterligare behörigheter behövs.
Deklarera omfång inline
Ange de nödvändiga omfången direkt i attributet.
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);
}
}
Konfigurera omfång från apparinställningar
Lagra omfång i appsettings.json för bättre underhållbarhet:
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");
}
}
Konfigurera Microsoft Entra External ID med användarflöden
För externa ID-program (B2C) med flera användarflöden anger du användarflödet i attributet.
[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");
}
}
Använd [AuthorizeForScopes] på Razor Pages
Använd [AuthorizeForScopes] för sidmodellklassen:
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");
}
}
Hantera medgivande i Blazor Server
Blazor Server-program kräver explicit undantagshantering med hjälp av MicrosoftIdentityConsentAndConditionalAccessHandler tjänsten.
Konfigurera Program.cs
Registrera medgivandehanteraren för Blazor Server i startkoden.
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApis("TodoList", builder.Configuration.GetSection("DownstreamApis"))
.AddInMemoryTokenCaches();
// Register the consent handler for Blazor
builder.Services.AddServerSideBlazor()
.AddMicrosoftIdentityConsentHandler();
Skapa Blazor-komponenten
Omslut API-anrop med try-catch-block och använd ConsentHandler.HandleException() för att hantera samtyckesutmaningar.
@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);
}
}
}
Hantera undantag manuellt (avancerat)
Om du behöver logik för ett anpassat medgivandeflöde, hantera MicrosoftIdentityWebChallengeUserException explicit.
[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");
}
}
}
Hantera scenarier för villkorlig åtkomst
Principer för villkorlig åtkomst kan kräva ytterligare autentiseringsfaktorer. Hanteringen är identisk med inkrementellt medgivande:
[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);
}
}
Vanliga utlösare för villkorlig åtkomst:
- Multifaktorautentisering (MFA)
- Krav på kompatibel enhet
- Betrodd nätverksplats
- Godkännande av användningsvillkor
- Krav på lösenordsändring
Följ metodtipsen
Tillämpa dessa rekommendationer när du implementerar medgivande och hantering av villkorsstyrd åtkomst.
Använda [AuthorizeForScopes] – Enklaste metoden för MVC-styrenheter och Razor Pages
Lagra omfång i konfiguration – Använd ScopeKeySection = "DownstreamApis:ApiName:Scopes:0" för att referera till omfång i appsettings.json
Tillämpa på kontrollantnivå – Ange standardomfattningar på kontrollanten, åsidosätt specifika åtgärder
Hantera undantag i Blazor – Alltid omsluta API-anrop med try-catch och använd ConsentHandler.HandleException()
Återkasta undantag – Om du fångar MicrosoftIdentityWebChallengeUserException, återkasta det så att [AuthorizeForScopes] kan bearbeta det
Testa villkorlig åtkomst – Kontrollera att din app hanterar MFA och andra CA-principer korrekt
Utelämna inte undantag – Att fånga utan att kasta igen bryter medgivandeflödet
Cachelagrar inte svar på obestämd tid – token upphör att gälla; utforma för omautentisering
Jämför statiska behörigheter och inkrementellt medgivande
Statiska behörigheter (administratörsmedgivande)
Alla behörigheter begärs under appregistreringen och godkänns av en klientadministratör:
Fördelar:
- Användare ser aldrig medgivandeprompter
- Krävs för Microsoft appar från första part
- Enklare användarupplevelse
Nackdelar:
- Kräver innehavaradministratörsengagemang
- Överprivilegierad från början
- Mindre flexibelt för scenarier med flera klientorganisationer
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
});
Inkrementellt medgivande (dynamiskt)
Behörigheter begärs efter behov under körning:
Fördelar:
- Bättre säkerhet (principen om minsta behörighet)
- Användare samtycker till vad de faktiskt använder
- Fungerar för appar med flera klientorganisationer
Nackdelar:
- Användare kan bli avbrutna av samtyckesmeddelanden
- Kräver hantering
MicrosoftIdentityWebChallengeUserException
Rekommendation: Använd inkrementellt medgivande för program med flera klientorganisationer. använda statiska behörigheter för företagsappar från första part där administratörsmedgivande garanteras
Konfigurera cachelagring av token
Microsoft.Identity.Web cachar token för att förbättra prestanda och minska anrop till Microsoft Entra.
Använd minnesintern cache (standard)
Lägg till en minnesintern tokencache för utvecklings- eller enserverscenarier.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches(); // In-memory cache
Används för:
- Utveckling
- Installationer med en server
- Liten användarbas
Limitations:
- Delas inte mellan instanser
- Förlorade vid omstart av app
- Minnesförbrukningen ökar med användare
Använda distribuerad cache (rekommenderas för produktion)
Konfigurera en distribuerad cache som Redis eller SQL Server för produktionsdistributioner.
// 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();
Används för:
- Distributioner med flera servrar (lastbalanserade)
- Scenarier för hög tillgänglighet
- Stor användarbas
- Beständig cache vid omstarter
Hantera fel vid tokeninhämtning
Fånga vanliga undantag
Följande kod visar hur du fångar och hanterar de vanligaste undantagen för tokenförvärv.
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");
}
Implementera mjuk nedtrappning
Läs in valfria data från underordnade API:er och återgå till standardvärden när anrop misslyckas.
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);
}
Implementera OWIN för .NET Framework
Följ dessa steg för OWIN-baserade webbprogram i .NET Framework.
1. Installera paket
Installera nödvändiga NuGet-paket.
Install-Package Microsoft.Identity.Web.OWIN
Install-Package Microsoft.Owin.Host.SystemWeb
2. Konfigurera start
Konfigurera Microsoft Entra autentisering och tokenförvärv i OWIN-startklassen.
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. Anropa underordnat API
Hämta en token och anropa det underordnade API:et från en MVC-styrenhet.
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-stöd har vissa skillnader jämfört med ASP.NET Core. Mer information finns i OWIN-dokumentationen .
Följ metodtips för säkerhet
Hantera omfång
Tillämpa principen om lägsta behörighet när du begär API-behörigheter.
Do:
- Begär endast de behörigheter du behöver
- Använda inkrementellt medgivande för avancerade funktioner
- Dokumentera nödvändiga omfång i din app
Don't:
- Begära onödiga behörigheter inledningsvis
- Begär endast administratörsomfång utan motivering
- Anta att alla omfång kommer att beviljas
Hantera token på ett säkert sätt
Följ dessa riktlinjer för att skydda åtkomsttoken i ditt program.
Do:
- Låt Microsoft.Identity.Web hantera token
- Använda distribuerad cache i produktion
- Hantera misslyckanden vid tokenförvärv smidigt.
Don't:
- Lagra tokenerna själv
- Loggåtkomsttoken
- Skicka token till programkod på klientsidan
Hantering av fel
Implementera robust felhantering för autentiserings- och API-anropsfel.
Do:
- Fånga och hantera samtyckesundantag
- Ge tydliga felmeddelanden till användare
- Loggfel för felsökning
Don't:
- Exponera tokenfel för användare
- API-anrop som misslyckas tyst
- Ignorera autentiseringsfel
Felsökning av vanliga problem
Granska de här lösningarna för autentiseringsfel som ofta påträffas.
Problem: "AADSTS65001: Användaren eller administratören har inte samtyckt"
Orsaka: Användaren har inte samtyckt till nödvändiga omfång.
Lösning:
catch (MicrosoftIdentityWebChallengeUserException ex)
{
// Redirect to consent page
return Challenge(
new AuthenticationProperties { RedirectUri = Request.Path },
OpenIdConnectDefaults.AuthenticationScheme);
}
Problem: "AADSTS50076: Multifaktorautentisering krävs"
Orsaka: Användaren måste slutföra MFA.
Lösning:
catch (MsalUiRequiredException)
{
// Redirect user to sign in with MFA
return Challenge(OpenIdConnectDefaults.AuthenticationScheme);
}
Problem: Token sparas inte mellan appomstarter
Orsaka: Använda minnesintern cache.
Solution: Växla till distribuerad cache (Redis, SQL Server eller Cosmos DB).
Problem: 401 Obehörig från underordnat API
Möjliga orsaker:
- Fel omfång begärda
- API-behörighet beviljas inte i appregistrering
- Token har upphört att gälla
Lösning:
- Verifiera att omfång i appsettings.json matchar API-krav
- Kontrollera att appregistreringen har API-behörigheter
- Kontrollera att token är cachelagrade och uppdaterade
För detaljerad diagnostik: Se Loggnings- och diagnostikguiden för korrelations-ID:n, felsökning av tokencache och omfattande felsökningsmönster.
Optimera prestanda
Planera cachelagringsstrategi för token
Välj en cachelagringsstrategi som matchar din distributionstopologi.
- Använda distribuerad cache för distributioner med flera servrar
- Konfigurera lämplig cache förfallodatum
- Övervaka cacheprestanda
Minimera tokenbegäranden
Microsoft. Identity.Web cachelagrar token automatiskt. Båda anropen i följande exempel återanvänder samma cachelagrade token.
// 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");
Gör parallella API-anrop
Anropa flera underordnade API:er samtidigt för att minska den totala svarstiden.
// 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;
Utforska relaterat innehåll
Hitta ytterligare vägledning för relaterade scenarier.