next-auth: NEXTAUTH_URL_INTERNAL variable does not work with keycloak

Provider type

Keycloak

Environment

System: OS: Windows 10 10.0.19043 CPU: (8) x64 Intel® Core™ i7-4700MQ CPU @ 2.40GHz Memory: 3.30 GB / 15.76 GB Binaries: Node: 16.13.1 - C:\laragon\bin\nodejs\node-v16.13.1\node.EXE Yarn: 1.22.11 - ~\AppData\Roaming\npm\yarn.CMD npm: 8.3.2 - C:\laragon\bin\nodejs\node-v16.13.1\npm.CMD Browsers: Edge: Spartan (44.19041.1266.0), Chromium (98.0.1108.55) Internet Explorer: 11.0.19041.1202 npmPackages: next: 12.0.7 => 12.0.7 next-auth: ^4.0.6 => 4.0.6 react: 17.0.2 => 17.0.2

Reproduction URL

https://github.com/nextauthjs/next-auth-example

Describe the issue

I am using Next-auth with keycloak and docker-compose.

Everything works fine on my local computer, but when I use docker-compose i get this error:

arcade-iori         | [next-auth][error][GET_AUTHORIZATION_URL_ERROR]
arcade-iori         | https://next-auth.js.org/errors#get_authorization_url_error connect ECONNREFUSED 127.0.0.1:80 {
arcade-iori         |   message: 'connect ECONNREFUSED 127.0.0.1:80',
arcade-iori         |   stack: 'Error: connect ECONNREFUSED 127.0.0.1:80\n' +
arcade-iori         |     '    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1157:16)',
arcade-iori         |   name: 'Error'
arcade-iori         | }
arcade-iori         | [next-auth][error][SIGNIN_OAUTH_ERROR]
arcade-iori         | https://next-auth.js.org/errors#signin_oauth_error connect ECONNREFUSED 127.0.0.1:80 {
arcade-iori         |   error: {
arcade-iori         |     message: 'connect ECONNREFUSED 127.0.0.1:80',
arcade-iori         |     stack: 'Error: connect ECONNREFUSED 127.0.0.1:80\n' +
arcade-iori         |       '    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1157:16)',
arcade-iori         |     name: 'Error'
arcade-iori         |   },
arcade-iori         |   provider: {
arcade-iori         |     id: 'keycloak',
arcade-iori         |     name: 'Keycloak',
arcade-iori         |     wellKnown: 'http://abianic.test/auth/realms/myrealm/.well-known/openid-configuration',
arcade-iori         |     type: 'oauth',
arcade-iori         |     authorization: { params: [Object] },
arcade-iori         |     checks: [ 'pkce', 'state' ],
arcade-iori         |     idToken: true,
arcade-iori         |     profile: [Function: profile],
arcade-iori         |     clientId: 'myclientnext',
arcade-iori         |     clientSecret: 'Pw6ffETQgR5VLeXKL3v5jIsTjkNyvvCA',
arcade-iori         |     issuer: 'http://abianic.test/auth/realms/myrealm',
arcade-iori         |     signinUrl: 'http://abianic.test/api/auth/signin/keycloak',
arcade-iori         |     callbackUrl: 'http://abianic.test/api/auth/callback/keycloak'
arcade-iori         |   },
arcade-iori         |   message: 'connect ECONNREFUSED 127.0.0.1:80'
arcade-iori         | }

How to reproduce

This is the Next-auth config:

import NextAuth from "next-auth"
import KeycloakProvider from "next-auth/providers/keycloak";


export default NextAuth({
  debug: true,
  secret: process.env.SECRET,
  site: process.env.NEXTAUTH_URL,
  providers: [
    KeycloakProvider({
      clientId: 'myclientnext',
      clientSecret: 'Pw6ffETQgR5VLeXKL3v5jIsTjkNyvvCA...',
      issuer: 'http://abianic.test/auth/realms/myrealm',
      authorizationUrl: "http://abianic.test/auth/realms/myrealm/protocol/openid-connect/auth",
      accessTokenUrl: "http://abianic.test/auth/realms/myrealm/protocol/openid-connect/token",
      profileUrl: "http://abianic.test/auth/realms/myrealm/protocol/openid-connect/userinfo",
    })
  ],
})

This is my docker-compose.yml:

version: '3.7'

volumes:
  keycloak_db_data:
      driver: local

networks:
  arcadenet:
    driver: bridge

services:

  keycloak-db:
    image: postgres:11.2
    container_name: arcade-keycloak-db
    volumes:
      - keycloak_db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: arcadecloack
      POSTGRES_USER: arcade
      POSTGRES_PASSWORD: arcade
    networks:
      - arcadenet

  keycloak:
    image: quay.io/keycloak/keycloak:16.1.0
    container_name: arcade-keycloak
    environment:
      DB_VENDOR: POSTGRES
      DB_ADDR: arcade-keycloak-db
      DB_DATABASE: arcadecloack
      DB_USER: arcade
      DB_SCHEMA: public
      DB_PASSWORD: arcade
      KEYCLOAK_USER: admin4
      KEYCLOAK_PASSWORD: admin
      PROXY_ADDRESS_FORWARDING: true
      # Uncomment the line below if you want to specify JDBC parameters. The parameter below is just an example, and it shouldn't be used in production without knowledge. It is highly recommended that you read the PostgreSQL JDBC driver documentation in order to use it.
      #JDBC_PARAMS: "ssl=true"
    ports:
      - 8080:8080
    depends_on:
      - keycloak-db
    networks:
      - arcadenet

  iori:
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    build:
        context: ../iori/
        dockerfile: Dockerfile
    image: iori
    container_name: arcade-iori
    restart: always
    ports:
      - 3000:3000
    volumes:
      - '../iori/:/app'
      - '/app/node_modules'
      - '/app/.next'
    environment:
      - CHOKIDAR_USEPOLLING=true
    networks:
      - arcadenet

  proxy:
    image: nginx
    container_name: arcade-proxy
    restart: unless-stopped
    ports:
      - 80:80
    volumes:
      - ./default-proxy.conf:/etc/nginx/conf.d/default.conf:ro
    networks:
      - arcadenet
    depends_on:
      - keycloak
      - iori

the env.local file:

NEXTAUTH_URL=http://abianic.test/
NEXTAUTH_URL_INTERNAL=http://arcade-iori:3000/
NEXTAUTH_SECRET=asd

This is the default-proxy.conf:

server {
    listen       80;
    listen  [::]:80;
    server_name  abianic.test;

    location /keycloak/ {
        proxy_pass          http://arcade-keycloak:8080/;
        proxy_set_header    Host               $host;
        proxy_set_header    X-Real-IP          $remote_addr;
        proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Host   $host;
        proxy_set_header    X-Forwarded-Server $host;
        proxy_set_header    X-Forwarded-Port   $server_port;
        proxy_set_header    X-Forwarded-Proto  $scheme;
    }


    location /auth/ {
        proxy_pass          http://arcade-keycloak:8080/auth/;
        proxy_set_header    Host               $host;
        proxy_set_header    X-Real-IP          $remote_addr;
        proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Host   $host;
        proxy_set_header    X-Forwarded-Server $host;
        proxy_set_header    X-Forwarded-Port   $server_port;
        proxy_set_header    X-Forwarded-Proto  $scheme;
    }

    location / {

        proxy_pass http://arcade-iori:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;

    }

    # requests without trailing slash will be forwarded to include slash
    location = /backend {
        return 301 $scheme://$http_host$uri/$is_args$args;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

host file:

127.0.0.1 abianic.test

I think the problem is that if it’s running in a Docker container then http://127.0.0.1:80 from the perspective of the Docker container is diferebt on each container, but I don’t have “localhost/127.0.0.1” configured anywhere.

Expected behavior

verything works fine when I run the Next.js project on my local computer (http://localhost:3000/), but when I use docker-compose to run the project in a container I get the error

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (5 by maintainers)

Most upvoted comments

I think this should still be fixed at some point. Not being able to test OAuth with a local Docker deployment of every container is really annoying. Especially when you are used to running everything in containers and don’t want to get everything installed.

I think it would be nice to allow (in the OAuth Interface itself) a parameter that works analogous to NEXTAUTH_URL_INTERNAL. So just some value that is used to parse the origin (scheme, domain, and most importantly port!), which is then used in every server side request.

If there are any downsides, please do let me know.

I notice the same problem, but none of the workaround are applicable. The point is that the browser can access the Keycloak server at the same base address as my application (eg.: https://127.0.0.1 ), but the server should point to a named container, with even a different protocol (eg.: http://mykeycloak; notice the http, instead of https). The NEXTAUTH_URL_INTERNAL variable seems just to be ignored.

Yeah so the main issue here is that 127.0.0.1 is referring to different things from the perspective of each container / the host, right?

Some possible solutions / workarounds include:

  • If you’re using docker on mac, you can always refer to the host with the hostname host.docker.internal
  • You could use host networking (i.e. the --network host flag)
  • You could set some additional hostnames in your /etc/hosts file, as has already been suggested here
  • Docker containers, amongst one another in a docker-compose setup, automatically get /etc/hosts entries for each other container based on the continer names. So like a hypothetical app container automatically has a hostname setup for the db container (for example), so to link to postgres instance running in the db container, you could just point it at db:5432.

I’ll close this issue for now as we seem to have identified the root cause of the issue and others have provided some solutions. It’s not really a next-auth code related issue, but rather a configuration error related to container networking.

Hey! Do you have any news on this topic? I’m currently experimenting with the same issue with docker

my solution was to put a new entry in host file:

127.0.0.1      abianic.test
127.0.0.1      arcade-proxy

And point the […nextauth].js file to the url with the keycloak container name:

import NextAuth from "next-auth"
import KeycloakProvider from "next-auth/providers/keycloak";


export default NextAuth({
  debug: true,
  secret: process.env.NEXTAUTH_SECRET,
  site: process.env.NEXTAUTH_URL,
  providers: [
    KeycloakProvider({
      clientId: process.env.KEYCLOAK_ID,
      clientSecret: process.env.KEYCLOAK_SECRET,
      issuer: process.env.KEYCLOAK_ISSUER,
      authorizationUrl: "http://arcade-proxy/auth/realms/myrealm/protocol/openid-connect/auth",
      accessTokenUrl: "http://arcade-proxy/auth/realms/myrealm/protocol/openid-connect/token",
      profileUrl: "http://arcade-proxy/auth/realms/myrealm/protocol/openid-connect/userinfo",
      wellKnown: "http://arcade-proxy/auth/realms/myrealm/.well-known/openid-configuration",
    })
  ],
})

Hey! Do you have any news on this topic? I’m currently experimenting with the same issue with docker