In diesem PAR-Statement geht es um eine Anwendung, die für die Authentisierung von Anwendern das Backend for Frontend – Pattern (BFF) nutzt. In der Entwicklungsumgebung funktioniert die Anmeldung. Sobald die Anwendung auf die Testumgebung deployed wurde, wurden die Endpunkte zur Anmeldung an den Identity Provider nicht gefunden.
Problem
Die Authentisierung funktioniert nicht, sobald die Anwendung im Release-Modus veröffentlicht wird. Statt ein Anmeldedialog kommt die Blazor-Standard-Fehlermeldung.
Aktion
Die Analyse grenzte das Problem auf die Datei service-worker.js der Anwendung ein. Im Debug-Modus hat der Serviceworker keinen weiteren Inhalt. Es sieht wie folgt aus:
self.addEventListener('fetch', () => { });
Dadurch hat die App im Entwicklungsmodus keinen Offline-Support. Sobald diese im Release-Modus veröffentlicht wird, greift die Logik der Datei service-worker.published.js. Diese unterstützt Caching, der bei den Endpunkten für die BFF-Endpunkte unerwünschte Auswirkungen hat. Da diese Endpunkte nicht im Cache sind, meldet die PWA das keine Seite gefunden wurde. Die Endpunkte befinden sich jedoch auf dem Server und sollen nicht aus dem Cache der PWA bedient werden.
Damit die Anmeldung korrekt funktioniert muss die Datei service-worker.published.js angepasst werden.
In der Datei steht eine Methode namens onFetch zur Verfügung:
async function onFetch(event) { let cachedResponse = null; if (event.request.method === 'GET') { // For all navigation requests, try to serve index.html from cache // If you need some URLs to be server-rendered, edit the following check to exclude those URLs const shouldServeIndexHtml = event.request.mode === 'navigate'; const request = shouldServeIndexHtml ? 'index.html' : event.request; const cache = await caches.open(cacheName); cachedResponse = await cache.match(request); } return cachedResponse || fetch(event.request); }
In dieser muss shouldServeIndexHtml erweitert werden, sodass der Service-Worker für die Endpunkte den Server kontaktiert.
async function onFetch(event) { let cachedResponse = null; if (event.request.method === 'GET') { // For all navigation requests, try to serve index.html from cache // If you need some URLs to be server-rendered, edit the following check to exclude those URLs const shouldServeIndexHtml = event.request.mode === 'navigate' && !event.request.url.includes('/signin-oidc') && !event.request.url.includes('/signout-callback-oidc') && !event.request.url.includes('/bff/'); const request = shouldServeIndexHtml ? 'index.html' : event.request; const cache = await caches.open(cacheName); cachedResponse = await cache.match(request); } return cachedResponse || fetch(event.request); }
Resultat
Nach dem erneuten Publizieren der Anwendung und bereinigen des Cache leitet der Service-Worker die Anfrage an den Server weiter und der Benutzer kann sich beim Identity Provider authentisieren.
Einen guten Einstieg in das Backend for Frontend (BFF) – Pattern mit historischen Hintergrund-Informationen zeigt Dominick Baier im NDC-Talk.