skoruba / IdentityServer4.Admin

The administration for the IdentityServer4 and Asp.Net Core Identity
MIT License
3.57k stars 1.15k forks source link

Forbidden 403 on Api to Api Call #811

Open poison2k opened 3 years ago

poison2k commented 3 years ago

Hello, i try to call an api with another api, but when i use a policy with a specific ApiScope i get a Forbidden 403.

I think it's a simple misconfiguration but i can't find my vault.

MyApi

      public void ConfigureServices(IServiceCollection services)
        {

            services.AddAuthentication("Bearer")
               .AddJwtBearer("Bearer", config =>
               {
                   config.Authority = "https://MyIdentityServer.de";
                   config.TokenValidationParameters = new TokenValidationParameters
                   {
                       ValidateAudience = false,
                   };

               });

            services.AddAuthorization(options =>
            {
                options.AddPolicy("ApiPolicy", policy =>
                {
                    policy.RequireAuthenticatedUser();
                    policy.RequireClaim("MyApiScope");
                });
            });

            services.AddCors(config =>
                config.AddPolicy("AllowAll",
                    p => p.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        ));
       ..........
    }

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
           .....
            app.UseCors("AllowAll");
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers()
                .RequireAuthorization("ApiPolicy");
            });
        }

My Call from the Other API:

            var serverClient = _httpClientFactory.CreateClient();
            var discoveryDocument = await serverClient.GetDiscoveryDocumentAsync("https://MyIdentityServer.de");
            var tokenResponse = await serverClient.RequestClientCredentialsTokenAsync(
                new ClientCredentialsTokenRequest
                {
                    Address = discoveryDocument.TokenEndpoint,
                    ClientId = "MyApi",
                    ClientSecret = "secret",
                    Scope = "MyApiScope"
                });

            var apiClient = _httpClientFactory.CreateClient();

            apiClient.SetBearerToken(tokenResponse.AccessToken);

            List<string> mySecrets = new List<string>();
            using (var response = await apiClient.GetAsync(https://myApiAdress.de/api/Controller/Secrets"))
            {
                string apiResponse = await response.Content.ReadAsStringAsync();
                mySecrets = JsonConvert.DeserializeObject<List<string>>(apiResponse);
            }
           return mySecrets

On the Identity Server i configured a ApiScope and a Client with Client Credentials, i get the Token from the Identity Server, the ApiScope is included but i get always Forbidden 403.

I hope anybody can help me.

poostwoud commented 2 years ago

Did you figure out a solution for this? Please note that the Swagger UI uses a client using grant type authorization_code. This results in the admin being the sub. I have not worked with this grant type so far, but it requires a postback uri, which is not an option in my case. I can't figure out how the admin user becomes the sub in this flow. I've crawled through the code of the API, but no luck so far.

poostwoud commented 2 years ago

Found this issue as well:

https://github.com/skoruba/IdentityServer4.Admin/issues/540

So I'm thinking about extending the api allowing client_credentials to be used as well. I will post my changes here fyi.

poostwoud commented 2 years ago

Okay, that was much easier then I thought it would be. Check out:

https://github.com/skoruba/IdentityServer4.Admin/blob/7023c0c6bb86f0d3c9bd2a5f603d17984c5c5fe3/src/Skoruba.IdentityServer4.Admin.Api/Helpers/StartupHelpers.cs#L244

There is a client requirement here that requires a client claim to be set named "role" and with the value defined in appsettings.json:

https://github.com/skoruba/IdentityServer4.Admin/blob/7023c0c6bb86f0d3c9bd2a5f603d17984c5c5fe3/src/Skoruba.IdentityServer4.Admin.Api/appsettings.json#L17

In the Admin it looks like:

image

Don't forget the "Client Claims Prefix" to be set to "client_" and be sure to request the scope defined in:

https://github.com/skoruba/IdentityServer4.Admin/blob/7023c0c6bb86f0d3c9bd2a5f603d17984c5c5fe3/src/Skoruba.IdentityServer4.Admin.Api/appsettings.json#L16

That's all!

Sen-Gupta commented 2 years ago

The information provided by @poostwoud works like charm. If you are creating a new client specially a daemon or worker process. The steps are as listed below.

Finally, you are good to use your newly configured client.

Here is screenshot from Program.cs of a dotnet project image

Address is the url of sts service, client id and client secret as you have configured. Scope is the name of scope you configured in allowed scope for the client under basic configuration for client.

Client.BaseAddress is the address of the API, we wish to invoke so we are adding AccessToken.

References: https://identitymodel.readthedocs.io/en/latest/aspnetcore/worker.html

Samples: https://github.com/IdentityModel/IdentityModel.AspNetCore