Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IdentityServer4 invalid_token "The issuer is invalid" on Azure, working on localhost

Help please, I'm building a .NET Core API with ionic front end. I want to use ASPNET Core Identity so I was more or less following this example https://identityserver4.readthedocs.io/en/release/quickstarts/6_aspnet_identity.html

here is what I have in Startup.cs

// Adds IdentityServer
services.AddIdentityServer()                
    .AddTemporarySigningCredential()
    .AddInMemoryIdentityResources(Config.GetIdentityResources())
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients(Configuration))
    .AddAspNetIdentity<ApplicationUser>();

and

app.UseIdentity();
app.UseIdentityServer();
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
    Authority = API_address,
    RequireHttpsMetadata = false,

    ApiName = "myAPIs"
});

and in my Config.cs file for in memory configurations I have

public class Config
{
    // scopes define the resources in your system
    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
        };
    }

    // scopes define the API resources in your system
    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            new ApiResource(
                "myAPIs",                                       // Api resource name
                "My API Set #1",                                // Display name
                new[] { JwtClaimTypes.Name, JwtClaimTypes.Role }) // Claims to be included in access token
        };
    }

    // client want to access resources (aka scopes)
    public static IEnumerable<Client> GetClients(IConfigurationRoot configuration)
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "myClient",
                ClientName = "My Custom Client",
                AllowedCorsOrigins = new List<string>
                {
                    "whateverINeedHere"
                },
                AccessTokenLifetime = 60 * 60 * 24,
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                RequireClientSecret = false,
                AccessTokenType = AccessTokenType.Jwt,
                AllowedScopes =
                {
                    "myAPIs"
                }
            }
        };
    }
}

Now the problem is that when I test this locally, everything works just fine. I hit the /connect/token endpoint, I get a token response, hit the controller that needs token authorization and my claims are there. But when I deploy it to Azure, when I want to use the token (issued from that environment) I get 401 Unauthorized with response header invalid_token "The issuer is invalid". I've Googled, but people get invalid tokens with signature problems, not issuer. I've never used identity server before and to me this looks like it's some configuration problem. I have compared tokens I get from identity server on jwt.io, they look exactly the same, only difference being the issuer localhost -> myAPIAddress.

Can someone point me to the right direction?

like image 384
Милан Avatar asked Oct 18 '22 15:10

Милан


2 Answers

This smells like it could be the temporary signing credentials. I also ran into problems when deploying to Azure when my cert wasn't loading.

I suggest you create a self signed cert and add it to azure using the following instructions. (Note this can be done in the new portal). https://azure.microsoft.com/en-us/blog/using-certificates-in-azure-websites-applications/

REMEMBER: Make sure you add the WEBSITE_LOAD_CERTIFICATES application setting!

Also for your benefit, here's the code I use to load the cert in my startup.cs. I keep a copy of the cert in the repository so I can load it from disk as a fallback (when I'm on my dev machine).

X509Certificate2 cert = null;
using (X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
    certStore.Open(OpenFlags.ReadOnly);
    X509Certificate2Collection certCollection = certStore.Certificates.Find(
        X509FindType.FindByThumbprint,
        // Replace below with your cert's thumbprint
        "A9781679661914B7539BE020EE9C4F6880579F42",
        false);
    // Get the first cert with the thumbprint
    if (certCollection.Count > 0)
    {
        cert = certCollection[0];
        // Use certificate
        Log.Logger.Information($"Successfully loaded cert from registry: {cert.FriendlyName}");
    }
}

// Fallback to local file for development
if (cert == null)
{
    cert = new X509Certificate2(Path.Combine(_env.ContentRootPath, "myauth.pfx"), "mypassword");
    Log.Logger.Information($"Falling back to cert from file. Successfully loaded : {cert.FriendlyName}");
}

services.AddIdentityServer()
    .AddSigningCredential(cert)
like image 196
Ben Cull Avatar answered Oct 20 '22 22:10

Ben Cull


Could be you've got an SSL/TLS issue between client and IdentityServer, are you able to view logged exceptions from IdentityServer itself? You may see something like:

"... Could not establish trust relationship for the SSL/TLS..."

If you're running IdentityServer on HTTPS you need to make sure you've got its domain/sub-domain in your certificate.

Either way, IdentityServer logs lots of useful info so turn on logging and check out what it says, that should point you in the right direction.

like image 26
Matt Avatar answered Oct 20 '22 20:10

Matt