I’m trying to deploy an Angular application with Keycloak authentication using Docker. The setup works fine on my local machine (using localhost), but when I deploy it to an Ubuntu VM, I get the following error in the browser console when accessing http://192.168.1.105:4200:
{error: 'Timeout when waiting for 3rd party check iframe message.'}
Here’s my docker-compose.yml:
version: '3.8'
services:
angular:
build:
context: ./web/jtekt-client
dockerfile: Dockerfile
ports:
- "4200:80"
mysql-db:
image: mysql:latest
container_name: mysql-db
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: jtekt
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
jtekt-server:
build: ./server/jtekt-server
container_name: jtekt-server
ports:
- "8081:8081"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql-db:3306/jtekt
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
depends_on:
mysql-db:
condition: service_healthy
keycloak:
image: quay.io/keycloak/keycloak:25.0.0
container_name: keycloak
ports:
- "8080:8080"
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
command: start-dev
Here’s the KeycloakService in my Angular app:
import { Injectable } from '@angular/core';
import Keycloak from 'keycloak-js';
import { UserProfile } from '../models/user-profile';
@Injectable({
providedIn: 'root',
})
export class KeycloakService {
private _keycloak: Keycloak | undefined;
private _profile: UserProfile | undefined;
get keycloak() {
if (!this._keycloak) {
this._keycloak = new Keycloak({
url: 'http://192.168.1.105:8080',
realm: 'jtekt',
clientId: 'jtekt',
});
}
return this._keycloak;
}
get profile(): UserProfile | undefined {
return this._profile;
}
constructor() {}
async init() {
console.log('Authentication the user...');
const authenticated = await this.keycloak?.init({
onLoad: 'login-required',
});
if (authenticated) {
this._profile = (await this.keycloak?.loadUserProfile()) as UserProfile;
}
}
login() {
return this.keycloak?.login();
}
logout() {
return this.keycloak?.logout();
}
hasRole(role: string) {
return this.keycloak?.hasRealmRole(role);
}
}
Here’s my Dockerfile for the Angular app:
FROM node:alpine AS build
RUN npm install -g @angular/cli
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build -- --configuration production
FROM nginx:alpine
COPY --from=build /app/dist/jtekt-client/browser /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Here’s my Nginx configuration (nginx.conf):
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# Security headers
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
}
What I’ve Tried:
Ensured the VM is accessible from the host machine.
Confirmed that Keycloak is running and accessible at http://192.168.1.105:8080.
Updated the Keycloak configuration in my Angular service to use the VM’s IP address.
Checked that the docker-compose.yml is correctly configured to expose the necessary ports.
Question:
Why am I getting a timeout error with the message “Timeout when waiting for 3rd party check iframe message” when trying to access my Angular app on the VM? How can I resolve this issue so that the Keycloak login page is correctly displayed when accessing the Angular app at http://192.168.1.105:4200?
Any help or suggestions would be greatly appreciated!