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.38k stars 9.99k forks source link

Asp.Net Core 2.1: SSL from UWP app #3145

Closed HappyNomad closed 6 years ago

HappyNomad commented 6 years ago

I ported my WebAPI from Asp.Net Core 2.0 to release candidate 2.1. The default template enables SSL, but I couldn't get it working. This exception is thrown:

System.Net.Http.HttpRequestException HResult=0x80072F0D Message=An error occurred while sending the request. Source=System.Net.Http StackTrace: at System.Net.Http.HttpClientHandler.d111.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.Http.HttpClient.d58.MoveNext() Inner Exception 1: COMException: The text associated with this error code could not be found. The certificate authority is invalid or incorrect

How can I get SSL to work in my projects? I'm new to working with SSL in .NET so hopefully it's easy to answer for someone familiar with it.

I thought the certificate stuff was handled by VS when I ran the project. Since I keep getting the exception, I manually ran the following commands:

Microsoft Windows [Version 10.0.17134.48] (c) 2018 Microsoft Corporation. All rights reserved.

C:...\WebAPI_NoAuth>dotnet install tool dotnet-dev-certs -g --version 2.1.0-rc1-final

Welcome to .NET Core!

Learn more about .NET Core: https://aka.ms/dotnet-docs Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli-docs

Telemetry

The .NET Core tools collect usage data in order to help us improve your experience. The data is anonymous and doesn't include command-line arguments. The data is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.

Read more about .NET Core CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry

ASP.NET Core

Successfully installed the ASP.NET Core HTTPS Development Certificate. To trust the certificate run 'dotnet dev-certs https --trust' (Windows and macOS only). For establishing trust on other platforms please refer to the platform specific documentation. For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054. No executable found matching command "dotnet-install"

C:...\WebAPI_NoAuth>dotnet dev-certs https --trust Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed if the certificate was not previously trusted. Click yes on the prompt to trust the certificate. A valid HTTPS certificate is already present.

The security warning popped up and I clicked 'yes'. Why is the same exception still thereafter thrown? I've tried passing new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Automatic } to HttpClient's constructor, but alas it's always the same exception.

Tratcher commented 6 years ago

@javiercn

javiercn commented 6 years ago

@HappyNomad Are you trying to host asp.net core inside a UWP application or do you have a UWP application that talks to an asp.net core application.

HappyNomad commented 6 years ago

@javiercn I have a UWP application that talks to an asp.net core application.

chekmx commented 6 years ago

I am also encountering this issue. any resolution found?

javiercn commented 6 years ago

I think this is more of a question about trusting self-signed certificates in UWP. My recommendation would be to ask about it on Windows specific channels or on a site like stackoverflow.

From what I can see taking a quick look at it, there is an HttpBaseProtocolFilter class that can be passed as an instance to the HttpClient instance in order to disable the validations

ilter.IgnorableServerCertificateErrors.Add(
    ChainValidationResult.Untrusted |
    ChainValidationResult.InvalidName);

If not, try passing a custom certificate validation callback as in regular .NET with https://msdn.microsoft.com/en-us/library/system.net.http.httpclienthandler.servercertificatecustomvalidationcallback(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/system.net.http.httpclienthandler.dangerousacceptanyservercertificatevalidator(v=vs.110).aspx

Whatever you do, DO NOT USE THIS CODE IN PRODUCTION as it will invalidate any validation on the certificates.

javiercn commented 6 years ago

Closing this issue as there's no more action to take here.

HappyNomad commented 6 years ago

@javiercn I got your suggestion working in the following code:

using ( var handler = new HttpClientHandler() ) {
#if DEBUG
    handler.ServerCertificateCustomValidationCallback =
        ( message, cert, chain, errors ) => { return true; };
#endif
    using ( var client = new HttpClient( handler ) ) {

But if the goal is to ignore SSL validation, then why not just turn off SSL? That's what I've been doing. I've returned to this issue, though, because I want to get it working as similar as possible to how it needs to work in production. For that, I'm looking into certificate pinning. Does it sound like I'm on the right track?

javiercn commented 6 years ago

@HappyNomad Certificate pinning has nothing to do with this. To make it work in the most similar way as how it would work in production, you would need to find a way for the UWP app to trust the local HTTPS development certificate during development.

I don't have any clue on how to do this if UWP doesn't look at the trust root on the certificate store. I would suggest contacting someone on the UWP forums.

Sorry I can't be of much help.

HappyNomad commented 6 years ago

@javiercn Okay, I asked on the UWP forum about making an app use the local certificate store. UPDATE: I came across this question, the first part of which led me to run certlm, copy the localhost certificate in Personal, and paste it into Trusted Root Certification Authorities. That resolved the exception I originally mentioned; although, this certificate stuff still being new to me, I can't explain for sure why.

Certificate pinning has nothing to do with this.

I'm just today learning about SSL and certificate pinning, and this statement confuses me. Wouldn't certificate pinning bypass the "need to find a way for the UWP app to trust the local HTTPS development certificate during development"? My understanding from what I just read is that certificate pinning means ignoring the local certificate store, and instead only using the pinned certificate. Please tell me if I'm misunderstanding.

javiercn commented 6 years ago

@HappyNomad Maybe we are talking different things. I understand HTTP public key pinning for certificate pinning, but I believe it has a different meaning for you/in the UWP platform. I'm no expert on UWP so maybe doing certificate pinning on UWP is a way to solve this in development.

Trusting the developer certificate during development (whatever form that takes) is the correct approach for it. Just remember that if you require custom code in your app to achieve that you don't include it in your production setup.

I would also not rely on '#DEBUG' to pivot the code but introduce a local symbol for the environment '#LOCALHOST' or '#DEVELOPMENT' and turn it on if not explicitly specified on the DEBUG configuration option. That way you can produce DEBUG and RELEASE builds that work with localhost if you need to do testing.

Hope this helps.

HappyNomad commented 6 years ago

@javiercn Thanks for you help.

Regarding certificate pinning, my nascent understanding leads me to believe it's achievable in UWP using this feature. According to this, a UWP app container can have its own certificate store. According to this, the certificate therein can be trusted to the exclusion of the system store.

I got my UWP app to trust the developer certificate by means of certlm. The solution didn't require extra code. In the local machine's certificate store, I copied the localhost certificate from Personal and pasted it into Trusted Root Certification Authorities. The same certificate was already in the user certificate store's Trusted Root Certification Authorities, but a UWP app can't access there.

The certificate I needed to copy over, that my Asp.Net Core web API uses, was "IIS Express Development Certificate" rather than "ASP.NET Core HTTPS development certificate". The latter was already in the user's MY store so for others reading this thread, according to this, if that's the one your web API uses then you can specify "the sharedUserCertificates capability in the manifest" to grant "an app container read access to the certificates and keys contained in the user MY store".

rafsanulhasan commented 6 years ago

@HappyNomad you solution is probably the best among others

mchasemd commented 5 years ago

.Agreed. Had to copy the certificate from Personal to Trusted Root Certification Authorities using mmc's Copy/Paste. That was lots of hours to find this gem.