You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core API后端基于Azure AD的认证原理与疑问

Azure AD Authentication with React (ADAL) and .NET Core Web API: Questions on Validation Mechanism, Keys, and Flow Type

Background

I'm building a frontend with React (using ADAL-React + Axios) and a backend with .NET Core 2 Web API, both deployed on Azure, using Azure AD authentication. The frontend is configured with TenantID and ClientID and works correctly, but I have questions about the authentication principles.

Current Flow

  1. When a user accesses the frontend, ADAL checks for authentication; if unauthenticated, redirects to Azure login page. Frontend ADAL config:
const adalConfig = {
  tenant: 'vhsprod.onmicrosoft.com',
  clientId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx',
  endpoints: {
    api: 'https://xxxxx.onmicrosoft.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx (client id)',
  },
  postLogoutRedirectUri: window.location.origin,
  redirectUri: 'http://localhost:3000/user-form',
  cacheLocation: 'sessionStorage'
};

export const authContext = new AuthenticationContext(adalConfig);

export const getToken = () => {
  return authContext.getCachedToken(authContext.config.clientId);
};
  1. After user logs in successfully, they're redirected back to frontend, and the token is obtained.
  2. When frontend sends API requests, the token (from sessionStorage.getItem('adal.idtoken')) is added to the Authorization header via Axios:
let initialToken = sessionStorage.getItem('adal.idtoken')

export const axiosCallToMyAPI = axios.create({
  baseURL: 'http://localhost:52860/api/',
  timeout: 5000,
  headers: {'Authorization': 'Bearer ' + initialToken}
});
  1. Backend appsettings.json Azure AD config:
"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "TenantDomain": "xxxx.onmicrosoft.com",
  "TenantId": "xxxx.onmicrosoft.com",
  "ClientId": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx"
}
  1. Backend Startup.cs uses AddJwtBearer to validate tokens:
services
  .AddAuthentication(sharedOptions => {
    sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
  })
  .AddJwtBearer(options => {
    options.Audience = this.Configuration["AzureAd:ClientId"];
    options.Authority = $"{this.Configuration["AzureAd:Instance"]}{this.Configuration["AzureAd:TenantId"]}";
    options.Events = new JwtBearerEvents() {
      OnTokenValidated = context => {
        return Task.CompletedTask;
      }
    };
  });

Questions

  1. How does the API validate the Azure token's validity? What's the mechanism behind OnTokenValidated? Does it only check Tenant/Client ID?
  2. Some references mention SecretKey/Signing Key, but my setup works without configuring them. Do I need to add these?
  3. Is the current Azure AD authentication method using the Implicit flow?

Answers

1. Token Validation Mechanism & OnTokenValidated

Let's break this down step by step. When your .NET Core API receives a Bearer token via the Authorization header, the AddJwtBearer middleware does far more than just checking Tenant/Client ID:

  • First, it fetches the public signing keys from Azure AD's OpenID Connect metadata endpoint (based on your Authority configuration). These keys verify the token's digital signature—ensuring the token wasn't tampered with and was indeed issued by Azure AD.
  • Next, it validates standard JWT claims:
    • iss (Issuer): Must match your Azure AD tenant's issuer URL (the Authority value).
    • aud (Audience): Must match the options.Audience (your API's Client ID)—this confirms the token was specifically issued for your API.
    • exp (Expiration Time): Checks that the token hasn't expired.
    • nbf (Not Before): Ensures the token isn't used before its valid start time.
    • It also verifies the token uses the expected algorithm (Azure AD uses RS256, an asymmetric algorithm).

As for OnTokenValidated: this is an event hook that runs after all core validation is complete. It's a spot to add custom logic (like checking user roles or custom claims) if you need to. Your empty implementation just lets the already-validated token proceed through the pipeline.

2. SecretKey/Signing Key: Do You Need Them?

Nope, you don't need to configure these—and that's by design. Azure AD uses asymmetric encryption (RS256) for signing tokens:

  • Azure AD signs tokens with its private key. Your API only needs the corresponding public key to verify the signature. The AddJwtBearer middleware automatically fetches these public keys from Azure AD's metadata endpoint, so you don't have to manually set them up.
  • SecretKeys are for symmetric algorithms (like HS256), where both issuer and consumer share the same secret. Azure AD doesn't use this for standard API scenarios because asymmetric encryption is more secure (no secret needs to be shared across services).

Your setup works correctly because the middleware handles public key retrieval automatically—no secret keys required here.

3. Is This the Implicit Flow?

Yes, exactly. Here's why:

  • You're using ADAL-React, which defaults to the Implicit Flow for SPAs (Single Page Applications) like React. In this flow, after login, Azure AD returns the ID token (and optionally access token) directly to the frontend via the redirect URI—no backend server is involved in the token exchange.
  • You're storing the ID token in sessionStorage and sending it to the API, which aligns with how the Implicit Flow operates for SPAs (since SPAs can't securely store client secrets, which are required for the more modern Authorization Code Flow with PKCE—note that ADAL is deprecated, and MSAL.js v2+ recommends PKCE for SPAs, but that's a separate consideration).

内容的提问来源于stack exchange,提问作者Nicolas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:30:28