4
votes

I'm working on IdentityServer4.AdminUI which developed on github GitHub IdentityServer4.AdminUI

First of all I created a new user simply and set it's password, then I Created new ApiResource with name Api_Name. Then I Created IdentityResource with the same name Api_Name. Finally I Created new client with name Api_Client and set client Allowed Scopes to Api_Name and Allowed Grant Types to Password and finally Set the client secret to secret

Now, I created new WebApi project (Core 2.1) and use this in startup class

public void ConfigureServices(IServiceCollection services) {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddMvcCore().AddAuthorization().AddJsonFormatters();

        services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options => {
                options.Authority = "http://localhost:5000"; //Identity Server URL
                options.RequireHttpsMetadata = false; // make it false since we are not using https
                options.ApiName = "Api_Name"; //api name which should be registered in IdentityServer
            });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
        if (env.IsDevelopment()) {
            app.UseDeveloperExceptionPage();
        }
        else {
            app.UseHsts();
        }

        app.UseAuthentication();

        app.UseHttpsRedirection();
        app.UseMvc();
    }

and sure I used [Authorize] attribute in WebApi controller

Finally, the test. I Created console application and use this code

var identityServer = await DiscoveryClient.GetAsync("http://localhost:5000"); //discover the IdentityServer
        if (identityServer.IsError) {
            Console.Write(identityServer.Error);
            return;
        }

        HttpClient client = new HttpClient();

        var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest {
            Address = identityServer.TokenEndpoint,
            ClientId = "Api_Client",
            ClientSecret = "secret",

            UserName = "Majd",
            Password = "P@ssw0rd@123"
        });

        if (tokenResponse.IsError) {
            Console.WriteLine(tokenResponse.Error);
            return;
        }

        //Call the API

        client.SetBearerToken(tokenResponse.AccessToken);

        var response = await client.GetAsync("https://localhost:44368/api/values");
        var response2 = await client.GetAsync("https://localhost:44368/api/values/1");
        var content = await response.Content.ReadAsStringAsync();
        Console.WriteLine(JArray.Parse(content));
        Console.ReadKey();

The problem is response2 return UnAuthorized 401. so why i got this error since I used the received access token from the identity server

1
what about the return result of response .. ??Atmanirbhar Bharat
Response return the value from api but it's not Authorized. I put it to be sure that every thing is O.KMajd Albaho
Did you try to add the user to a role and give access to that role to the API...Atmanirbhar Bharat

1 Answers

6
votes

You need to also add a requested scope in your token request (even though you said that the client is allowed to access Api_Name).

    var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest {
        Address = identityServer.TokenEndpoint,
        ClientId = "Api_Client",
        ClientSecret = "secret",

        UserName = "Majd",
        Password = "P@ssw0rd@123",
        Scope = "Api_Name"
    });

In IDS4, the tokens are only issued for the scopes that have been requested, unlike IDS3 where you would get all the scopes that the client is allowed. So as far as your Api authentication middleware is concerned, your client was not allowed to access it because the token did not suffice.