dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.37k stars 9.99k forks source link

401 Invalid_token The issuer is invalid - Asp.Net Core 3.1, Angular, Identity, Azure App Service, Linux #23520

Closed richmhouse closed 3 years ago

richmhouse commented 4 years ago

Describe the bug

I have created a web app https://www.alpacabiriba.com using the Visual Studio 2019 Template (Create New Project | Asp.Net Core Web Application | Angular + Inidividual User Accounts). I published this to an Azure Linux App Service using the VS2019 wizzards.

It works fine in development. It also works fine in Azure except when I click on Fetch Data when I get WWW-Authenticate: Bearer error="invalid_token", error_description="The issuer 'https://www.alpacabiriba.com' is invalid"

As it's deployed to a Microsoft's own cloud environment shouldn't it work out of the box or failing this have clear instructions of what to change?

To Reproduce

Visual Studio 2019 Template (Create New Project | Asp.Net Core Web Application | Angular + Inidividual User Accounts) Deploy to Azure App Service using VS2019 & Deployment Centre Wizzards.

I changed as little code as I could to try & get it working. The only changes were.

1) I changed it to load the p12 SSL certificate from /var/ssl/private the Azure App Service put it in. This included my attempt to inline the AddApiAuthorization extension method to get round it insisting on accessing the certificate key from the appsettings.json rather than /var/ssl/private.

2) I added some code to void Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env) to apply database migrations when run in Azure.

var identityServicesServicesColection = services.AddIdentityServer();
identityServicesServicesColection
  .AddAspNetIdentity < ApplicationUser > ()
  .AddOperationalStore < ApplicationDbContext > ()
  //.ConfigureReplacedServices()
  .AddIdentityResources()
  .AddApiResources()
  .AddClients();
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (environment == Environments.Development)
{
  identityServicesServicesColection.AddSigningCredentials();
}
else
{
  var p12 = LoadP12Certificate();
  identityServicesServicesColection.AddSigningCredential(p12);
}
      private X509Certificate2 LoadP12Certificate()
        {
            const string azurePrivateCertificatesDirectory = "/var/ssl/private";
            if (! Directory.Exists(azurePrivateCertificatesDirectory))
            {
                throw new InvalidOperationException($"Directory {azurePrivateCertificatesDirectory} does not exist");

            }
             var privateCertificates = Directory.GetFiles(azurePrivateCertificatesDirectory);
            if (privateCertificates.Length < 1)
            {
                throw new IOException($"No private certificate files found in directory {azurePrivateCertificatesDirectory}");
            }
            var privateCertificateFile = privateCertificates.FirstOrDefault();
            // https://docs.microsoft.com/en-us/azure/app-service/configure-ssl-certificate-in-code
            byte[] bytes;
            try
            {
                bytes = File.ReadAllBytes(privateCertificateFile);
            }
            catch (Exception)
            {
                throw new IOException($"Cannot read certificate file '{privateCertificateFile}'");
            }

            try
            {
                var certificate = new X509Certificate2(bytes);
                return certificate;
            }
            catch (Exception)
            {
                throw new Exception($"Cannot create private certificate from file '{privateCertificateFile}'");
            }
        }
  public void ApplyAnyPendingMigrations(IApplicationBuilder app)
        {
            using (var serviceScope = app.ApplicationServices.CreateScope())
            {
                var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
                context.Database.Migrate();

                if (context.Database.GetPendingMigrations().Any())
                {
                    context.Database.Migrate();
                }
            }

        }

Exceptions (if any)

WWW-Authenticate: Bearer error="invalid_token", error_description="The issuer 'https://www.alpacabiriba.com' is invalid"

Further technical details

Runtime Environment: OS Name: Windows OS Version: 10.0.18363 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\3.1.301\

Host (useful for support): Version: 3.1.5 Commit: 65cd789777

.NET Core SDKs installed: 2.0.0 [C:\Program Files\dotnet\sdk] 2.1.200 [C:\Program Files\dotnet\sdk] 2.1.202 [C:\Program Files\dotnet\sdk] 2.1.402 [C:\Program Files\dotnet\sdk] 2.1.503 [C:\Program Files\dotnet\sdk] 2.1.512 [C:\Program Files\dotnet\sdk] 2.1.513 [C:\Program Files\dotnet\sdk] 2.1.805 [C:\Program Files\dotnet\sdk] 3.1.301 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed: Microsoft.AspNetCore.All 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.All 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

blowdart commented 4 years ago

Is your signing credential file loading correctly? Does the certificate have a private key? Is there anything in the logs from the JWT bearer middleware?

@javiercn How are the extensions configuring allowed issuers?

richmhouse commented 4 years ago

Thanks for getting back to me @blowdart

The credential file appears to be loading correctly:

The following has details of the SSL certificate - the checks are passing at the moment: https://decoder.link/sslchecker/alpacabiriba.com/443

I created the p12 using namecheap converters. My understanding is that a p12 is a bundle of a private key with its X.509 certificate. As such I assume it has a private key. My code doesn't input the p12's password (I read somewhere that this wasn't necessary with a p12), but perhaps I got this wrong. Should I be inputting the password?

The default_docker.log has "Failed to determine the https port for redirect.". I'm guessing this could be the problem. Do I need to configure this somehow? I've pasted the full log below.

Regards RIch

default_docker.log ...

2020-07-01T12:24:08.203741977Z   _____                               
2020-07-01T12:24:08.203770177Z   /  _  \ __________ _________   ____  
2020-07-01T12:24:08.203775977Z  /  /_\  \___   /  |  \_  __ \_/ __ \ 
2020-07-01T12:24:08.203780177Z /    |    \/    /|  |  /|  | \/\  ___/ 
2020-07-01T12:24:08.203783977Z \____|__  /_____ \____/ |__|    \___  >
2020-07-01T12:24:08.203787977Z         \/      \/                  \/ 
2020-07-01T12:24:08.203791777Z A P P   S E R V I C E   O N   L I N U X
2020-07-01T12:24:08.203795577Z 
2020-07-01T12:24:08.203798977Z Documentation: http://aka.ms/webapp-linux
2020-07-01T12:24:08.203802577Z Dotnet quickstart: https://aka.ms/dotnet-qs
2020-07-01T12:24:08.203806077Z ASP .NETCore Version: 3.1.0
2020-07-01T12:24:08.203809577Z Note: Any data outside '/home' is not persisted
2020-07-01T12:24:09.045736169Z Running oryx -appPath /home/site/wwwroot -output /opt/startup/startup.sh -defaultAppFilePath /defaulthome/hostingstart/hostingstart.dll     -bindPort 8080 -userStartupCommand '' 
2020-07-01T12:24:09.407275795Z Oryx Version: 0.2.20200114.13, Commit: 204922f30f8e8d41f5241b8c218425ef89106d1d, ReleaseTagName: 20200114.13
2020-07-01T12:24:09.416859998Z Cound not find build manifest file at '/home/site/wwwroot/oryx-manifest.toml'
2020-07-01T12:24:09.417349698Z Could not find operation ID in manifest. Generating an operation id...
2020-07-01T12:24:09.417725499Z Build Operation ID: 803279e8-7b69-4831-b4f2-b9312432326e
2020-07-01T12:24:11.107730786Z Writing output script to '/opt/startup/startup.sh'
2020-07-01T12:24:11.855642246Z Trying to find the startup DLL name...
2020-07-01T12:24:11.856404146Z Found the startup D name: Biriba.dll
2020-07-01T12:24:11.856734646Z Running the command: dotnet "Biriba.dll"
2020-07-01T12:24:15.799492429Z In non-development environment so loading P12
2020-07-01T12:24:17.297680925Z Applying pending migrations
2020-07-01T12:24:24.964023230Z info: IdentityServer4.Startup[0]
2020-07-01T12:24:24.964078030Z       Starting IdentityServer4 version 3.0.0.0
2020-07-01T12:24:25.101943465Z info: IdentityServer4.Startup[0]
2020-07-01T12:24:25.101984365Z       Using explicitly configured authentication scheme Identity.Application for IdentityServer
2020-07-01T12:24:25.402660141Z info: Microsoft.Hosting.Lifetime[0]
2020-07-01T12:24:25.402737041Z       Now listening on: http://[::]:8080
2020-07-01T12:24:25.403884741Z info: Microsoft.Hosting.Lifetime[0]
2020-07-01T12:24:25.403915141Z       Application started. Press Ctrl+C to shut down.
2020-07-01T12:24:25.404714142Z info: Microsoft.Hosting.Lifetime[0]
2020-07-01T12:24:25.404735842Z       Hosting environment: Production
2020-07-01T12:24:25.411325243Z info: Microsoft.Hosting.Lifetime[0]
2020-07-01T12:24:25.411339443Z       Content root path: /home/site/wwwroot
2020-07-01T12:24:25.701069816Z warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
2020-07-01T12:24:25.701099916Z       Failed to determine the https port for redirect.
richmhouse commented 4 years ago

I've got it working :) :) :).

I set ASPNETCORE_HTTPS_PORT to 5001

I'd tried this before but one of the many other problems I had to solve masked it.

I won't tell you how many weeks this has taken me to solve all the many problems I needed to by piecing together snippets of information from various websites. I would be wonderful if a straight forward set of end to end instuctions could be published. I'll write up what I've done to get it working including my hacks/ workarounds and put it out there, but it would be better coming from people who are experts.

Thanks for your help.

richmhouse commented 4 years ago

PS Please could you look at my hack to input the p12 and advise if there's a cleaner workaround you'd recommend?

var identityServicesServicesColection = services.AddIdentityServer();
identityServicesServicesColection
  .AddAspNetIdentity < ApplicationUser > ()
  .AddOperationalStore < ApplicationDbContext > ()
  //.ConfigureReplacedServices()
  .AddIdentityResources()
  .AddApiResources()
  .AddClients();
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
if (environment == Environments.Development)
{
  identityServicesServicesColection.AddSigningCredentials();
}
else
{
  var p12 = LoadP12Certificate();
  identityServicesServicesColection.AddSigningCredential(p12);
}
blowdart commented 4 years ago

There's better support for linux style certificate formats coming in 5.0 which should hopefully remove the need for your hack.

richmhouse commented 4 years ago

Thanks @blowdart . Looking forward to 5.0. It would be great if you could test 5.0 to make sure this particular VS template it works with Azure & Linux. End to end working tutorials that take a development all the way to deployment in Azure would be wonderful. Reckon doing this it would also help improve 5.0 and iron out any wrinkles.

iarec commented 4 years ago

I've got it working :) :) :).

I set ASPNETCORE_HTTPS_PORT to 5001

I'd tried this before but one of the many other problems I had to solve masked it.

I won't tell you how many weeks this has taken me to solve all the many problems I needed to by piecing together snippets of information from various websites. I would be wonderful if a straight forward set of end to end instuctions could be published. I'll write up what I've done to get it working including my hacks/ workarounds and put it out there, but it would be better coming from people who are experts.

Thanks for your help.

Thank you! Thank you! Thank you!

LTRichHouse commented 3 years ago

image

ghost commented 3 years ago

Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.

This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!