# Source: https://raw.githubusercontent.com/ServiceStack/docs.servicestack.net/refs/heads/main/MyApp/_pages/netcore-localhost-cert.md

---
slug: netcore-localhost-cert
title: Configure localhost development dev certificate
---

Due to the environmental pressures to [use HTTPS everywhere](https://web.dev/why-https-matters/) with 
[Browsers marking HTTP as not secure](https://blog.google/products/chrome/milestone-chrome-security-marking-http-not-secure/) and 
[operating systems and mobile platforms](https://developer.apple.com/documentation/security/preventing_insecure_network_connections) requiring
all connections to be secure by default, it's become the defacto standard to both host production sites with HTTPS as well as
[developing locally under HTTPS with a Self-Signed Certificate](https://www.hanselman.com/blog/DevelopingLocallyWithASPNETCoreUnderHTTPSSSLAndSelfSignedCerts.aspx).

In most cases it's sufficient to run .NET Core Apps on `https://localhost:5001` for normal browser development and if you receive an invalid certificate
error you can run:

:::sh
dotnet dev-certs https --trust
:::

To trust the local development certificate and remove the SSL Certificate error in your browser.

## When localhost is not allowed

However for Apps needing to support OAuth providers that don't allow `localhost` domains like **Sign In with Apple** you would need
to use a different domain. A popular workaround is to use a DNS name that resolves to `127.0.0.1` in which case you can use:

```
local.servicestack.com
```

Which you can use to view your local Web App typically on `https://localhost:5001` at `https://local.servicestack.com:5001` which
will allow you to register as valid domains & callback URLs in OAuth Apps you want to support. As this is a real DNS A record
it will also work in emulators & different environments like WSL.

## When developing for Android

But to be able to access your local dev server from an Android Emulator you'd instead need to use the special `10.0.2.2` loopback
IP, which you could support by [updating your Android Emulator /system/etc/hosts file](https://stackoverflow.com/a/53929946/85785)
mapping to include:

```
10.0.2.2       local.servicestack.com
```

Which can be quite cumbersome to change, alternatively an easier solution is to use a DNS record that resolves to `10.0.2.2`:

```
dev.servicestack.com
```

and instead update your OS hosts file (e.g. `%SystemRoot%\System32\drivers\etc\hosts` for Windows or `/etc/hosts` on macOS/Linux) to include:

```
127.0.0.1       dev.servicestack.com
```

Which will let you use the same `dev.servicestack.com` to access your local dev server in both Android Emulators and your Host OS 
so you can have a single domain & callback URL you can use in your OAuth Apps configuration.

## When developing for iOS

As iOS is a heavily locked down OS you wont have the same opportunity to modify iOS's hosts file, instead the easiest way to configure 
a custom address for a given domain is to configure it on the DNS Server. Fortunately this easy to setup in macOS with a 
[lightweight, easy to configure DNS Server like Dnsmasq](https://passingcuriosity.com/2013/dnsmasq-dev-osx/) which lets
you easily add custom DNS rules whilst falling back to use its default DNS resolution for non-configured addresses.

The easiest way to install Dnsmasq on macOS is to use [Homebrew](https://brew.sh):

:::sh
brew install dnsmasq
:::

Once installed copy over the default configuration files:

```bash
cp $(brew list dnsmasq | grep /dnsmasq.conf.example$) /usr/local/etc/dnsmasq.conf
sudo cp $(brew list dnsmasq | grep /homebrew.mxcl.dnsmasq.plist$) /Library/LaunchDaemons/
```

Then configure Dnsmasq to start automatically by registering it with **launchd**:

:::sh
sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.dnsmasq.plist
:::

The easiest to configure the IP Address for a single domain is to still add it to `/etc/hosts`, e.g. if your local ASP.NET
dev server is on a different server to your macOS being used to develop/test iOS Apps, you would use that IP Address instead:

```
192.168.0.2     dev.servicestack.com
```

Alternatively you can maintain these rules in Dnsmasq's config which offers far greater flexibility:

:::sh
sudo vi /usr/local/etc/dnsmasq.conf
:::

```
address=/dev.servicestack.com/192.168.0.2
```

In which case you'll also want to update the OS's resolver config to 
[query your local DNS Server when resolving these addresses](https://www.stevenrombauts.be/2018/01/use-dnsmasq-instead-of-etc-hosts/#2-only-send-test-and-box-queries-to-dnsmasq).

### Restart Dnsmasq to apply changes

After making changes to your DNS configuration, restart dnsmasq for it to take effect:

```bash
sudo launchctl stop homebrew.mxcl.dnsmasq
sudo launchctl start homebrew.mxcl.dnsmasq
```

### Update iOS to use your custom DNS Server

First find out the current IP Address of your macOS instance:

:::sh
ipconfig getifaddr en0
:::

Which you can get your iOS development device to use by going into your **Wi-Fi** Network Info in iOS **Settings**:

![](/img/pages/dev/ios-network-info.jpeg)

Going to **Configure DNS**:

![](/img/pages/dev/ios-wifi-info.png)

Then switching to use **Manual** DNS servers and adding your macOS IP Address where it will now be used to resolve DNS queries:

![](/img/pages/dev/ios-configure-dns.jpeg)

## Generating self-signed SSL Certificates for Custom Domains

Whether you use `local.servicestack.com` or `dev.servicestack.com` or your own hostname, you'll need to create and trust
a self-signed certificate to be able to view it in a browser without certificate errors.

To simplify creation of self-signed certificate for `*.servicestack.com` you can use the [dotnet mix tool](/mix-tool)
to download the openssl script and running it:

```bash
npx add-in gen-dev-crt.sh
bash gen-dev-crt.sh
```

Which will write this script below to your projects HOST project:

```csharp
PASSWORD=dev
if [ $# -ge 1 ]
  then
    PASSWORD=$1
fi

openssl req -x509 -out dev.crt -keyout dev.key -days 825 \
  -newkey rsa:2048 -nodes -sha256 \
  -subj '/CN=*.servicestack.com' -extensions EXT -config <( \
   printf "[dn]\nCN=*.servicestack.com\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:*.servicestack.com\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

openssl pkcs12 -export -out dev.pfx -inkey dev.key -in dev.crt -password pass:$PASSWORD
```

Which uses OpenSSL to generate a self-signed certificate `dev.crt`, private key `dev.key` and a PKCS #12 `dev.pfx` certificate in macOS, Linux & Windows using WSL.

### Trust self-signed certificate

After generating a new self-signed certificate you'll need to trust it in your OS's certificate store so it's recognized & treated as a valid certificate.

#### Windows

On Windows you can trust certificates by running the powershell command below in **Administrator** mode:

```
Import-Certificate -FilePath dev.crt -CertStoreLocation Cert:\CurrentUser\Root
```

Where it will import the Certificate into the [Current User Certificate Store](https://docs.microsoft.com/en-us/windows/win32/seccrypto/system-store-locations#cert_system_store_current_user)
which you can view/remove in **regedit.msc** at:

```
Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\SystemCertificates\Root\Certificates\
```

#### macOS

In macOS you can [add a trusted root certificate to your System.keychain](https://derflounder.wordpress.com/2011/03/13/adding-new-trusted-root-certificates-to-system-keychain/) with:

:::sh
sudo security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" dev.crt
:::

#### Linux

Unfortunately it's not as cohesive in Linux where different Distro's & Apps handle it differently, however this existing answer
covers [installation in Debian/Ubuntu distributions](https://unix.stackexchange.com/a/90607/698).

### Configure in .NET Core

You can configure the .NET Core to use this self-signed certificate during development by specifying the path to `dev.pfx` and the password used
in your `appsettings.Development.json`:

```json
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "https://*:5001",
        "Protocols": "Http1",
        "Certificate": {
          "Path": "dev.pfx",
          "Password": "dev"
        }
      }
  }
}
```

### Accessing from Browsers

Now after restarting your browser to reset its SSL caches you'll be able to use either `*.servicestack.com` domains to view your local development without SSL Errors:

![](/img/pages/security/dev-certs.png)

### Accessing from C# Clients

As .NET has access your OS's trusted certificates you'll be able to access the custom domains without additional configuration:

```csharp
var client = new JsonApiClient("https://dev.servicestack.com:5001"); //.NET HttpWebRequest
var response = await client.GetAsync(new Hello { Name = "World" });

var client = new JsonHttpClient("https://dev.servicestack.com:5001");    //.NET HttpClient
var response = await client.GetAsync(new Hello { Name = "World" });
```

### Accessing from Native Applications

Something you want to avoid is including your [certificate & private key with your Native application](https://letsencrypt.org/docs/certificates-for-localhost/#for-native-apps-talking-to-web-apps)
which is considered a compromise of your private key that attackers can use to implement a successful [MitM attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).

### Flutter Android

Instead you'll want to either [install the self-signed certificate](https://blog.netspi.com/four-ways-bypass-android-ssl-verification-certificate-pinning/) on your local
device/emulator where it wont be trusted by anyone else.

Otherwise a far easier solution is to ignore SSL certificates when accessing your local dev server which you can do with Dart/Flutter using the `HttpClient` 
[badCertificateCallback](https://api.flutter.dev/flutter/dart-io/HttpClient/badCertificateCallback.html) property:

```dart
var httpClient = new HttpClient()
    ..badCertificateCallback =
        ((X509Certificate cert, String host, int port) => host == 'dev.servicestack.com' && port == 5001);
```

Although ideally you'd use a constant value like [kDebugMode](https://api.flutter.dev/flutter/foundation/kDebugMode-constant.html) so that
the `badCertificateCallback` pass-through doesn't make it into production builds. Here's an example configuring a [ServiceStack Dart Service Client](/dart-add-servicestack-reference)
to use development or production APIs:

```dart
var client = kDebugMode
    ? ClientFactory.createWith(ClientOptions(baseUrl:'https://dev.servicestack.com:5001', ignoreCert:true))
    : ClientFactory.create('https://prod.app');

var response = await client.get(Hello()..name=='World');
```

### Removing Certificate Artifacts

If you're only using Windows you'll typically only end up using the PKCS #12 `dev.pfx` certificate combining both certificate & private key 
which can be safely removed to clear unnecessary generated artifacts & clear-text copy of the private key:

```bash
del dev.key
del dev.crt
```

Where as other OS's predominantly use Certificates & Private Keys, which if needed can be later extracted from the `dev.pfx`:

#### Extract Certificate

:::sh
openssl pkcs12 -in dev.pfx -clcerts -nokeys -out dev.crt
:::

#### Extract Private Key

:::sh
openssl pkcs12 -in dev.pfx -nocerts -nodes | openssl rsa -out dev.key
:::