1 of 113

πŸš‚

Micro-Frontends: Authentication Magic at Dutch Railways

2 of 113

TABLE OF CONTENTS

Micro frontends

Module federation

MSAL authentication

Kubernetes config

Live application

04

05

01

02

03

3 of 113

Peter Eijgermans

CodeSmith / Architect

Full-Stack

4 of 113

Meet Petra - Train Controller

6:00 AM: Needs real-time train positions

6:15 AM: Emergency response required

6:30 AM: System takes 45 seconds to load each screen

6:31 AM: Frustration level: MAXIMUM

5 of 113

🀯 8:47 AM - Amsterdam Station Chaos

3,000 railway workers locked out

Authentication system: CRASHED

Rush hour:

IN PROGRESS

6 of 113

Punchline:

This is why we’re hereβ€”

to prevent such disasters

7 of 113

Show of Hands Time

πŸ™‹β€β™€οΈ "Who's afraid to deploy on Friday afternoon?"

πŸ™‹β€β™‚οΈ "Who's maintaining multiple authentication systems?"

πŸ™‹ "Who's dealing with a monolith that takes forever to build?"

8 of 113

The Railway Monolith: A Beautiful Disaster

Slow development/deployment

Not Maintainable

Hard to Scale

SPOF

9 of 113

"This HUGE app is like one giant box of LEGO that nobody can organize.

If one part of the app breaks? The whole thing crashes.οΏ½ If you want to add something new? You have to rebuild the whole box."

10 of 113

Monolith

Database

Massive Application

11 of 113

What If We Could..

Architecture: How to get from Monolith to Modular speed ?!

  • πŸš€ Deploy features independently β€” anytime, without fearοΏ½
  • πŸƒβ€β™‚οΈ Let teams move fast β€” without stepping on each other’s toesοΏ½
  • πŸ”— Connect multiple apps seamlesllyοΏ½
  • πŸ› οΈ Use Module Federation to share code and scale easilyοΏ½

Authentication & Security:

  • πŸ”‘ Login once β€” access everything, seamlesslyοΏ½
  • βš™οΈ Share authentication state across all appsοΏ½
  • πŸ›‘οΈProper SSO setupοΏ½
  • πŸ”„ Auto-refresh tokens & secure WebSockets for real-time data

12 of 113

These are the dreams of every team:

First, we want to build and improve fastβ€”οΏ½ with smaller parts, easy to connect, no more crashes.

Then, we want users to log in just once,οΏ½

Today, I’ll walk through these pointsβ€”

and we’ll check them off

Let’s go!

13 of 113

Architecture:

From Monolith to

Modular Speed !

14 of 113

Step 1 - Split frontend and backend

Database

Backend

Microservices

Frontend

15 of 113

Step 2 - Split backend as micro services

DB

DB

DB

DB

Backend

Microservices

Frontend

16 of 113

Step 3 - Split frontend -> Verticals

Frontend

Backend

Team A

Team A

C

B

B

DB

DB

DB

B

C

WS REST

pairing

17 of 113

Short definition

β€œAn architectural style where independently deliverable frontend and backend applications are composed into a greater whole”

18 of 113

Micro Frontends to the Rescue

19 of 113

Micro frontend architecture Dutch Railways

Host / Shell

Train

Tracking

Train /Track Tracking

Route Planning

Track Occupancy

Route Planning

Route Planning

Track Occupancy

Track Occupancy

FE

Track

Section

Track

Section

Track

Section

Train /Track Tracking

Route Planning

Track

Section

Micro Services

Track Occupancy

responsibilities:οΏ½1. routingοΏ½2. compositionοΏ½3. authentication

4. state mgmt

5. easy scaling

6. …..

WS

rest

20 of 113

HOST / SHELL

MF train tracking

MF route planning

MF track

section

21 of 113

But…

How to build the

Frontend efficiently?

22 of 113

Module Federation

23 of 113

2022 Webcomponents

Host / Shell

Train

Tracking

Train / Infra

Tracking

Route Mgmt

Track Occupancy

Route Mgmt

Route Mgmt

Track Occupancy

Track Occupancy

Track

Section

Track

Section

Track

Section

Angular

Angular

Angular

Angular

Angular

Angular

Angular

Angular

Angular

Angular

Angular

shared libs

shared libs

shared libs

24 of 113

🐒 50s load time

β†’ Petra misses emergencies

25 of 113

2025 Module Federation for speed !!!

Host / Shell

Train

Tracking

Train / Infra

Tracking

Route Mgmt

Track Occupancy

Route Mgmt

Route Mgmt

Track Occupancy

Track Occupancy

Track

Section

Track

Section

Track

Section

Angular

Shared Lib

Independent Deployment/ CI CD

Technology Agnostic

Improved Scalability

26 of 113

27 of 113

πŸš„ 0.5s load time β†’ Petra saves the day

Performance

Module Federation is fast

28 of 113

29 of 113

Config Remote

30 of 113

Config Host

31 of 113

Config specific versions to share !

32 of 113

How does the Host

load

the Remotes?

33 of 113

34 of 113

35 of 113

Mid-talk Checkpoint

Architecture & Speed (Micro Frontends & Module Federation):

  • πŸš€ Deploy features independently β€” anytime, without fearοΏ½
  • πŸƒβ€β™‚οΈ Let teams move fast β€” without stepping on each other’s toesοΏ½
  • πŸ”— Connect multiple apps into one seamless experienceοΏ½
  • πŸ› οΈ Use Module Federation to share code and scale easilyοΏ½

βœ…

βœ…

βœ…

βœ…

36 of 113

Demo

Module Federation !

37 of 113

"Breaking the system apart helped speed up developmentβ€”

but we still had a major problem left."

38 of 113

Authentication

39 of 113

40 of 113

The Multi-App Authentication Nightmare

Slow or broken SSO

Multiple logins

Token Chaos

CORS issues

Redirect loops

41 of 113

πŸ¦Έβ€β™‚οΈ The 2 Heroes of Modern Authentication

OpenID Connect (OIDC): Identity Layer

"OIDC is like showing your ID at the entrance”

OAuth 2.1: The Delegation Protocol

"OAuth is like getting a festival wristband"

🎫

Key Players:

  • Authorization Server (EntraID - The Bouncer)
  • Resource Server (Your API - The Bartender checks wristband)
  • Client Application (Angular App - You, The Customer)

🎫

42 of 113

OIDC Flow

"Now let's see exactly how this OIDC flow works step by step.

Starting with what happens when a user clicks 'Login'..."

43 of 113

Flow 1: Initial Login & Authorization

πŸ”

44 of 113

βš™οΈ FIRST: needed auth-config MSAL

45 of 113

Authorization Server (EntraID - The Bouncer)

46 of 113

Part 1 β†’ Part 2: "Great!

We have an authorization code.

Now let's see how we exchange it for tokens..."

47 of 113

Flow 2: Token Exchange & Caching

48 of 113

Authorization Server (EntraID - The Bouncer)

49 of 113

Token Types

Purpose

Where Used

Format

Lifetime

Example Scope Needed

🎫Access Token

Access to protected APIs

Sent in Authorisation headers as Bearer

JWT

~1 hour

api://xyz/.default

πŸ†”Token

User identity info for authentication

Used by frontend

JWT

~1 hour

πŸ”„Refresh Token

Get new tokens without login.eEnables SSO! 🎯

Used internally

hidden

Long-lived

The Scope is a URL for specific permissions for an API

50 of 113

Part 2 β†’ Part 3: "Perfect! We have our tokens cached in the browser! β†’ local or sessionscopeοΏ½

Now let's see how our application uses them..."

51 of 113

Flow 3: API Calls & Token Management

πŸš€

52 of 113

The Magic:

Automatic token injection via HTTP interceptors!

Resource Server (Your API - The Bartender)

πŸ”„

53 of 113

Token injection

GET /user/getDrink

Authorization: Bearer eyJ0eXAiOiJK...

Component

HTTP Interceptor

JWT Secured Resource Server

GET /user/getDrink

54 of 113

OIDC Flow - Key Takeaways!

πŸ” Login

User β†’ EntraID β†’ Authorization Code

🎫 Exchange

Authorization Code β†’ 3 Tokens:

  • Access: API calls
  • ID: User info
  • Refresh: New tokens + SSO

πŸš€ Use

Access token β†’ API calls (auto-refresh)

55 of 113

56 of 113

MSAL for OIDC

Key Benefit: MSAL abstracts away the complexity of token management, token renewal and token injection.

57 of 113

Now Let's See How MSAL Angular Handles This

MSAL AuthenticationResult Interface:

interface AuthenticationResult {

accessToken: string; // "eyJ0eXAiOiJKV1QiLCJhbGci..."

idToken: string; // Identity proof

refreshToken: string; // Renewal ticket

expiresOn: Date; // Expiration time

scopes: string[]; // Permissions granted

account: AccountInfo; // User profile information

}

58 of 113

MSAL Architecture

59 of 113

πŸ—οΈ Angular MSAL Architecture Overview

MsalService

60 of 113

Transition : "Now that we understand MSAL architecture, let's see how this looks in a real Angular component..."

61 of 113

Real-World

Login Component

62 of 113

πŸ—οΈ Building Your First MSAL Login Component

63 of 113

πŸ—οΈ Building Your First MSAL Login Component

64 of 113

But…

How do we share authentication across micro-frontends?

That's our next challenge..."

65 of 113

Challenge

⚠️ Key Risks:

οΏ½

Different Login Status in Each App

Multiple Tokens, Out of Sync

Problems Across Different Domains

Goal: SSO

Security Gaps

66 of 113

67 of 113

The Solution:

Share MSAL Packages

68 of 113

Module Federation Solution

πŸ”— Sharing MSAL Packages in config HOSTοΏ½οΏ½

Key Concept:

Shared MSAL packages

ensure single instance !

69 of 113

Module Federation Solution

πŸ”— Sharing MSAL Packages in REMOTE configοΏ½οΏ½

70 of 113

2025 Module Federation for speed !!!

Host / Shell

Train

Tracking

Train / Infra

Tracking

Route Mgmt

Track Occupancy

Route Mgmt

Route Mgmt

Track Occupancy

Track Occupancy

Track

Section

Track

Section

Track

Section

Angular

MSAL

71 of 113

72 of 113

How to config SSO?

73 of 113

βš™οΈ Same auth-config for all Micro frontends !

74 of 113

πŸ—οΈ Same OIDC Module - The Foundation for OIDC

75 of 113

🏭 Same MSAL Instance config!

76 of 113

HTTP Interceptor Configuration

Magic: Automatically adds Authorization: Bearer <token> header

πŸ”„ Automatic Token Injection:

77 of 113

SSO Checklist !

βœ… Same Identity Provider (EntraID)

βœ… Shares MSAL Package and storage

βœ… Same auth config

βœ… Single Token Refresh Strategy

78 of 113

Demo SSO !

79 of 113

Websockets for real time data

80 of 113

What are Websockets ?

Network protocol

Two-way communication

Data is pushed to client

Always Open

81 of 113

πŸ”Œ WebSocket Authentication Challenge #3

The Problem: Websockets do not support HTTP headers for tokens authentication tokens!

82 of 113

πŸ”Œ WebSocket Authentication Challenge

The Solution β†’ Custom authentication handling !

msalService

83 of 113

Final Checkoff

Authentication & Security (MSAL & Auth Solutions):

  • πŸ”‘ Login once β€” access everything, seamlesslyοΏ½
  • βš™οΈ Share authentication state across all appsοΏ½
  • πŸ›‘οΈ proper SSO setupοΏ½
  • πŸ”„ Auto-refresh tokens & secure WebSockets for real-time data

βœ…

βœ…

βœ…

βœ…

Mission Completed !

84 of 113

Final Challenge:

Kubernetes Config

β€” One App, Many Environments?

85 of 113

βš™οΈ MSAL auth-config example

86 of 113

βš™οΈ Kubernetes ConfigMap

87 of 113

Runtime Config Flow (High-level)

1. K8s ConfigMap

provides

app-config.json per Env

2.Load Config

fetch(app-config.json)

new AppConfig()

setup.ts

3. InjectionToken

APP_CONFIG

DI System

bootstrap.ts

4. MSAL Setup

Factory Functions:

β€’ MSALInstance

β€’ Guard & Interceptor

88 of 113

Kubernetes advantages !

βœ… Settings stored in Kubernetes, not in the app

βœ… Change config without rebuilding

βœ… One app on different Environments

One app, many environmentsβ€”no rebuilds

89 of 113

REAL WORLD APP

Trackviewer is micro frontend-based app for the Dutch Railway.

With Trackviewer you can see at a glance where exactly trains are, what the delay is and from which track they will disappear.

90 of 113

Remember Petra ?

91 of 113

β€œCall to Action” :

Claim one whole day,

Try Module Federation

and implement MSAL for seamless OIDC flows

92 of 113

β€œCall to Action” :

Claim one whole day,

Try Module Federation

and implement MSAL for seamless OIDC flows

GrΓ cies !

93 of 113

Peter Eijgermans

CodeSmith / Architect

Full-Stack

94 of 113

Peter Eijgermans

95 of 113

πŸš€ Bootstrapping the Shell Application

Key Point:

MsalRedirectComponent handles OAuth callback

96 of 113

🎯 Silent First, Interactive Fallback

Strategy:

Always try silent first, fallback to interactive

97 of 113

πŸ”’ Security Best Practices

βœ… What We're Doing Right:

  • Secure Token Storage: LocalStorage with proper cache management
  • Scope Validation: Backend validates audience claims
  • Token Expiration Handling: Automatic refresh with fallback
  • HTTPS Everywhere: Non-negotiable for production

🚨 Watch Out For:

  • Token Leakage: Never log tokens or put them in URLs params
  • Scope Creep: Request minimal necessary permissions
  • Cross-Origin Issues: Proper CORS configuration
  • Token Sharing: Don't share tokens between domains
  • Refresh Token Rotation: Handle refresh token expiration

98 of 113

Common Problems & Solutions:

1. "MSAL instance not initialized"

// Ensure initialization in BearerTokenService

await this.authService.instance.initialize();

2. Module Federation version conflicts

// Use singleton and strict versions

shared: {

'@azure/msal-angular': { singleton: true, strictVersion: true }

}

99 of 113

Common Problems & Solutions:

3. WebSocket authentication failures

typescript

// Check token expiration before sending

if (tokenResult.expiresOn < new Date()) {

tokenResult = await this.bearerTokenService.acquireToken();

}

4. Redirect loops

typescript

// Ensure proper redirect URI configuration

redirectUri: `${location.origin}${location.pathname}`

100 of 113

Key takeaways

πŸ”’ Security: MSAL simplifies the complexity of implementing OAuth/OIDC

🧩 Scalability: Module Federation enables distributed auth

⚑ Performance: Shared packages, single MSAL instance

πŸ”Œ Flexibility: Custom services for WebSocket auth

πŸ› οΈ Maintainability: Environment-specific configurations in K8s

101 of 113

🎫 Custom Token Service for WebSockets

102 of 113

OIDC Flow: 🎫 Getting the golden ticket

We have 3 Types of Tokens:

  • 🎫 Access Token: "Grants access to protected APIs" - Short-lived, contains permissions/scopes (JWT format)
  • πŸ†” ID Token: Contains user identity claims / info
  • πŸ”„ Refresh Token: "I can get new tickets" - Long-lived, used to get new Access and ID tokens

Grants access to protected APIs

Grants access to protected APIs

103 of 113

The Magic of Injection Tokens

The APP_CONFIG injection token acts as a bridge between your external configuration (from K8s) and Angular's DI system

104 of 113

The Magic of Injection Tokens

Step-by-step flow:

  1. πŸ“‹ Kubernetes ConfigMap β†’ Provides app-config.json
    • Contains environment-specific config (clientId, authority, scopes)
  2. πŸ“¦ Docker Container Setup
    • ConfigMap mounted as volume into nginx container
    • Path: /usr/share/nginx/html/assets/app-config.json
  3. 🌐 Browser Runtime
    • Angular app loads in browser
    • Fetches ./assets/app-config.json via HTTP
  4. ⚑ Angular Injection
    • Config loaded into APP_CONFIG injection token
    • MSAL receive config via dependency injection

105 of 113

πŸ›‘οΈProtecting Routes with MSAL Guard

106 of 113

MSAL coding - Key Takeaways!

βœ… OIDC Module configures MSAL for Angular/React

βœ… MSALInterceptorConfigProvider contains list protected resources

βœ… Custom Token Service for WebSockets

βœ… Share MSAL packages with Module Federation

107 of 113

Challenge 4: How to Solve the Multi-Environment Authentication ?

108 of 113

Problem:

Hard-coded authentication configuration

Different environments need different MSAL settings

109 of 113

Solution:

Single build artifact

Dynamic configuration Kubernetes Configsmaps

Type-safe injection

Traditional Approach:

Build per Environment

Hard-coded config

Deployment complexily

110 of 113

Micro frontends - Key Takeaways!

βœ… Understand the Micro frontend Architecture

βœ… Host vs. Remote applications

βœ… Configure and Share resources with Module Federation

111 of 113

112 of 113

113 of 113