Search code examples
c#asp.net-coreoauth-2.0identityserver4openid-connect

IdentityServer4: audience is empty when calling web api?


IdentityServer4 v4, when calling the web api via a web blazor client app an error occurs.

Bearer error="invalid_token", error_description="The audience 'empty' is invalid" value in header 

The scope is added in startup like this, how to add audience?

            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;
                options.ClientId = "testapp";
                options.ResponseType = "code";
                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;
                options.UseTokenLifetime = false;
                options.Scope.Add("openid");
                options.Scope.Add("profile");
                options.Scope.Add("offline_access");
                options.Scope.Add("account");
                options.Scope.Add("accountwrite");
                options.Scope.Add("accountread");
                options.Scope.Add("payment");
                options.Scope.Add("paymentwrite");
                options.Scope.Add("paymentread");
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name"
                };
                options.Events = new OpenIdConnectEvents
                {
                    OnAccessDenied = context =>
                    {
                        context.HandleResponse();
                        context.Response.Redirect("/");
                        return Task.CompletedTask;
                    }
                };
            });

Solution

  • The Audience claim is only populated if you have defined ApiScopes and ApiResources in IdentityServer.

    An API scope can be defined as :

    new ApiScope(name: "invoice",
            displayName: "Invoices access",
            userClaims: new List<string> { "level" }),
    

    And to define a suitable ApiResource, you can define one by:

    _apiResources = new List<ApiResource>()
    {
        new ApiResource("invoiceapi")
        {
            Scopes = { "invoice" }   //invoice is the name of the ApiScope
        }
    };
    

    Then you need to ask for the invoice scope in your client.

    To complement this answer, I write a blog post that goes into more detail about this topic: IdentityServer – IdentityResource vs. ApiResource vs. ApiScope