Kratos + selfservice node domain-dependent redirect loop

Hello! I’m using development setup with self-generated root certificate and lots of domain certificates generated on top of it. So I almost never use port in favour of domain names which is not so far from producition environment.

On top of all docker services I have traefik which is set up to forward:
https ://api.kratos.local -> http ://kratos:4433
https ://admin.kratos.local -> http ://kratos:4434
https ://ui.kratos.local -> http ://secured-app # self service ui node

With next config ui-node works like a charm:

environment:
KRATOS_PUBLIC_URL: http ://kratos:4433/
KRATOS_ADMIN_URL: http ://kratos:4434/
PORT: 80
SECURITY_MODE: cookie
labels:
traefik.enable: true
traefik.frontend.rule: “Host: ui.kratos.local”
traefik.port: ‘80’
traefik.protocol: ‘http’
traefik.frontend.headers.SSLRedirect: true

Notice that they are on different domains! ui-node is https://ui.kratos.local and kratos-api is just http://kratos:4433. And it does work nicely. I’ve read “common cookie and csrf pitfails” and actually do not understand how that info affects my configuration - as for me there is no difference in domains because anyway ui-node should just re-assemble all requests and send them to kratos.

When I set ui-node to interact with kratos by it’s own domain with https:

environment:
  KRATOS_PUBLIC_URL: https://api.kratos.local/
  KRATOS_ADMIN_URL: https://admin.kratos.local/
  PORT: 80
  SECURITY_MODE: cookie
  NODE_EXTRA_CA_CERTS: /usr/local/share/ca-certificates/internalone.ca.crt
volumes:
  - '../../certificates/ca.crt:/usr/local/share/ca-certificates/internalone.ca.crt:ro'
networks:
  - traefik
external_links:
  - traefik:api.kratos.local
  - traefik:admin.kratos.local

I encounter redirect loop. I can’t understand what causes it. Both configurations have kratos and app on different domain. And only one of them is working as expected.

Here is diff of docker (stdout) logs:

I can’t attach a diff of HAR request fragments from a browser debugger due to limitations for ne users. It contains strange data but it does not seem to be fery useful.
The latest response is just a redirect to ‘/auth/login’ while for the working config it is 200 with HTML response body. The preceding request diff is much more interesting - they are both identical redirects but the failing one has zero content size. The content itself is not visible for both cases in HAR exported from Firefox so it’s not very useful or I don’t understand it.

So inspecting requests does not seem to give any useful results. Looping redirects are just happening in one case and do not happen in the other one.

Maybe I can’t get some kind of a simple reason why it can’t work at all?

Sorry guys it seems like I’ve misconfigured Traefik. When I query api.kratos.local with curl - kratos prints to stdout that request was to ui.kratos.local.

I’ll try to fix that first and then will report results.

Hm… No, traefik is okay. If I try the next request from inside of ui-node container:

curl kratos:4433
curl https ://api.kratos.local

That’s what kratos prints to stdout:

kratos | time=2020-07-11T09:55:02Z level=info msg=started handling request method=GET name=public#https://ui.kratos.local/.ory/kratos/public/ remote=172.20.0.17:49168 request=/
kratos | time=2020-07-11T09:55:02Z level=info msg=completed handling request method=GET name=public#https://ui.kratos.local/.ory/kratos/public/ remote=172.20.0.17:49168 request=/ status=404 text_status=Not Found took=63.98µs

kratos | time=2020-07-11T09:55:27Z level=info msg=started handling request method=GET name=public#https ://ui.kratos.local/.ory/kratos/public/ remote=172.20.0.17 request=/
kratos | time=2020-07-11T09:55:27Z level=info msg=completed handling request method=GET name=public#https ://ui.kratos.local/.ory/kratos/public/ remote=172.20.0.17 request=/ status=404 text_status=Not Found took=89.513µs

Oh, I’ve got it. It seems like a bug in kratos-selfservice-ui-node.
And it looks like it’s common for nodejs apps due to wrong documentation.

You can not “just pipe” an http request. You have to change “Host” header because actually it was added exactly for HTTP server to determine the virtualhost where single destination could have multiple virtualhosts.

That broken request worked fine for me in nginx but it’s only because nginx does’nt know about all the hosts which traefik knows about in my environment config.

I’ll experiment alittle more with nginx and then post an issue.

Fixed https://github.com/ory/kratos-selfservice-ui-node/issues/60