This guide provides a step-by-step explanation of how to implement token-based authentication and authorization in an Angular Single-Page-Application using Entrypage.io as your identity provider.

Prerequisites:

Implementing OAuth in a Single Page Application with Angular

To configure OAuth in a Single Page Application, it is crucial to select the correct client type. The client’s ability to securely store a client secret determines the appropriate type. When developing an application with Angular, this depends on the architecture:

  • An Angular application built with Server-Side Rendering (SSR) is capable of securely storing a client secret.
  • Conversely, a Single Page Application (SPA) running in a client’s browser is not.

This guide details how to implement OAuth in an Angular SPA that operates within the client’s browser. To do so, you should follow these steps:

  1. Create a public client with Proof Key for Code Exchange (PKCE) support, which does not require a client secret.
  2. Create and configure an Angular application to use an OIDC client library, such as the one from Damien Bod.
  3. Configure the Angular application to authenticate with your chosen authorization server.

1. Configure the Authorization Server

To set up your authorization server with Entrypage.io, follow these steps:

  1. Go to portal.entrypage.io and sign in to your account.
  2. Navigate to the Clients tab and create a new client.
  3. Configure the client with PKCE enabled.
  4. Configure the client without a Client Secret.
  5. Set the client_id to angular-single-page-app.
    • Configure the redirect_uri. Angular runs on http://localhost:4200 and that’s also the redirect-uri
    • Note: Be sure to only use localhost addresses in sandbox domains. Never use a localhost redirect URI in a production environment.
  6. At the token expiry settings, set the expiry of the access token to 10 minutes
  7. Add your domain to the list of allowed CORS Origins. In this case ‘http://localhost:4200’.
    • Note: Be sure to only use localhost addresses in sandbox domains. Never use a localhost origin in a production environment.

2. Create the Angular app:

Create a blank Angular app and install the Angular OIDC Client:

ng entrypage-demo

cd entrypage-demo
ng add angular-auth-oidc-client

Upon installation of angular-auth-oidc-client you’ll be prompted to choose between PKCE with refresh token or a silent renew with an iframe. Choose OIDC Code Flow PKCE using iframe silent renew;

Configure the following settings:

3. Configure the Oidc-Client

After installation, angular-auth-oidc-client has created a file located at: /src/app/auth/auth.config.ts. Be sure to provide the client_id and the scope there:

import { PassedInitialConfig } from 'angular-auth-oidc-client';

export const authConfig: PassedInitialConfig = {
  config: {
            authority: 'https://auth.yourserver.com', // Replace this with your server-address
            redirectUrl: window.location.origin,
            postLogoutRedirectUri: window.location.origin,
            clientId: 'angular-single-page-app',
            scope: 'openid', // Add additional scopes here if configured in your client (e.g. profile, email, etc.)
            responseType: 'code',
            silentRenew: true,
            silentRenewUrl: window.location.origin + '/silent-renew.html',
            renewTimeBeforeTokenExpiresInSeconds: 10,
        }
}

4. Obtain the Tokens

Installing and configuring the OAuth-client will not automatically trigger authentication. To trigger it, use the following code:

import { CommonModule } from '@angular/common';
import { Component, inject, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { OidcSecurityService } from 'angular-auth-oidc-client';

@Component({
  selector: 'app-root',
  imports: [RouterOutlet, CommonModule],
  templateUrl: './app.html',
  styleUrl: './app.css'
})
export class App {
  protected readonly title = signal('test');

  private readonly oidcSecurityService = inject(OidcSecurityService);

  userData$ = this.oidcSecurityService.userData$;

  constructor() {
    // Handle the callback when returning from the auth server
    this.oidcSecurityService.checkAuth().subscribe(({ isAuthenticated, userData, accessToken }) => {
      console.log('authenticated', isAuthenticated);
      console.log('token', accessToken);
    });
  }

  public authorize() {
    // Start the login flow
    this.oidcSecurityService.authorize();
  }
}

This code begins the OAuth 2.1 authorization handshake by redirecting the user to the /authorize endpoint via the .authorize() method.

Important: After the user approves the request, they are sent back to your application’s root URL. Your app must then use the checkAuth() method to exchange the authorization code it receives in the URL for an access token.

Demo

Find a complete example of how to implement the client-credentials grant in a .NET Console application on GitHub.