Angular 17.2 and Router Based Authentication with Remult
In this quick guide, I will show you how to implement router-based authentication in Angular 17.2 together with Remult.
This has the advantage that you can protect certain parts of an app while others remain publicly accessible.
To keep it as simple as possible, this guide follows the Angular step-by-step setup tutorial from Remult with a few adjustments.
The finished repo to check out can be found here:
https://github.com/FloMaetschke/remult-angular-router-auth
On the server side, the example code from the Remult User Authentication Tutorial is used with fixed usernames. Only usernames are used because of simplicity.
There are three main subpages:
Login Public and Private, the latter can only be seen as a logged in user.

Showtime!
Auth Guard
Let's create an auth guard we can use to protect specific routes.
ng g guard auth

To verify the authentication, we use remult's built in remult.authenticated() function.
// src/app/auth.guard.ts
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { remult } from 'remult';
export const authGuard: CanActivateFn = (route, state) => {
if(remult.authenticated()) {
return true;
}
// navigate to login page, if not authenticated:
inject(Router).navigate(['/login']);
return false;
};
If the user is not authorized, redirect to login page.
Please note that the
CanActivateinterface is obsolete in newer Angular versions.
But how the hell does remult now know whether the user is logged in or not?
To get this working, we need to query the endpoint http://localhost:4200/currentUser from the API. This is best done the first time the app is called, before it is loaded. In Angular, we can use the APP_INITIALIZER provider token to query the endpoint at startup:
// src/app/app.config.ts
import { APP_INITIALIZER, ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { firstValueFrom } from 'rxjs';
import { UserInfo, remult } from 'remult';
import { HttpClient, provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
provideRemultAuthentication(),
],
};
function provideRemultAuthentication() {
return {
provide: APP_INITIALIZER,
useFactory: (http: HttpClient) => {
return async () => {
return (remult.user = await firstValueFrom(
http.get<UserInfo>('/api/currentUser')
));
};
},
deps: [HttpClient],
multi: true,
};
}
It is important to call the
provideHttpClient()beforehand so that we can use Angular'sHttpClientas a dependency.
The Routes
// src/app/app.routes.ts
import { Routes } from '@angular/router';
import { authGuard } from './auth.guard';
import { LoginComponent } from './login/login.component';
import { PrivateComponent } from './private/private.component';
import { PublicComponent } from './public/public.component';
export const routes: Routes = [
{
path: '',
redirectTo: 'public',
pathMatch: 'full',
},
{
path: 'login',
component: LoginComponent,
},
{
path: 'public',
component: PublicComponent,
},
{
path: 'private',
component: PrivateComponent,
canActivate: [authGuard],
},
];
The authGuard just created is used in the last route definition. This must return true before the route is activated so that the route is loaded.
Login and Logout
Login and logout functions are handled via an AuthService so that the code can be easily accessed by other components. For example, with a logout button in the AppComponent that is accessible from all subpages. Feel free to look in the individual component's templates.
ng g service auth
// src/app/auth.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { UserInfo, remult } from 'remult';
import { firstValueFrom } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class AuthService {
constructor(private http: HttpClient, private router: Router) {}
async login(username: string) {
try {
remult.user = await firstValueFrom(
this.http.post<UserInfo>('/api/signIn', { username })
);
this.router.navigateByUrl('');
} catch {
alert('Login failed');
}
}
async logout() {
try {
await firstValueFrom(this.http.post('/api/signOut', {}));
remult.user = undefined;
this.router.navigateByUrl('');
} catch {
alert('Logout failed');
}
}
}
Run:
To try this example, you have to run 2 processes: angular dev server and the node express server.
npm run dev
npm run dev-node
Thx
Thx to Noam Honig for creating such a nice framework!
If you don't know what remult is, you have to check it out.
It simplifies most common task of an app developers daily life.