Using Ory Proxy
Ory Proxy is a powerful tool which authenticates users, converts session into a JSON Web Token, and ensures that cookies and URLs are properly configured.
The Ory Proxy is an alternative to custom domains (CNAME), and a useful helper when developing locally. For production, we recommend using our Custom Domain feature where possible.
If you haven't already, please install the Ory CLI on your development machine or server.
Concepts
Before heading into the concrete examples, let's look at some of Ory Proxy's concepts.
URL Structure
Ory Proxy mirrors Ory Cloud's APIs and UIs under the /.ory
path. If you were
to call, for example, the URL
https://<your-project-slug>.projects.oryapis.com/ui/login
, the equivalent
proxied URL would be https://<proxy-host>/.ory/ui/login
.
Ory Proxy has shorthand URLs which you can use to initiate self-service flows:
/.ory/self-service/login/browser
initiates the self-service login flow./.ory/self-service/registration/browser
initiates the self-service registration flow./.ory/self-service/recovery/browser
initiates the self-service recovery flow./.ory/self-service/verification/browser
initiates the self-service verification flow./.ory/self-service/settings/browser
initiates the self-service settings flow.
If you redirect or link the user to one of those paths, the login, registration, ... flow will be initiated:
<a href="/.ory/self-service/login/browser">Log in</a>
You can also append a return_to
query parameter so that the user ends up at
that URL. Please keep in mind that the domain MUST be an allow-listed URL in the
Ory Cloud Project configuration!
The return_to URL must include the protocol and domain! Relative URLs aren't possible.
<a
href="/.ory/self-service/login/browser?return_to=https://localhost:4000/my-url"
>Log in</a
>
Zero Trust
Ory Proxy translates any known Ory credentials (for example an Ory Session Token or Ory Session Cookie) to a JSON Web Token. Assuming the user calls Ory Proxy with a valid Ory Session Cookie
GET /some-path
Host: localhost:4000
Cookie: ory_session_jollyproskuriakovaxe98qw5t8g=MTYyNzU1OTgyNHxEdi1CQkFFQ180SUFBUkFCRUFBQVJfLUNBQUVHYzNSeWFXNW5EQThBRFhObGMzTnBiMjVmZEc5clpXNEdjM1J5YVc1bkRDSUFJR3RGU1d4dlUwOXVSR2w1UjJONmFVRlhaWEIxWVhCVlNHWlZOVTQxWWtGMnwhbFZh8BCCQ3tMemDczrB9-epefXl1E7whiChUt62LuA==
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36
...
Ory Proxy resolves that session and converts it to a JSON Web Token which is
included in the HTTP Request's Authorization
Header which is made to the
"upstream" (the URL which Ory Proxy is protecting). The session cookie will
still be included in the request, in case that you need it to generate a logout
URL for example.
GET /some-path
Host: <your-application>:3000
Authorization: eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Mjc1NjAxMjQsImlhdCI6MTYyNzU2MDA2NCwiaXNzIjoiaHR0cHM6Ly9qb2xseS1wcm9za3VyaWFrb3ZhLXhlOThxdzV0OGcucHJvamVjdHMub3J5YXBpcy5jb20iLCJqdGkiOiJlYWFlYzI0My0yY2IwLTQ2OGEtYmViZS0xYTAzNDkyNDJjZjAiLCJuYmYiOjE2Mjc1NjAwNjQsInNlc3Npb24iOnsiaWQiOiJiNzNkN2RjNC1mNTY1LTRmZWEtOTUxZS04YzIzZWUwNTc4M2YiLCJhY3RpdmUiOnRydWUsImV4cGlyZXNfYXQiOiIyMDIxLTA3LTMwVDEyOjAxOjAyLjk2NjYzWiIsImF1dGhlbnRpY2F0ZWRfYXQiOiIyMDIxLTA3LTI5VDEyOjAxOjAzLjAyNDM2NVoiLCJpc3N1ZWRfYXQiOiIyMDIxLTA3LTI5VDEyOjAxOjAyLjk2NjY1MloiLCJpZGVudGl0eSI6eyJpZCI6IjBmMGM5YmVjLTZiNjgtNDdmMy1iNjJiLTc3NTBmMDY1MzU5YyIsInNjaGVtYV9pZCI6ImRlZmF1bHQiLCJzY2hlbWFfdXJsIjoiaHR0cHM6Ly9qb2xseS1wcm9za3VyaWFrb3ZhLXhlOThxdzV0OGcucHJvamVjdHMub3J5YXBpcy5jb20vYXBpL2tyYXRvcy9wdWJsaWMvc2NoZW1hcy9kZWZhdWx0Iiwic3RhdGUiOiJhY3RpdmUiLCJzdGF0ZV9jaGFuZ2VkX2F0IjoiMjAyMS0wNy0yOVQxMjowMTowMi44NDQ0NzJaIiwidHJhaXRzIjp7ImVtYWlsIjoiZGV2K2RvY3NAb3J5LnNoIiwiZmlyc3RuYW1lIjoiT3J5IERvY3MiLCJ2ZWdldGVyaWFuIjp0cnVlfSwidmVyaWZpYWJsZV9hZGRyZXNzZXMiOlt7ImlkIjoiNjRiM2YyNzAtNzBmYy00OGI4LTg3MDQtODA4NWM3ODMzNjJiIiwidmFsdWUiOiJkZXYrZG9jc0Bvcnkuc2giLCJ2ZXJpZmllZCI6ZmFsc2UsInZpYSI6ImVtYWlsIiwic3RhdHVzIjoic2VudCIsInZlcmlmaWVkX2F0IjpudWxsLCJjcmVhdGVkX2F0IjoiMjAyMS0wNy0yOVQxMjowMTowMi44ODg1NjJaIiwidXBkYXRlZF9hdCI6IjIwMjEtMDctMjlUMTI6MDE6MDIuODg4NTYyWiJ9XSwicmVjb3ZlcnlfYWRkcmVzc2VzIjpbeyJpZCI6IjUyNmEyYjI1LTJiOWEtNDQ1Yi05ODJkLTk3ODYyZDliYmM5YiIsInZhbHVlIjoiZGV2K2RvY3NAb3J5LnNoIiwidmlhIjoiZW1haWwiLCJjcmVhdGVkX2F0IjoiMjAyMS0wNy0yOVQxMjowMTowMi44OTc0MDdaIiwidXBkYXRlZF9hdCI6IjIwMjEtMDctMjlUMTI6MDE6MDIuODk3NDA3WiJ9XSwiY3JlYXRlZF9hdCI6IjIwMjEtMDctMjlUMTI6MDE6MDIuODc3NDE3WiIsInVwZGF0ZWRfYXQiOiIyMDIxLTA3LTI5VDEyOjAxOjAyLjg3NzQxN1oifX0sInN1YiI6IjBmMGM5YmVjLTZiNjgtNDdmMy1iNjJiLTc3NTBmMDY1MzU5YyJ9.6vvdyNkNce39W8WPKwF5QUTOlBjF5VW6Xl3QzYHU9M1riiDVgQ4rK8XHEqcjhAQcis8EIbRm7K0UuLNGwKsKzQ",
Cookie: ory_session_jollyproskuriakovaxe98qw5t8g=MTYyNzU1OTgyNHxEdi1CQkFFQ180SUFBUkFCRUFBQVJfLUNBQUVHYzNSeWFXNW5EQThBRFhObGMzTnBiMjVmZEc5clpXNEdjM1J5YVc1bkRDSUFJR3RGU1d4dlUwOXVSR2w1UjJONmFVRlhaWEIxWVhCVlNHWlZOVTQxWWtGMnwhbFZh8BCCQ3tMemDczrB9-epefXl1E7whiChUt62LuA==
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36
...
We strongly encourage you to validate the JSON Web Token using Ory Proxy's
public key. The public key is available at /.ory/proxy/jwks.json
:
curl -sk https://<proxy-host>/.ory/proxy/jwks.json | jq
{
"keys": [
{
"use": "sig",
"kty": "EC",
"kid": "f8f2e6ff-0480-4343-9dee-0d2a463146dc",
"crv": "P-256",
"alg": "ES256",
"x": "Say2LSWvHxUnyxuW5lxsTFkKopZq402eH4YqcRiBgvA",
"y": "7XaYgYsW-Mjb5qIq47LxyaPHjPZfRHRnnfir8aqd9BU"
}
]
}
Using the public key, you can validate and decode the JSON Web Token, which includes all the session and identity information linked to the Ory Session Cookie:
{
"exp": 1627560124,
"iat": 1627560064,
"iss": "https://<project-slug>.projects.oryapis.com",
"jti": "eaaec243-2cb0-468a-bebe-1a0349242cf0",
"nbf": 1627560064,
"session": {
"id": "b73d7dc4-f565-4fea-951e-8c23ee05783f",
"active": true,
"expires_at": "2021-07-30T12:01:02.96663Z",
"authenticated_at": "2021-07-29T12:01:03.024365Z",
"issued_at": "2021-07-29T12:01:02.966652Z",
"identity": {
"id": "0f0c9bec-6b68-47f3-b62b-7750f065359c",
"schema_id": "default",
"schema_url": "https://<project-slug>.projects.oryapis.com/api/kratos/public/schemas/default",
"state": "active",
"state_changed_at": "2021-07-29T12:01:02.844472Z",
"traits": {
"email": "dev+docs@ory.sh",
"firstname": "Ory Docs",
"vegeterian": true
},
"verifiable_addresses": [
{
"id": "64b3f270-70fc-48b8-8704-8085c783362b",
"value": "dev+docs@ory.sh",
"verified": false,
"via": "email",
"status": "sent",
"verified_at": null,
"created_at": "2021-07-29T12:01:02.888562Z",
"updated_at": "2021-07-29T12:01:02.888562Z"
}
],
"recovery_addresses": [
{
"id": "526a2b25-2b9a-445b-982d-97862d9bbc9b",
"value": "dev+docs@ory.sh",
"via": "email",
"created_at": "2021-07-29T12:01:02.897407Z",
"updated_at": "2021-07-29T12:01:02.897407Z"
}
],
"created_at": "2021-07-29T12:01:02.877417Z",
"updated_at": "2021-07-29T12:01:02.877417Z"
}
},
"sub": "0f0c9bec-6b68-47f3-b62b-7750f065359c"
}
Ory Proxy for Local Development
Before you start set the environment variable
ORY_SDK_URL
. It can be found in the
"API & Services" section of your Ory Cloud Console.
Ory Proxy works great on local machines (localhost
). Assuming you are running,
for example, a NodeJS app on port 3000, you would point Ory Proxy to that URL:
export ORY_SDK_URL=https://<project>.projects.oryapis.com/
ory proxy http://localhost:3000
For more information on other CLI flags run ory help proxy
or head over to the
Ory Proxy Local Reference.
Ory Proxy for Production
Ory Proxy is also capable of protecting remote and production environments. Alternatively you can also use DNS CNAME. The only difference to running the proxy locally, is that you append the root URL where your app (via Ory Proxy) is exposed at:
export ORY_SDK_URL=https://<project>.projects.oryapis.com/
ory proxy http://localhost:3000 https://my-domain.com
For other CLI flags which, for example, disable the auto-opening of the URL in
the browser, run ory help proxy
or head over to the
Ory Proxy Production Reference.
Running on a VM
If you are deploying on a VM, Virtual or Dedicated Server using Ory Proxy is easy! Just run your application server and the proxy in parallel. Assuming you are using NodeJS to run your server on port 3000, and are exposing web traffic at port 8080, use:
ory proxy --port 8080 http://127.0.0.1:3000 https://your-domain.com &
# This should be your server command
node your-entrypoint.js
# Could also be something like:
# go run main.go
# php index.php
# ...
Running in Docker
One option is to add both Ory Proxy and your service to a Docker container.
warning
Running two processes in one Docker Container is problematic as Docker will only watch the process running in the foreground. If the process in the background crashes, Docker won't be notified. To get a more stable system in place, please follow Run multiple services in a container.
For simplicity we've chosen to run Ory Proxy as a background task here!
To run Ory Proxy alongside your application, create a file called
entrypoint.sh
with a content along the lines of:
#!/bin/bash
set -e
# This assumes that your server is running on port 3000. If it's running on a different port,
# change the `3000` to the port where your server is running at!
ory proxy --port 8080 http://127.0.0.1:3000 https://your-domain.com &
# This should be your server command
node your-entrypoint.js
# Could also be something like:
# go run main.go
# php index.php
# ...
Then, add the script to your Dockerfile and run it:
# ...
EXPOSE 8080
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
Kubernetes
Adding a Helm Chart for Ory Proxy is on the roadmap, which would allow running Ory Proxy either as a Service, Ingress, or Side Car!
Troubleshooting
If you run get an error while working with Ory Proxy or Ory CLI , make sure you are on the latest version.
- For
brew (MacOs)
use
brew upgrade ory/tap/cli
, - For
scoop (Win)
use
scoop update ory
to update to the latest version. The Ory CLI will autoupdate in the near future.