My Angular app using Auth0 with SSR was working fine until upgrade to Auth0 v2.0.1 (as part of upgrade to Angular 15).
There are no compilation errors but the deployed app errors on the server (Heroku deployment)
The error is on app start up and relates to injection of AuthService into my wrapper class.
I've used isPlatformBrowser and isPlatformServer to ensure that code which depends on browser (location) does not run on the server and this worked fine until the upgrade.
ERROR ReferenceError: location is not defined
at AuthService.shouldHandleCallback (...\server\main.js:1:4215732)
at new AuthService (...server\main.js:1:4213627)
at Object.AuthService_Factory [as factory] (...\server\main.js:1:4216049)
at R3Injector.hydrate (...\server\main.js:1:2376384)
at R3Injector.get (...\server\main.js:1:2374606)
at injectInjectorOnly (...\server\main.js:1:2257584)
at Object.ɵɵinject (...\server\main.js:1:2257754)
at Object.Auth0Wrapper_Factory [as factory] (...\server\main.js:1:160425)
at R3Injector.hydrate (...\server\main.js:1:2376384)
at R3Injector.get (...\server\main.js:1:2374606)
The error appears to be purely on construction/dependency injection and not on any method call on the injected AuthService (which I've protected with a check on isPlatformBrowser)
Similar issue here (5 years ago), here (1 year ago) and here (9 months ago).
None have accepted answers.
Reproducing the problem from the Auth0 Sample App
npm install
(and update local Angular CLI - ng update @angular/cli @angular/core
)ng add @nguniversal/express-engine
At this stage the app will build and run but without the login (npm start
) but the server build fails (npm run prerender
).
The generated server.ts for SSR requires an update. "Error: server.ts:13:18 - error TS2349: This expression is not callable." (A namespace-style import cannot be called or constructed - stackoverflow)
The solution is to replace import * as express from 'express';
with import express from 'express';
After this update, npm run prerender
then fails with
Unhandled Promise rejection: window is not defined ; Zone: <root> ;
Task: Promise.then ; Value: ReferenceError: window is not defined
at C:\...\A0-with-SSR\dist\login-demo\server\main.js:1:4112058
at C:\...\A0-with-SSR\dist\login-demo\server\main.js:1:4114283
The error above is different from the error in my original application, but the same in nature: location and window are not defined on the server. However in my original application, the error relates to Auth0 initialisation but in the reproduction of the issue using the sample app, the error message does not refer to Auth0.
So how can Auth0 be set up to use Angular Universal SSR from the Sample App provided?
Code is available to clone from GitHub
Additional info required to configure the Auth0 application in the dashboard (Allowed Callback URLs, Web Origins and Logout URLs)
If you use http://localhost:4200 as recommended, you'll get an error, which isn't the subject of this post. This relates to the requirement for https even in the development environment. The only way I've found around this is to create an entry in the hosts file for a test domain pointing to localhost 127.0.0.1
On Windows, update hosts in C:\Windows\System32\drivers\etc to include
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
127.0.0.1 mylocaldomain.com
A self-signed certificate will need to be generated and installed. More here (use mylocaldomain.com in place of localhost)
Configuration of the Auth0 application can now be completed in the Auth0 dashboard using https://mylocaldomain.com:4200
Back in the local Angular Application code, in auth0_config.json, replace http://localhost:4200 with https://mylocaldomain.com:4200 and remove audience from authorizationParams (we're not concerned with the backend API here)
Amend the start script in package.json to use ssl with the self signed certificate
"start":"ng serve -o --host mylocaldomain.com --ssl --ssl-key ssl\server.key --ssl-cert ssl\server.crt",
The start script can now be run and login to Auth0 is possible.
Frederik Prijk at Auth0 has provided the answer to this, which, in summary, is to ensure the AuthModule is not imported on the server.
This is the app.server.module providers:
providers: [
{
provide: AuthService,
useValue: {},
},
{ provide: AuthConfigService,
useValue: {} as any },
],
More details here - https://github.com/auth0/auth0-angular/issues/432
Sample app on GitHub here - https://github.com/CueToDo/add-A0-to-SSR