Search code examples
c#authenticationjwtasp.net-core-webapi

Verify a JWT Token issued by Entra AD App Registration in ASP.NET Core


I right now have an Entra/Azure AD App registration that is being used by a small Angular SPA to authenticate it to an ASP.NET Core Web API.

When I decode the JWT, the iss (issuer) is:

 "iss": "https://sts.windows.net/64..............a21/",

and in my Program.cs, I have:

builder.Services.AddAuthentication(options =>
    {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    o.TokenValidationParameters = new TokenValidationParameters
    {
        ValidIssuer = builder.Configuration["https://login.microsoftonline.com/64..............a21"],
        ValidAudience = builder.Configuration["http://localhost:5036/"],
        IssuerSigningKey = new SymmetricSecurityKey
        (Encoding.UTF8.GetBytes(builder.Configuration["?????"])), //this is what i feel like I am missing
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = false,
        ValidateIssuerSigningKey = true
    };
});

I am getting http error 401's when running my Angular app in local dev mode and the API locally too. I was following this guide to make the app registration.

So my question is - how can I get the signing key so that my app can validate JWT tokens from Azure.


Solution

  • You should only need to use code like this:

    .AddJwtBearer(options =>
    {
        options.Authority = ...;
        options.Audience = ...;
    }
    

    Your wider problem looks to be that you are receiving the wrong type of JWT access token, with a nonce in the JWT header.

    To fix it you need to expose an API scope from an API registration, then include it in the API permissions of your Angular client. During its OIDC flow the client should then request that scope. My example SPA uses these settings:

    {
        "app": {
            "apiBaseUrl":             "https://api.mycompany.com/api"
        },
        "oauth": {
            "authority":              "https://login.microsoftonline.com/7f071fbc-8bf2-4e61-bb48-dabd8e2f5b5a/v2.0",
            "clientId":               "e9a29a01-21b4-4533-bae6-438141ebc05c",
            "redirectUri":            "https://web.mycompany.com/spa/",
            "postLogoutRedirectUri":  "https://web.mycompany.com/spa/loggedout.html",
            "scope":                  "openid api://552b475c-471d-43a1-9dfe-f6b895931110/investments"
        }
    }
    

    Step 4 of my blog post has further details.