Hello everyone,
We need to deploy our application using several docker containers following the micro-services pattern. Eventually, the angular app must be accessible using "https://some-domain/ whereas the API and the Auth server must be accessible using the "https://some-domain/api" and "https://some-domain/auth" in that order. To do so, we are considering deploying the following containers, 1- Database Container 2- Cache (Redis) Container 3- Auth Server Container serving its services over plain http 4- API Server Container serving its services over plain http 5- Nginx Container which will serve the angular app. in addition, it will act as a reverse proxy for both "/auth" and "/api" virtual directories forwarding their requests to the Auth and the API containers and it will serve everything over https acting as an SSL terminating reverse proxy.
Is this configuration feasible? if so, please advise about the needed steps to configure the solution for this deployment (How to set up App Path Base for the API and the Auth projects, How to forward the headers behind the proxy. etc.. ).
Thanks.
- ABP Framework version: v8.1.0
- UI Type: Angular
- Database System: EF Core (PostgreSQL)
- Tiered (for MVC) or Auth Server Separated (for Angular): Yes
- Exception message and full stack trace:
- Steps to reproduce the issue:
17 Answer(s)
-
0
hi
We are not experts in Docker. You can give it a try. I think it is possible.
If you face any problems, you can provide feedback here.
-
0
Thanks, As a first step, I have tried the following configuring,
Instead of running the Auth server and the API server as docker containers at the moment, we are running them locally on the same server using 'dotnet run' on ports 4444 and 5555 in that order. In addition, we have configured an Nginx server to serve the angular app and to act as a reverse proxy targeting both Auth and API services.
But we're having an issue logging in to the app, apparently, the API server is unable to validate the bearer token. here is the error we're having on the API server
Bearer was not authenticated. Failure message: IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null or empty.
Noting that the application was working perfectly fine before running Auth and API server behind Nginx.
Kindly find below our Nginx configuration,
server { listen 443 ssl; ssl_certificate some-path ssl_certificate_key some-path ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!DH:!EXPORT:!LOW:!MD5:!RC4:!SEED:!SSLv2:!SSLv3; server_name localhost; location / { # Document root for the Angular app root /var/www/app; index index.html index.htm; try_files $uri /index.html; } location /auth/ { proxy_pass http://localhost:4444/auth/; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
location /api/ {
proxy_pass http://localhost:5555/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; }
}
here is a part of the Auth server log related to the request.
20:17:22 INF] Request starting HTTP/1.0 GET http://localhost/auth/connect/authorize?response_type=code&client_id=BOMS_App&state=M2YxUS1qY1hUcExtUlBZY2V4TkFHWGtqMGg2TDRTUk5UeEoyNlZOemVoVS1E%3B%252F%253Fiss%253Dhttps%253A%25252F%25252Flocalhost%25252Fauth&redirect_uri=https%3A%2F%2Flocalhost&scope=openid%20offline_access%20BOMS&code_challenge=wKyenYS__zGR-VQSbdazdk7rxj4Vn6GH5hXvrD3nZCY&code_challenge_method=S256&nonce=M2YxUS1qY1hUcExtUlBZY2V4TkFHWGtqMGg2TDRTUk5UeEoyNlZOemVoVS1E&culture=en&ui-culture=en&returnUrl=%2F%3Fiss%3Dhttps%3A%252F%252Flocalhost%252Fauth - null null
[20:17:23 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessFormPostResponse. [20:17:23 INF] The authorization response was successfully returned to 'https://localhost' using the query response mode: { "code": "[redacted]", "state": "M2YxUS1qY1hUcExtUlBZY2V4TkFHWGtqMGg2TDRTUk5UeEoyNlZOemVoVS1E;%2F%3Fiss%3Dhttps%3A%252F%252Flocalhost%252Fauth", "iss": "https://localhost/auth" }. [20:17:23 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was successfully processed by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessQueryResponse. [20:17:23 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ApplyAuthorizationResponseContext was marked as handled by OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers+Authentication+ProcessQueryResponse. [20:17:23 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was successfully processed by OpenIddict.Server.OpenIddictServerHandlers+Authentication+ApplyAuthorizationResponse1[[OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext, OpenIddict.Server, Version=5.1.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. [20:17:23 DBG] The event OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext was marked as handled by OpenIddict.Server.OpenIddictServerHandlers+Authentication+ApplyAuthorizationResponse1[[OpenIddict.Server.OpenIddictServerEvents+ProcessSignInContext, OpenIddict.Server, Version=5.1.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]]. [20:17:23 INF] Executed action Volo.Abp.OpenIddict.Controllers.AuthorizeController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore) in 50.5326ms [20:17:23 INF] Executed endpoint 'Volo.Abp.OpenIddict.Controllers.AuthorizeController.HandleAsync (Volo.Abp.OpenIddict.AspNetCore)' [20:17:23 INF] Request finished HTTP/1.0 GET https://localhost/auth/connect/authorize?response_type=code&client_id=BOMS_App&state=M2YxUS1qY1hUcExtUlBZY2V4TkFHWGtqMGg2TDRTUk5UeEoyNlZOemVoVS1E%3B%252F%253Fiss%253Dhttps%253A%25252F%25252Flocalhost%25252Fauth&redirect_uri=https%3A%2F%2Flocalhost&scope=openid%20offline_access%20BOMS&code_challenge=wKyenYS__zGR-VQSbdazdk7rxj4Vn6GH5hXvrD3nZCY&code_challenge_method=S256&nonce=M2YxUS1qY1hUcExtUlBZY2V4TkFHWGtqMGg2TDRTUk5UeEoyNlZOemVoVS1E&culture=en&ui-culture=en&returnUrl=%2F%3Fiss%3Dhttps%3A%252F%252Flocalhost%252Fauth - 302 0 null 77.5349ms
And here is a part of the API server log related to the request showing the error,
Request starting HTTP/1.0 GET http://localhost:5555/api/abp/application-configuration?includeLocalizationResources=false - null null [20:17:22 INF] Failed to validate the token. Microsoft.IdentityModel.Tokens.SecurityTokenInvalidIssuerException: IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null or empty. at Microsoft.IdentityModel.Tokens.Validators.ValidateIssuerAsync(String issuer, SecurityToken securityToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.Tokens.Validators.ValidateIssuer(String issuer, SecurityToken securityToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.Tokens.InternalValidators.ValidateAfterSignatureFailed(SecurityToken securityToken, Nullable1 notBefore, Nullable1 expires, IEnumerable1 audiences, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignature(JsonWebToken jwtToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignatureAndIssuerSecurityKey(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateJWSAsync(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) [20:17:22 INF] Bearer was not authenticated. Failure message: IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null or empty. [20:17:22 INF] Executing endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc)' [20:17:22 INF] Route matched with {area = "abp", action = "Get", controller = "AbpApplicationConfiguration", page = ""}. Executing controller action with signature System.Threading.Tasks.Task1[Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto] GetAsync(Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationRequestOptions) on controller Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController (Volo.Abp.AspNetCore.Mvc). [20:17:22 WRN] The cookie 'XSRF-TOKEN' has set 'SameSite=None' and must also set 'Secure'. [20:17:22 DBG] Executing AbpApplicationConfigurationAppService.GetAsync()... [20:17:22 DBG] Executed AbpApplicationConfigurationAppService.GetAsync(). [20:17:22 INF] Executing ObjectResult, writing value of type 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ApplicationConfigurationDto'. [20:17:22 INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc) in 22.3516ms [20:17:22 INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController.GetAsync (Volo.Abp.AspNetCore.Mvc)' [20:17:22 INF] Request finished HTTP/1.0 GET http://localhost:5555/api/abp/application-configuration?includeLocalizationResources=false - 200 null application/json; charset=utf-8 30.2458ms
-
0
hi
Have you configured your app to
Forwarded headers
? https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-8.0#fhmovalidationParameters.ValidIssuer
will be set asrequest.Scheme + Uri.SchemeDelimiter + host + request.PathBase
You can add a middleware to output the HTTP request info to logs to see the request host.
-
0
Hi,
Same issue after configuring ForwardedHeaders on API server (already was configured on Auth Server ). I have added a middleware to log http request as received to API server, please have a look,
[Start of Request Header Dump **************************************************** Accept => application/json, text/plain, / Connection => close Host => localhost User-Agent => Mozilla/5.0 (X11; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0 Accept-Encoding => gzip, deflate, br Accept-Language => en Authorization => Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjNBMjVBMDE1RTM0QUM0ODQ0OTNEMjZCN0FDNDJFMzAwNDIyMzExMkIiLCJ4NXQiOiJPaVdnRmVOS3hJUkpQU2EzckVMakFFSWpFU3MiLCJ0eXAiOiJhdCtqd3QifQ.eyJpc3MiOiJodHRwczovL2xvY2FsaG9zdC9hdXRoIiwiZXhwIjoxNzE1NzkyMTc5LCJpYXQiOjE3MTU3ODg1NzksImF1ZCI6IkJPTVMiLCJzY29wZSI6Im9wZW5pZCBvZmZsaW5lX2FjY2VzcyBCT01TIiwianRpIjoiYzFlY2ExMGMtYTRmMS00MjA3LTllZjItNWFhMjViYjljOGQ5Iiwic3ViIjoiM2ExMjdmY2ItOWZjMi0xYmI2LWMwNzAtYjlhNGZkZmMzMDY2IiwidW5pcXVlX25hbWUiOiJhZG1pbiIsIm9pX3Byc3QiOiJCT01TX0FwcCIsIm9pX2F1X2lkIjoiM2ExMjgwZGItOTNjZC1hOWQxLTk4MzEtNDdmNTJiYmFmYWRlIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYWRtaW4iLCJnaXZlbl9uYW1lIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4iLCJlbWFpbCI6ImFkbWluQGFicC5pbyIsImVtYWlsX3ZlcmlmaWVkIjoiRmFsc2UiLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOiJGYWxzZSIsImNsaWVudF9pZCI6IkJPTVNfQXBwIiwib2lfdGtuX2lkIjoiM2ExMjhmMjQtZGEwNS05YzA0LWQwODItY2UyMGQ3MTM1ZjJkIn0.nNPjps__EmlW4mooC2DecoguQ1JEbqinIw7wMwXTLCaxux0P2GbBRuyYmpP4SJ18KM3AeSSm-isQrkTqctw8yTh7Hno1k86vJ0eb6u1vEHYJQuDeLY_I7fTdALsW51PNTjHuV_bu8x9_1EcyT8-M7GK-8s4iAeX0YiE8YBEyoYozwh13TZHT15g81J61ZQPCFZitc6j1UaGdfaL7lsDsPS2T-o5FAebeYY-gUo1l8gQ49HysYsqkMJ4CFjpOxvuds-MggFWYEBvK3bPGxPJp0FO6lwp0EbRpc5J1kED-FufpeB5e9OnYjIBDVelvznRzPDMfexoFFjSLzLnR1MV5MA Cookie => XSRF-TOKEN=CfDJ8N1QfI568glOqiA2gwTfpOckyL_E2fyYBQf9Sf0yzu-3Rmek9iPiAXQmTaDpo17zr8ikHolLKfCCBkGA4lrkuR4ldBdClb_v13GjgqanxDmyKXve9G6s3vIdUwUV_prNWNzq7axKIkYaTV39svQpZ2o; lpx_side-menu-state=; lpx_loaded-css=dark; .AspNet.Consent=true; pga4_session=b667a340-da68-459c-b4c6-bd9e27da0a3b!TCIlwI7wW+q7/befKsaarfjt7kI/h5WR7j4662Z91Do=; .AspNetCore.Antiforgery.A9rjSBHiKcc=CfDJ8N1QfI568glOqiA2gwTfpOeGwEPmux_VuEQ17Vh4rdATwSgmz4s7S3QQcje7B_Rtwrd_KcXvwxByuGxSRTbldwI23uTyMS7LYsv2DTg_t8oIRUPS-Popc2koDkMlKnd8zsM74vE_TzPPOc2VQP3oql8; .AspNetCore.Culture=c%3Den%7Cuic%3Den Referer => https://localhost/?iss=https%3A%2F%2Flocalhost%2Fauth X-Real-IP => 127.0.0.1 X-Original-Proto => http X-Requested-With => XMLHttpRequest Sec-Fetch-Dest => empty Sec-Fetch-Mode => cors Sec-Fetch-Site => same-origin X-Original-For => 127.0.0.1:36630 End of Request Header Dump ****************************************************
here is the decoded bearer token (Payload section),
{ "iss": "https://localhost/auth", "exp": 1715792179, "iat": 1715788579, "aud": "BOMS", "scope": "openid offline_access BOMS", "jti": "c1eca10c-a4f1-4207-9ef2-5aa25bb9c8d9", "sub": "3a127fcb-9fc2-1bb6-c070-b9a4fdfc3066", "unique_name": "admin", "oi_prst": "BOMS_App", "oi_au_id": "3a1280db-93cd-a9d1-9831-47f52bbafade", "preferred_username": "admin", "given_name": "admin", "role": "admin", "email": "admin@abp.io", "email_verified": "False", "phone_number_verified": "False", "client_id": "BOMS_App", "oi_tkn_id": "3a128f24-da05-9c04-d082-ce20d7135f2d" }
Thank you.
-
0
hi
Your token's
issuer
ishttps://localhost/auth
, but theHost
in your HTTP request islocalhost
. -
0
Hi,
I see, but the 'host' header in the http request is related to the host sending the request (in this case, the angular app hosted on https://localhost) whereas the 'Issuer' is indeed https://localhost/auth (where Auth server is running). I don't see why they should match. Please can you explain more?
-
0
hi
I don't see why they should match. Please can you explain more?
This is a rule to validate a token, the server will get the issuer from the token and get the host from the HTTP context. eventually try to match them.
1. You can try to set the issuer and reissue a token.
serverBuilder.SetIssuer(new Uri("https://localhost/"));
public override void PreConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration(); PreConfigure<OpenIddictBuilder>(builder => { builder.AddValidation(options => { options.AddAudiences("MyProjectName"); options.UseLocalServer(); options.UseAspNetCore(); }); }); if (!hostingEnvironment.IsDevelopment()) { PreConfigure<AbpOpenIddictAspNetCoreOptions>(options => { options.AddDevelopmentEncryptionAndSigningCertificate = false; }); PreConfigure<OpenIddictServerBuilder>(serverBuilder => { serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", "00000000-0000-0000-0000-000000000000"); serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!)); }); } }
You can configure the
TokenValidationParameters
to disable to match the issuer and host. or addhttps://localhost/
andhttps://localhost/auth
tovalidissuers
https://learn.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters.validissuer?view=msal-web-dotnet-latest#microsoft-identitymodel-tokens-tokenvalidationparameters-validissuer
https://learn.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters.validissuers?view=msal-web-dotnet-latest#microsoft-identitymodel-tokens-tokenvalidationparameters-validissuers
-
0
Thank you for explaining. Most appreciated.
I will try the proposed solution and will get back to you shortly. thanks.
-
0
: )
-
0
Hello again,
I have tried to set the issuer on the API server to "https://localhost/auth" using the following,
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]);
options.MetadataAddress = configuration["AuthServer:Authority"] + "/.well-known/openid-configuration";
options.Audience = "BOMS";
options.TokenValidationParameters.ValidIssuer = "
https://localhost/auth"
;
});
}
apparently, it has passed this validating but it is now failing with the following error
End of Request Header Dump **************************************************** [18:45:35 INF] Failed to validate the token. Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10500: Signature validation failed. No security keys were provided to validate the signature. at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignature(JsonWebToken jwtToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateSignatureAndIssuerSecurityKey(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ValidateJWSAsync(JsonWebToken jsonWebToken, TokenValidationParameters validationParameters, BaseConfiguration configuration) [18:45:35 INF] Bearer was not authenticated. Failure message: IDX10500: Signature validation failed. No security keys were provided to validate the signature.
and here is the token
{ "iss": "https://localhost/auth", "exp": 1716137135, "iat": 1716133535, "aud": "BOMS", "scope": "openid offline_access BOMS", "jti": "e62044b8-a4fc-4107-be12-40620c369d79", "sub": "3a127fcb-9fc2-1bb6-c070-b9a4fdfc3066", "unique_name": "admin", "oi_prst": "BOMS_App", "oi_au_id": "3a1280db-93cd-a9d1-9831-47f52bbafade", "preferred_username": "admin", "given_name": "admin", "role": "admin", "email": "admin@abp.io", "email_verified": "False", "phone_number_verified": "False", "client_id": "BOMS_App", "oi_tkn_id": "3a12a3b4-770e-2aea-699c-a9b474601962" }
<br> <br> What am I missing ?
-
0
hi
Please set your API and authserver log level to
Debug
and then share the logs of these requests.Thanks
public class Program { public async static Task<int> Main(string[] args) { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) .Enrich.FromLogContext() .WriteTo.Async(c => c.File("Logs/logs.txt")) .WriteTo.Async(c => c.Console()) .CreateLogger();
liming.ma@volosoft.com
-
0
Hi,
I have sent you the logs after enabling the logging.
Thank you.
-
0
hi
Can you also try to use the latest
Microsoft.IdentityModel
packages in your API website?<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="7.5.1" /> <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.5.1" /> <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.5.1" />
-
0
-
0
-
0
Hello,
I have included the mentioned packages in the Http.Api.Host project and retried the action after rebuilding the project. I sent you the logs to the mail. Still fails with the same error and looping back and forth between Auth site the Angular App.
Thanks.
-
0
hi
Can you share the online URL of the authserver and API websites?
liming.ma@volosoft.com