Develop against a remote instance of Ory Kratos from localhost

Ory Kratos uses secure cookies, which cannot travel across domains. This can become a problem when testing an app on localhost against a remote instance of Ory Kratos. Here is, what you can do.

Develop against a remote instance of Ory Kratos from localhost

Ory Kratos is a great and open-source identity provider with a strong focus on security. For its self-service flows like Login or Registration, it uses secure cookies, which cannot travel across domains. This can become a problem when testing an app on localhost against a remote instance of Ory Kratos on a different domain. Here is, what you can do.

Let's assume, that your application is hosted on myapp.com and Ory Kratos is hosted on auth.myapp.com. Then the config for Kratos probably contains ui_urls pointing to myapp.com like in the example below.

selfservice:
  flows:
    login:
      ui_url: https://myapp.com/login
      
 # ...
Extract from kratos.yaml, a configuration file for Ory Kratos

This means, that even when kicking-off the login self-service flow, Kratos will re-direct to the public myapp.com app instead of yours which is running on localhost.

You have two options to develop against Ory Kratos from localhost:

  1. Run a local version of Ory Kratos running in a container with a different configuration that points to localhost instead of myapp.com (not covered in this post)
  2. Trick your local web server into assuming to host from myapp.com instead of localhost and modify your DNS entries (read along to learn how)

Override your app's domain with localhost

First, we need to modify DNS on our development machines in a way, that whenever we navigate to myapp.com, it gets resolved to our local machine instead of the actual app hosted on a public IP address in the cloud.

The easiest way to achieve this, is to add the following line to your etc/hosts file:

# Use local version of myapp.com for development
127.0.0.1 myapp.com
Extract from /etc/hosts

This ensures, that once Ory Kratos redirects to https://myapp.com/login for the login self-service flow for example, your browser will serve from the instance of your app that is running locally.

Secure localhost with SSL and serve it on port 443

We also need to make sure, that we are not leaving SSL land when using the local instance of our app. For this, we need to make sure, is uses HTTPS and gets exposed on the same port your production app is running on (usually  443).

Next, we will need a certificate for your domain that can be served by the local web server. Install mkcert on your machine and run the following commands from the root directory of your web app.

# Install mkcert
mkcert -install

# Create .cert directory if it doesn't exist
mkdir -p .cert

# Generate a certificate for localhost
mkcert -key-file ./.cert/key.pem -cert-file ./.cert/cert.pem "localhost"
Warning: Don't check-in these certificates into your version control, as they contain confidential information.

Now we have to configure the local web server to use myapp.com instead of localhost as its host and use the same port as our production app (usually  443).

Example: React

Here you can find an example for React. For other technologies there are similar concepts available.

In React, you can instruct the local web server by creating a file called .env.development in the root folder of your app. In there, we can instruct the web server to serve on our domain instead of localhost and use the certificates that we have just created.

HOST=myapp.com
PORT=443
HTTPS=true 
SSL_CRT_FILE=.cert/cert.pem 
SSL_KEY_FILE=.cert/key.pem
.env.development 

When running yarn start now, your browser will open on myapp.com but serve the locally running version of your app.

Cleanup

Don't forget to remove the line from the /etc/hosts file after development, to be able to visit the actual myapp.com website again.