Skip to content

SSO / OIDC with Keycloak returns Errors #108

@reniko

Description

@reniko

Describe the bug
After configuring keycloak, login with keycloak is not working.

To Reproduce
Steps to reproduce the behavior:

  1. Configure Keycloak SSO as described in https://portabase.io/docs/dashboard/installation/auth/oidc/examples/keycloak
  2. In login screen click on SSO button
  3. Get error message "An error occurred while signing in with the provider. Please try again."

Expected behavior
Login with SSO successful.

Screenshots
Image

Desktop (please complete the following information):

  • OS: Windows 11
  • Browser [edge or Firefox]
  • Version [145.0.3800.70 (edge) or 148.0 (Firefox ]

Additional context
Keycloak in general is working for that real (with other clients of course).

Local user/password authentication is working.

No error messages in container logs

From developer options (in Chrome/Firefox under Windows 11) I get an HTTP 400 after clicking on SSO Button when calling https://portabase.example.com/api/auth/sign-in/sso

.env:

POSTGRES_DB=portabase
POSTGRES_USER=portabase
PROJECT_NAME=Portabase
RETENTION_CRON="0 7 * * *"

# --- App Configuration ---
PROJECT_URL=https://portabase.example.com
PROJECT_SECRET=<some random string>

# --- Database URL ---
POSTGRES_USER=portabase
POSTGRES_PASSWORD=<some secret password>
POSTGRES_HOST=db
POSTGRES_PORT=5432
POSTGRES_DB=portabase

# Identifier and Title
AUTH_OIDC_ID="sso"
AUTH_OIDC_TITLE="SSO"
AUTH_OIDC_DESC=""
AUTH_OIDC_ICON=""
# OIDC Credentials
AUTH_OIDC_CLIENT="portabase"
AUTH_OIDC_SECRET="<secret from keycloak>"
AUTH_OIDC_ISSUER_URL="https://auth.example.com/realms/<myRealm>"
#AUTH_OIDC_HOST="auth.example.com" #makes no difference if set
# Advanced Settings
AUTH_OIDC_SCOPES="openid profile email"
#AUTH_OIDC_PKCE=true  #makes no difference if set
# Role Mapping
#AUTH_OIDC_ROLE_MAP="admin:admin,default:pending"

AUTH_EMAIL_PASSWORD_ENABLED=true
AUTH_SIGNUP_ENABLED=true
AUTH_PASSKEY_ENABLED=false
AUTH_SYNC_OIDC_ROLES_ON_LOGIN=true

compose.yaml:

name: portabase

services:
  db:
    image: postgres:17.9-alpine3.23
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      TZ: ${TZ}
    volumes:
      - /opt/data/portabase/db:/var/lib/postgresql/data
    networks:
      - portabase
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
    security_opt:
      - no-new-privileges:true
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  app:
    image: portabase/portabase:1.4.2
    restart: unless-stopped
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?schema=public=value
    depends_on:
      db:
        condition: service_healthy
    volumes:
      - /opt/data/portabase/data:/data
    networks:
      - portabase
      - pangolin
    healthcheck:
      test: ["CMD", "wget", "-O", "-", "http://localhost"]
      interval: 30s
      timeout: 5s
      retries: 5
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

networks:
  portabase:
    name: portabase
    enable_ipv6: true
  pangolin:
    name: pangolin
    external: true

Some informations from inside the app container:

root@b24a0e58160b:/app# env | grep AUTH_OIDC_ID
AUTH_OIDC_ID=sso

nginx error.log empty

nginx access.log:
172.20.0.6 - - [02/Mar/2026:13:58:36 +0100] "POST /api/auth/sign-in/sso HTTP/1.1" 400 145 "https://portabase.example.com/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36 Edg/145.0.0.0"

curl auf http://localhost:80/api/auth/sign-in/sso results in HTTP 404:

root@b24a0e58160b:/app# curl -v http://localhost:80/api/auth/sign-in/sso
*   Trying ::1:80...
* connect to ::1 port 80 failed: Connection refused
*   Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /api/auth/sign-in/sso HTTP/1.1
> Host: localhost
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Server: nginx/1.18.0
< Date: Mon, 02 Mar 2026 13:02:28 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://cdn.jsdelivr.net https://www.googletagmanager.com https://code.iconify.design https://code.iconify.com https://cdn.iconify.design https://api.iconify.design; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://code.iconify.design https://cdn.iconify.design https://code.iconify.com; img-src 'self' blob: data: https: https://code.iconify.design https://cdn.iconify.design https://code.iconify.com https://api.iconify.design http://localhost:9000; font-src 'self' https://fonts.gstatic.com https://cdn.iconify.design; object-src 'none'; connect-src 'self' https://api.iconify.design https://code.iconify.design https://api.github.com; base-uri 'self'; form-action 'self'; frame-ancestors 'none'
< Permissions-Policy: camera=(), microphone=(), geolocation=(), fullscreen=(self)
< X-Content-Type-Options: nosniff
< X-Frame-Options: DENY
< Referrer-Policy: strict-origin-when-cross-origin
< Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
< vary: rsc, next-router-state-tree, next-router-prefetch, next-router-segment-prefetch
< 
* Connection #0 to host localhost left intact

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Status

    Planned

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions