Identityserver4: Getting 'Unauthorized' when requesting a token

Created on 31 Jan 2017  路  22Comments  路  Source: IdentityServer/IdentityServer4

I am new to this and have read the guide along with doing quite a few tutorials but I'm getting the above token response.

I have used postman, client side requests and a webrequest and all is well (returning a token response), but when I try requesting it from the identitymodel dll, I get the 'Unauthorized' token response.

var disco = await DiscoveryClient.GetAsync("https://identityservertest"); var tokenClient = new TokenClient(disco.TokenEndpoint, clientId, clientSecret); var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(username, password);

I have set up the identity server in a test environment under SSL (using a valid certificate) and to sign the tokens, I've used a self signed certificate. I've also set up CORS so it allows any origin, headers, method and credentials.

The clients haven't been set with 'AllowedCorsOrigins' as I assume if that is left empty, it wouldn't make a difference where the client is connecting from and also the fact it works locally on my machine.

When I look at the log, the idsv doesn't show anything of any significance, only logs when it discovers the idsv. When I run the idsv on my local machine, everything works a treat. I'm sure it's a configuration issue, but any pointers will be much appreciated.

question

Most helpful comment

Maybe ,I have the same problem.try this:
var discoveryClient = new DiscoveryClient(Contants.Constants.Authority);
//var disco = await DiscoveryClient.GetAsync(Contants.Constants.Authority);
discoveryClient.Policy = new DiscoveryPolicy { RequireHttps = false };
var disco = await discoveryClient.GetAsync();

All 22 comments

Have you checked disco.IsError and made sure that this request was working?

Hi Dominic, disco.IsError is returning false. In disco, I can see all the configuration of the idsv.

Below is the client I used in the above example:

new Client { ClientId = "aedb9357-b3ee-46cd-b4cd-4582ferd5897", ClientName = "testClient", AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, ClientSecrets = { new Secret("test".Sha256()) }, AllowedScopes = new List<string> { "a.read", "a.write", "a.delete", "b.read" }, Claims = new List<Claim> { new Claim("Role","Test Role") }, AllowOfflineAccess = true, AlwaysSendClientClaims = true },

The API resources have been declared which include the scopes mentioned in the code above.

FYI - The token endpoint is showing correctly in the tokenClient.

the identityserver logs must show something of interest.

This is what I have so far from the investigation I've done:

If I configure the application in IIS to be unsecure (not SSL) - 'Error connecting to http://ipaddress/.well-known/openid-configuration: HTTPS required'. Nothing is in log as it doesn't reach the idsv

After that attempt, I did some reading up and came across https://github.com/IdentityServer/IdentityServer4/issues/213 so I added in the following into the startup of the idsv;

app.Use(async (context, next) => { context.Request.Scheme = "https"; await next.Invoke(); });

If I configure the application in IIS to be secure (SSL) with a valid certificate with no domain name specified - 'Error connecting to https://ipaddress:443/.well-known/openid-configuration: An error occurred while sending the request'. Nothing is in log as it doesn't reach the idsv

If I configure the application in IIS to be secure (SSL) with a valid certificate with a domain name specified - I get the 'Unauthorized' error in the token response.

The following is the log I get from the last attempt:

info: Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]
User profile is available. Using 'C:\Windows\system32\config\systemprofile\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
Hosting environment: Production
Content root path: C:\inetpub\IdentityServerTest
Now listening on: http://localhost:27440
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://identity.test/.well-known/openid-configuration
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (39ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [x].[Id], [x].[Description], [x].[DisplayName], [x].[Emphasize], [x].[Enabled], [x].[Name], [x].[Required], [x].[ShowInDiscoveryDocument]
FROM [IdentityResources] AS [x]
ORDER BY [x].[Id]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (6ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [i].[Id], [i].[IdentityResourceId], [i].[Type]
FROM [IdentityClaims] AS [i]
WHERE EXISTS (
SELECT 1
FROM [IdentityResources] AS [x]
WHERE [i].[IdentityResourceId] = [x].[Id])
ORDER BY [i].[IdentityResourceId]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [x].[Id], [x].[Description], [x].[DisplayName], [x].[Enabled], [x].[Name]
FROM [ApiResources] AS [x]
ORDER BY [x].[Id]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a3].[Id], [a3].[ApiResourceId], [a3].[Type]
FROM [ApiClaims] AS [a3]
WHERE EXISTS (
SELECT 1
FROM [ApiResources] AS [x]
WHERE [a3].[ApiResourceId] = [x].[Id])
ORDER BY [a3].[ApiResourceId]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a2].[Id], [a2].[ApiResourceId], [a2].[Description], [a2].[Expiration], [a2].[Type], [a2].[Value]
FROM [ApiSecrets] AS [a2]
WHERE EXISTS (
SELECT 1
FROM [ApiResources] AS [x]
WHERE [a2].[ApiResourceId] = [x].[Id])
ORDER BY [a2].[ApiResourceId]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a].[Id], [a].[ApiResourceId], [a].[Description], [a].[DisplayName], [a].[Emphasize], [a].[Name], [a].[Required], [a].[ShowInDiscoveryDocument]
FROM [ApiScopes] AS [a]
WHERE EXISTS (
SELECT 1
FROM [ApiResources] AS [x]
WHERE [a].[ApiResourceId] = [x].[Id])
ORDER BY [a].[ApiResourceId], [a].[Id]
info: Microsoft.EntityFrameworkCore.Storage.IRelationalCommandBuilderFactory[1]
Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [a0].[Id], [a0].[ApiScopeId], [a0].[Type]
FROM [ApiScopeClaims] AS [a0]
INNER JOIN (
SELECT DISTINCT [a].[ApiResourceId], [a].[Id]
FROM [ApiScopes] AS [a]
WHERE EXISTS (
SELECT 1
FROM [ApiResources] AS [x]
WHERE [a].[ApiResourceId] = [x].[Id])
) AS [a1] ON [a0].[ApiScopeId] = [a1].[Id]
ORDER BY [a1].[ApiResourceId], [a1].[Id]
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 2938.6673ms 200 application/json
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://identity.test/.well-known/openid-configuration/jwks
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration/jwks
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 62.7071ms 200 application/json

where does this error come from:

'Error connecting to http://ipaddress/.well-known/openid-configuration: HTTPS required'.

The error comes from the line:

var disco = await DiscoveryClient.GetAsync("http://ipaddress");

This is the test environment. Hosting the idsv locally in IIS with a self signed certificate works fine.

then disable the HTTPS requirement on the policy property.

The HTTPS requirement is only set when I've set the application to be secure under SSL in IIS

The error

'Error connecting to http://ipaddress/.well-known/openid-configuration: HTTPS required'.

is when I've set it up as unsecure in IIS and without setting the HTTPS requirement in idsv.

Is there anything which needs setting in IIS which might be causing the issue? Baring in mind I can retrieve the token from postman, from client side code (via ajax) and from a webrequest.

I'm really more interested in getting it to work in the test environment under SSL as I'm sure this will be the same issue when we move into the production environment.

Thank you for the help so far.

What exactly is the problem now? by default DiscoveryClient does not allow HTTP - you need to relax the policy for that.

So my issue at the moment is, I have the idsv setup in a test environment (Windows Server 2012 if that makes a difference), I have it set up so it's secure under SSL in IIS (using a certificate), I have a different certificate to validate the token, I also have set the following in the pipeline:

app.Use(async (context, next) => { context.Request.Scheme = "https"; await next.Invoke(); });

When I make this request ;

var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(username, password);

I get the 'Unauthorized' token response. The DiscoveryClient returns all the correct configurations setup in idsv and the IsError is returning false.

Any help will be much appreciated as currently I'm lost and out of ideas.

Thank you - relaxing the policy does indeed work when the idsv is hosted in the test environment not under SSL. It discovers the idsv and returns a valid token.

I'm still stuck with the above scenario which is the main sticking point.

why do you do this?

app.Use(async (context, next) => { context.Request.Scheme = "https"; await next.Invoke(); });

I do it so the DiscoveryClient can return me the configuration. If I don't use the code above, I start getting policy violations (Issuer name does not match authority: http://ipaddress & Endpoint not using HTTPS), note - it should be 'https://ipaddress' not 'http://ipaddress'

Then something is not correctly configured with your IIS integration.

Any pointers or examples of how I go about configuring the IIS Integration to work with HTTPS?

Thank you

I've already gone through that when I initially set IIS up. I thought you meant UseIISIntegration() in WebHostBuilder hence why I was asking for pointers.

I'll carry on doing research and reading up, I'm sure it'll be a configuration issue, but where?

Any update on the issue? closing for now - feel free to re-open if it needs further discussion.

Maybe ,I have the same problem.try this:
var discoveryClient = new DiscoveryClient(Contants.Constants.Authority);
//var disco = await DiscoveryClient.GetAsync(Contants.Constants.Authority);
discoveryClient.Policy = new DiscoveryPolicy { RequireHttps = false };
var disco = await discoveryClient.GetAsync();

@zzyykk123456
Thanks for sharing!

@ZahirYounis You can use my answer at stack overflow https://stackoverflow.com/a/46364226/2047788

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

user1336 picture user1336  路  3Comments

krgm03 picture krgm03  路  3Comments

leksim picture leksim  路  3Comments

Aravind1729 picture Aravind1729  路  3Comments

brockallen picture brockallen  路  3Comments