Reputation: 357
I set up a docker in macos (but should work in any environement):
1) Identity server 4 running in a container
launchsettings:
"MacTest": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_HTTPS_PORT": "44000",
"ASPNETCORE_ENVIRONMENT": "MacTest"
},
"applicationUrl": "https://0.0.0.0:44000"
}
dockerfile (dockerfile-idp):
ENTRYPOINT ["dotnet", "run", "--launch-profile", "MacTest"]
composer:
identityserver:
image: idp
build:
context: .
dockerfile: ./docker/dockerfile-idp
ports:
- "9000:9000"
- "44000:44000"
volumes:
- .:/idp
2) An APIsource authenticate on identity server running on an container: launchsettings:
"MacTest": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "MacLocalTest",
"ASPNETCORE_HTTPS_PORT": 44100
},
"applicationUrl": "https://0.0.0.0:44100"
}
dockerfile (dockerfile-api):
ENTRYPOINT ["dotnet", "run", "--launch-profile", "MacTest"]
composer:
api:
image: api
build:
context: .
dockerfile: ./docker/dockerfile-api
ports:
- "9100:9100"
- "44100:44100"
volumes:
- .:/api
3) An angular app running on other container
Problem: Angular login page can connect to identity server and can get the token that works... OK
It can can Api and retrieve public data... OK
BUT it can't call a protected method with Authorize. I start believing that the api try to authenticate itself from identity server but for some reason it can't access to the server.
[HttpGet("info")]
[AppAuthorize] => THIS NOT WORK
public IActionResult Info()
{
...
}
ERROR:
System.Net.Sockets.SocketException (99): Cannot assign requested address
at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
HttpRequestException: Cannot assign requested address
System.Net.Http.ConnectHelper.ConnectAsync(string host, int port, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask<ValueTuple<HttpConnection, HttpResponseMessage>> creationTask)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, bool doRequestAuth, CancellationToken cancellationToken)
System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task<HttpResponseMessage> sendTask, HttpRequestMessage request, CancellationTokenSource cts, bool disposeCts)
Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)
Show raw exception details
System.Net.Http.HttpRequestException: Cannot assign requested address ---> System.Net.Sockets.SocketException: Cannot assign requested address
at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
IOException: IDX20804: Unable to retrieve document from: 'https://localhost:44000/.well-known/openid-configuration'.
Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)
Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel)
Microsoft.IdentityModel.Protocols.ConfigurationManager<T>.GetConfigurationAsync(CancellationToken cancel)
Show raw exception details
System.IO.IOException: IDX20804: Unable to retrieve document from: 'https://localhost:44000/.well-known/openid-configuration'. ---> System.Net.Http.HttpRequestException: Cannot assign requested address ---> System.Net.Sockets.SocketException: Cannot assign requested address
at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
--- End of inner exception stack trace ---
at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel)
at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://localhost:44000/.well-known/openid-configuration'.
Microsoft.IdentityModel.Protocols.ConfigurationManager<T>.GetConfigurationAsync(CancellationToken cancel)
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.AuthenticationHandler<TOptions>.AuthenticateAsync()
Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, string scheme)
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler.HandleAuthenticateAsync() in C:\local\identity\server4\AccessTokenValidation\src\IdentityServerAuthenticationHandler.cs
Microsoft.AspNetCore.Authentication.AuthenticationHandler<TOptions>.AuthenticateAsync()
Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, string scheme)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.InvokeCore(HttpContext context)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
I'm trying to set a new wetwork setting but quite challanging, I don't even know if the network is the problem. Anybody can help?
Thnak you
Upvotes: 2
Views: 3406
Reputation: 357
I resolved my problem (not yet with https) but notmal workflow get worked.
If anybody had the same issue I recommend the article: Exactly what I did but I have an angular app in plus
For https I recommend: To get it work with https
It's quite challenging, still work to do but at least this enoying step done.
Upvotes: 0
Reputation: 357
Thank you for your help. I think I managed to pass this error and now another error shows up:
AuthenticationException: The remote certificate is invalid according to the validation procedure.
identity server startup:
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44000";
options.SupportedTokens = SupportedTokens.Jwt;
// Note: Set to true in production
options.RequireHttpsMetadata = true;
options.ApiName = "api";
});
Api startup:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://idp:44000";
options.RequireHttpsMetadata = true;
options.ApiName = "api";
});
I couldn't find any solution. Is it any certificate problem do you think?
Upvotes: 0
Reputation: 3762
So you have shown a lot of the setup of the IdentityServer, but you haven't shown much of the setup for your API.
My best bet is one of the following two:
1) You haven't installed a middleware and set it up correctly on your API. And therefore the API is not able to do anything with the bearer token.
From the documentation: Securing APIs
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
// base-address of your identityserver
options.Authority = "https://demo.identityserver.io";
// name of the API resource
options.Audience = "api1";
});
You need to add the authority (which is the IdentityServer) and then you need to tell the IdentityServer that it will be securing an API. All of this can be found in the documentation.
2) Your network between the two docker containers does not allow them to communicate with each other.
Try to connect to the docker container of your API with SSH (google how to do that). Try to call the identityserver with cURL and see if you can hit the IP from inside of the Docker container of the API. If you cannot do that, you need to setup a shared internal network between the two docker containers.
Upvotes: 2