Token from identity server connection\token is not valid for my API
Asked Answered
T

2

7

I am getting a token from my identityserver 4 via url connection/token with a POST request:

Then I copy/paste the value of the access_token key to my API GET request as a header:

mytokenstring

eyJhbGciOiJSUzI1NiIsImtpZCI6IkYxMDhCODA2NUNFMTRBOEEwOTZBODUyMkIxQUNBMkFDMTdEQjQwNEEiLCJ0eXAiOiJKV1QiLCJ4NXQiOiI4UWk0Qmx6aFNvb0phb1Vpc2F5aXJCZmJRRW8ifQ.eyJuYmYiOjE1MDg1OTU5MzIsImV4cCI6MTUwODU5OTUzMiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo2NTUzNSIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0OjY1NTM1L3Jlc291cmNlcyIsInRlYWNoZXJzX3Rlc3RfcGxhbm5lciJdLCJjbGllbnRfaWQiOiJ0ZWFjaGVyc190ZXN0X3BsYW5uZXIiLCJzY29wZSI6WyJ0ZWFjaGVyc190ZXN0X3BsYW5uZXIiXX0.g2x31JcYrXyIavfxCu7UKY3kndznI_gYHJYCxl0dQn3u7l7vWo6qKr13XYMo6P1Lqtu68T2FEXL-5kyS0XwFClpdJE6m13-hfKZsd2QHBmOlgZ2ANwghXW4hfU5nWiwkUACwkP9wfDCULV3oQm5i49L5TQmUiiqcy0TTS2FDBdS5ymFBi1bCKnPh5ErsD8V_4eTqLzxv8CyVkPx2gPd6aBIf_2JNrjrMrrm69kghOHnktVG17KPQhppbIeJO8RP-URiJUJGXIY09yRGVF7YXtkFj-I5QOMvNIAWgUeqNYqH0cuQol9nglA4mtU1MfXtnRoEpRRzGViw7gxJ_-MFadA

Authorization: Bearer mytokenstring

What can cause that the token from the identity server is not valid for my API?

I get a 401 error with POSTMAN

Looking into the output of the kestrel server I get this:

Api> fail: Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware[0]
Api>       'MS-ASPNETCORE-TOKEN' does not match the expected pairing token '52da49ee-6599-483a-b97a-15ced1603005', request rejected.

What do I wrong and what pairing token Guid is that?

API HttpGet:

header:

Authorization Bearer eyJh...UntilTheEndOfTheString

IdentityServer setup:

public void ConfigureServices(IServiceCollection services)
{
    string certificateFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certifiateselfsigned.pfx");

    var certificate = new X509Certificate2(certificateFilePath, "test");

    services.AddIdentityServer()
    .AddSigningCredential(certificate)
        .AddInMemoryApiResources(InMemoryConfiguration.GetApiResources())
        .AddInMemoryClients(InMemoryConfiguration.GetClients())
        .AddTestUsers(InMemoryConfiguration.GetUsers());

    services.AddMvc();
}

UPDATE

Api

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(options =>
    {
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;

        })
            .AddIdentityServerAuthentication(opt =>
           {
               opt.RequireHttpsMetadata = false;
               opt.Authority = "http://localhost:65535"; // IdentityProvider => port running IDP on
               opt.ApiName = "teachers_test_planner"; // IdentityProvider => api resource name
           });

    services.AddMvc();
}

IdentityProvider

public static class InMemoryConfiguration
{
    public static List<TestUser> GetUsers()
    {
        return new List<TestUser>
    {
        new TestUser{ SubjectId = "6ed26693-b0a1-497e-aa14-7b880536920f", Username = "[email protected]", Password = "mypassword",
            Claims = new List<Claim>
            {
                new Claim("family_name", "tatum")
            }
        }
    };
    }

    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
    {
        new ApiResource("teachers_test_planner", "Mein Testplaner")
    };
    }

    public static IEnumerable<IdentityResource> GetIdentyResources()
    {
        return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
    };
    }

    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
    {
        new Client
        {
            ClientId = "teachers_test_planner",
            ClientSecrets = new[]{ new Secret("secret".Sha256()) },
            AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
            AllowedScopes = new []{ "teachers_test_planner" }
        }
    };
    }
}

UPDATE 2

You can find the test project here:

https://github.com/LisaTatum/IdentityServer4Test

UPDATE 3

As nobody asked how I do the http_post to the connect/token endpoint here it is:

enter image description here

Tampon answered 11/10, 2017 at 18:53 Comment(13)
what is the json returned from your POST? and then what are you using from the POST for your GET?Storehouse
updated with more info. Check the token here: jwt.io/#debugger ;-)Tampon
are you are passing everything but the quotes for that access_token?Storehouse
without quotes yes! Problem is also not the expiration time... my wild guess is something like that here: github.com/IdentityServer/IdentityServer3/issues/703 quote:"Ok, your error indicates that the SSL cert IdentityServer is using is not trusted for the token validation from the Web API project to IdentityServer. IOW, you need to establish machine trust to your SSL cert (not just clicking "ignore SSL error" in the browser)."Tampon
sorry for the silly questions, but needed to be sure. does this happen with postman? and the app you created?Storehouse
I have NOT used the IdentityServer so knowledge is vague. have you checked the error logs for IdentityServer (assuming they exist)? Event Viewer? anywhere else besides what postman is reporting?Storehouse
yes with postman. I have created a self signed certificate for identity server which is put into my user account in the thrusted store so I was able at all to make a Post request to /connect/token. The certificate fixed that problem.Tampon
I have not more logging information!Tampon
the installed certificate allowed you to post but didn't fix the issue?Storehouse
the installed certificate just allowed me to POST yes. But maybe I still have to do more with it...dont know.Tampon
I am sorry I cannot help further, maybe all of the back and forth will be enough for someone more knowledgeable with IdentityServer can helpStorehouse
Do you have a separate API project from the IdentityServer4 project?Cartesian
2 projects. IdentityProvider and Api project.Tampon
R
4

All you missed is app.UseAuthentication(). You have to add this into Configure method on Api startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(); // Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseAuthentication();// The missing line

    app.UseStaticFiles();

    app.UseMvc();
}

I write the following consle app to test calling your api

class Program
{
    public static void Main(string[] args) => MainAsync().GetAwaiter().GetResult();

    private static async Task MainAsync()
    {
        // discover endpoints from metadata
        var disco = await DiscoveryClient.GetAsync("http://localhost:65535");
            
        // request token
        var tokenClient = new TokenClient(disco.TokenEndpoint, "teachers_test_client", "secret");
        var tokenResponse = await tokenClient.RequestClientCredentialsAsync("teachers_test_planner");

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

        Console.WriteLine(tokenResponse.Json);
        Console.WriteLine("\n\n");

        // call api
        var client = new HttpClient();
        client.SetBearerToken(tokenResponse.AccessToken);

        var response = await client.GetAsync("http://localhost:52129/api/values/1");
        if (!response.IsSuccessStatusCode)
        {
            Console.WriteLine(response.StatusCode);
        }
        else
        {
            var content = await response.Content.ReadAsStringAsync();
            Console.WriteLine(content);
        }
        Console.ReadKey();
    }
}

You could try on the postman, i haven't tried that

However, I had to change few more things on your project(github) to make it run on my machine. And they are

Project: IdentityProvider

  • mytestplanner.pfx was not set to Copy Always

Project: Api2

  • uninstall IdentityServer4 package. Why do you need IdentityServer4 on the client?
  • Change target framework from <TargetFramework>net462</TargetFramework> to <TargetFramework>netcoreapp2.0</TargetFramework>, (the reason is that 4.6.2 is not installed on my machine)

Anyway, let me know if this works for you

Update

I have added the working project here

Riccio answered 25/10, 2017 at 12:18 Comment(2)
I tried it on my production solution and it works there, thanks. Tested with postman. I was just that I added AddIdentityServerAuthentication and I did not app.UseAuthentication... the other corrections are due to copy/paste errors from production to github test solution :-)Tampon
Glad it works for you. @Tampon thanks for the bounty, this is my first earned bounty :)Riccio
A
0

This can happen if you request a "wrong" token.

Assuming you have Client C calling API A, "POST GetToken" would look something like this:

  • ClientId: C.ClientId
  • Resource: A.Resource ("audience")

Your token suggests that you are doing the following request

Is "http://localhost:65535/resources" the audience of your target API?

Alfonso answered 20/10, 2017 at 17:43 Comment(4)
sorry Alex I thought I posted all code... I have updated my question with more information.Tampon
See if this can resolve the kestrel error in your log: #38839534 also could you add your example token again? Also try renaming your client teachers_test_client while keeping scope and api the same. Lastly, try removing the certificate from your setup to reduce the possible error sources: .AddSigningCredentialAlfonso
Token is added again. Renamed the clientId to 'teachers_test_client'. Removed the certificate with AddSigningCredential and got this error: <h2 class="stackerror">InvalidOperationException: No signing credential is configured. Can&#x27;t create JWT token</h2>Tampon
I will upload the test project to github this evening :-)Tampon

© 2022 - 2024 — McMap. All rights reserved.