.NET Framework 4.7.2下Azure B2C AD令牌获取:AuthenticateAsync返回空
Alright, let's work through your problem step by step. You're trying to fetch an Azure B2C access token using OWIN's AuthenticateAsync but getting a null result, even with SaveTokens=true set in your OpenIdConnect configuration. Here are the key issues to address and actionable fixes:
1. Resolve Duplicate AuthenticationType Conflicts
OWIN relies on unique AuthenticationType values to distinguish between different authentication middleware instances. If you've configured multiple OpenIdConnect middleware with the same AuthenticationType, this will cause conflicts and prevent AuthenticateAsync from finding the correct authentication ticket.
Fix:
Generate a unique AuthenticationType for each middleware instance. For example, append the policy name and client ID to ensure uniqueness:
private OpenIdConnectAuthenticationOptions CreateOptionsFromSiteConfig(B2CConfig config) { string uniqueAuthType = $"{config.Policy}-{config.ClientId}"; // Unique identifier per policy/client OpenIdConnectAuthenticationOptions options = new OpenIdConnectAuthenticationOptions(); options.AuthenticationType = uniqueAuthType; // ... rest of your configuration }
2. Remove Unnecessary RedeemCode=true Setting
Your ResponseType is set to "id_token token", which uses the Implicit Flow for token retrieval. The RedeemCode=true flag is intended for the Authorization Code Flow (where you exchange a code for tokens), so enabling it here is redundant and may interfere with token saving.
Fix:
Remove the options.RedeemCode = true; line from your configuration.
3. Ensure Authentication is Triggered (Passive Mode)
You've set AuthenticationMode = AuthenticationMode.Passive, which means the middleware won't automatically authenticate requests. If the current request hasn't been explicitly authenticated, AuthenticateAsync will return null because no ticket exists in the context.
Fix:
Trigger authentication explicitly before trying to retrieve the token. You can do this in two ways:
- Add the
[Authorize]attribute to your controller/action, specifying the unique authentication type:[Authorize(AuthenticationTypes = "your-unique-auth-type")] public async Task<ActionResult> YourAction() { // Fetch token here } - Or call
ChallengeAsyncdirectly if the auth result is null:var owinContext = HttpContext.GetOwinContext(); var authResult = await owinContext.Authentication.AuthenticateAsync("your-unique-auth-type"); if (authResult == null) { // Trigger authentication flow await owinContext.Authentication.ChallengeAsync("your-unique-auth-type"); return new HttpUnauthorizedResult(); }
4. Use the Correct Method to Retrieve the Token
Instead of directly accessing the Properties.Dictionary, use OWIN's built-in GetTokenValue method for safer, more reliable token retrieval. This method is designed to handle stored tokens properly.
Final Working Code to Fetch Token:
var owinContext = HttpContext.GetOwinContext(); var authResult = await owinContext.Authentication.AuthenticateAsync("your-unique-auth-type"); if (authResult != null && authResult.Properties != null) { string accessToken = authResult.Properties.GetTokenValue("access_token"); // Use your access token here }
5. Verify No Accidental Overwrites in SecurityTokenValidated
Double-check your SecurityTokenValidated notification to ensure you're not replacing the entire AuthenticationTicket.Properties object. Any replacement would erase the saved tokens. Your current code looks fine (you're only modifying identity claims), but this is a common pitfall to watch for.
内容的提问来源于stack exchange,提问作者Hos

