DEV Community

Cover image for Help! Next.js + next-auth + keycloak + docker-compose
Cristhian García Vélez
Cristhian García Vélez

Posted on

Help! Next.js + next-auth + keycloak + docker-compose

I am using Next.js + next-auth + keycloak with docker-compose.

Everything 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 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-proxy        | 172.23.0.1 - - [17/Feb/2022:03:51:02 +0000] "POST /api/auth/signin/keycloak HTTP/1.1" 302 5 "http://project.test/api/auth/signin?callbackUrl=http%3A%2F%2Fproject.test%2F" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36" "-"
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://project.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://project.test/auth/realms/myrealm',
arcade-iori         |     authorizationUrl: 'http://project.test/auth/realms/myrealm/protocol/openid-connect/auth',
arcade-iori         |     accessTokenUrl: 'http://project.test/auth/realms/myrealm/protocol/openid-connect/token',
arcade-iori         |     profileUrl: 'http://project.test/auth/realms/myrealm/protocol/openid-connect/userinfo',
arcade-iori         |     signinUrl: 'http://project.test/api/auth/signin/keycloak',
arcade-iori         |     callbackUrl: 'http://project.test/api/auth/callback/keycloak'
arcade-iori         |   },
arcade-iori         |   message: 'connect ECONNREFUSED 127.0.0.1:80'
arcade-iori         | }
arcade-proxy        | 172.23.0.1 - - [17/Feb/2022:03:51:02 +0000] "GET /api/auth/error?error=OAuthSignin HTTP/1.1" 302 5 "http://project.test/api/auth/signin?callbackUrl=http%3A%2F%2Fproject.test%2F" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36" "-"
Enter fullscreen mode Exit fullscreen mode

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://project.test/auth/realms/myrealm',
      authorizationUrl: "http://project.test/auth/realms/myrealm/protocol/openid-connect/auth",
      accessTokenUrl: "http://project.test/auth/realms/myrealm/protocol/openid-connect/token",
      profileUrl: "http://project.test/auth/realms/myrealm/protocol/openid-connect/userinfo",
    })
  ],
})
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

This is the default-proxy.conf:

server {
    listen       80;
    listen  [::]:80;
    server_name  project.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;
    }
}
Enter fullscreen mode Exit fullscreen mode

host file:

127.0.0.1 project.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.

Top comments (4)

Collapse
 
wireless25 profile image
Stephan Simonett

Did you find a solution? I have the same problem, it seems for the server-side request, you need to use the internal container name, but then the same URL is also used in the client to do the redirects to Keycloak. I search for a solution to have 2 URLs for Keycloak, one for the server and one for the client. But so far, I was not able to solve it.

Collapse
 
ozdemirrulass profile image
Ulaş Özdemir
Collapse
 
crisgarlez profile image
Cristhian García Vélez

For my local development environment this was my solution:

github.com/nextauthjs/next-auth/is...

Collapse
 
ozdemirrulass profile image
Ulaş Özdemir

ulasozdemir.com.tr/enterprise-leve...

If anyone still having this problem here is a step by step guide + repository