Get your free and exclusive +30-page Authentication Analytics Whitepaper

Building an Angular Passkey Login Page with TypeScript

Angular & Passkeys: This tutorial teaches developers how to implement passkeys in Angular for secure, scalable user authentication.

Vincent Delitz

Vincent

Created: July 9, 2023

Updated: March 25, 2026

angular-passkeys
PasskeysCheatsheet Icon

Looking for a dev-focused passkey reference? Download our Passkeys Cheat Sheet. Trusted by dev teams at Ally, Stanford CS & more.

Get Cheat Sheet
Key Facts
  • The tutorial uses Angular version 15.2.9 with the @corbado/web-js package to add passkey authentication to an Angular app.
  • Two Angular components are required: a login component that mounts the Corbado auth UI and a profile component displaying user data post-authentication.
  • The Corbado.load() call initializes the project; the app conditionally renders the router only after initialization completes.
  • The Angular ViewChild decorator is used to reference the auth UI div where Corbado mounts the passkey login interface after view initialization.
  • Corbado session management exposes the authenticated user's ID and email via the Corbado.user object immediately after login.

1. Introduction#

The final result of this tutorial looks as follows:

2. Prerequisites#

This tutorial assumes basic familiarity with Angular, HTML, CSS and JavaScript / TypeScript. Lets dive in! Moreover, you need to have Node and NPM installed on your machine. To facilitate things and follow this tutorial, we recommend to install the Angular CLI as well:

npm install -g @angular/cli

3. Repository structure#

Lets first discuss the structure of our project (full GitHub repo):

. ├── .angular ├── angular.json ├── package.json ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json └── src ├── app │ ├── login │ │ ├── login.component.css │ │ ├── login.component.html │ │ ├── login.component.spec.ts │ │ └── login.component.ts │ ├── profile │ │ ├── profile.component.css │ │ ├── profile.component.html │ │ ├── profile.component.spec.ts │ │ └── profile.component.ts │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── app.component.css │ └── app-routing.module.ts └── style.css

The rest of the files of this project can be ignored for the purpose of this tutorial.

Slack Icon

Become part of our Passkeys Community for updates & support.

Join

4. Set up the Angular project#

In the following, we explain step-by-step what needs to be done to successfully set up the Angular project. If you want to see the finished code, please have a look at our sample application repository.

Lets start out by initializing a new Angular project. In this tutorial, we're using Angular version 15.2.9:

ng new passkeys-demo-angular

In the installation guide steps, we select the following:

  • Share pseudonymous usage data: No
  • Angular routing: Yes
  • Stylesheet format: CSS
  • Enable SSR: No (Choose yes if it's required for your application)

If you run

ng serve

the sample Angular skeleton application starts at http://localhost:4200.

5. Set up the Corbado UI component for passkey authentication#

5.1 Set up your Corbado account and project#

Visit the Corbado developer panel to sign up and create your account (you'll see the passkey sign-up in action here!).

In the project setup wizard, begin by selecting an appropriate name for your project. For the product selection, opt for "Corbado Complete". Subsequently, specify your technology stack and select "DEV along with "Corbado session management" options. Afterwards, youll get more foundational setup guidance.

Next, choose "Web app" as an application type and Vue as your framework. In the application settings, define your application url and relying party id as follows:

  • Application URL: Provide the URL where you embedded the UI component, here: http://localhost:4200.
  • Relying Party ID: Provide the domain (no protocol, no port and no path) where passkeys should be bound to, here: localhost
Substack Icon

Subscribe to our Passkeys Substack for the latest news.

Subscribe

5.2 Embed the UI component in the frontend#

First, let's install all packages required for our implementation. Namly, this will include the Corbado web-js package as well as it's corresponding types and to fix some typescript issues, we'll also include react and ua-parser-js types.

npm i @corbado/web-js
npm i -D @corbado/types @types/react @types/ua-parser-js

Navigate to the root directory of the project:

cd passkeys-demo-angular

Retrieve your Corbado Project's ID, which we'll need in the following. You can find it here under Corbado API access.

Next, navigate to the app.component.ts file. We'll use it as a boundary to only render our app once the Corbado project has initialized.

import { Component, OnInit } from "@angular/core"; import Corbado from "@corbado/web-js"; @Component({ selector: "app-root", templateUrl: "./app.component.html", styleUrls: ["./app.component.css"], }) export class AppComponent implements OnInit { title = "passkeys-demo-angular"; isInitialized = false; constructor() {} ngOnInit(): void { this.initialize(); } async initialize() { try { await Corbado.load({ projectId: "<Your Corbado Project ID>", darkMode: "off", }); this.isInitialized = true; } catch (error) { console.error("Initialization failed:", error); } } }

Once our project has initialized, we'll set the corresponding state and in our App we'll conditionally render our router depending on this isInitialized state inside the `app.component.html file.

Most of the Corbado configuration can be done in the Corbado.load call. An extensive list can be found here.

Replace all content with the following:

<ng-container *ngIf="isInitialized"> <router-outlet></router-outlet> </ng-container>

Next, we create two new components, one where we display our passkey login UI component and one that displays basic user information after we have successfully authenticated.

ng generate component login ng generate component profile

Open src/app/app-routing.module.ts and add the routes for the login and profile component. The login component should be reachable at http://localhost:4200, while the profile component is reachable at http://localhost:4200/profile:

// src/app/app-routing.module.ts import { NgModule } from "@angular/core"; import { ProfileComponent } from "./profile/profile.component"; import { RouterModule, Routes } from "@angular/router"; import { LoginComponent } from "./login/login.component"; const routes: Routes = [ { path: "profile", component: ProfileComponent }, { path: "login", component: LoginComponent }, { path: "", component: LoginComponent }, { path: "**", redirectTo: "/" }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule {}

Let's now set up our auth page. For this we'll need a reference to a div element on our page, which should be used to inject the auth UI into. We establish this reference with Angular ViewChild decorator. After the view has initialized, we'll use the global Corbado object again to mount the auth UI and define a callback to be executed once the user has successfully logged in or signed up. In our case, we'll redirect to the /profile page. Let's set this up in our login.component.ts file.

import { Component, OnInit, ViewChild, ElementRef, AfterViewInit } from "@angular/core"; import { Router } from "@angular/router"; import Corbado from "@corbado/web-js"; @Component({ selector: "app-login", templateUrl: "./login.component.html", styleUrls: ["./login.component.css"], }) export class LoginComponent implements OnInit, AfterViewInit { @ViewChild("authElement", { static: false }) authElement!: ElementRef; // Access the element constructor(private router: Router) {} ngOnInit() { if (Corbado.user) { this.router.navigate(["/profile"]); } } ngAfterViewInit() { // Mount the Corbado auth UI after the view initializes Corbado.mountAuthUI(this.authElement.nativeElement, { onLoggedIn: () => this.router.navigate(["/profile"]), // Use Angular's router instead of window.location }); } }

To establish the reference to our auth UI div we'll put the following into the login.component.html:

<div #authElement></div>

5.3 Set up the profile page#

After successful authentication, the Corbado UI component redirects the user to the provided Redirect URL (https://localhost:4200/profile). This page renders basic user information (user ID and email) and provides a button to logout. If the user isn't logged in, it will provide him with the option to go back to the home page.

Because we only render components once Corbado has loaded, the setup of our profile.components.ts file is very straight forward. We can just set the user state to the Corbado.user value to be able to use it in our template. If the user is not logged in, this value will be undefined.

We'll also define a handleLogout callback to allow the user to log out in the template.

This is how our profile.component.ts file should look like.

import { Component } from "@angular/core"; import { Router } from "@angular/router"; import Corbado from "@corbado/web-js"; @Component({ selector: "app-profile", templateUrl: "./profile.component.html", styleUrls: ["./profile.component.css"], }) export class ProfileComponent { user = Corbado.user; constructor(private router: Router) {} async handleLogout() { await Corbado.logout(); await this.router.navigate(["/"]); } }

In the profile.component.html we'll use the user state to determine if he's logged in and conditionally render our content:

<div> <ng-container *ngIf="user; else notLoggedIn"> <div> <h1>Profile Page</h1> <div> <p> User-ID: {{user.sub}} <br /> Email: {{user.email}} </p> </div> <button (click)="handleLogout()">Logout</button> </div> </ng-container> <ng-template #notLoggedIn> <div> <p>You're not logged in.</p> <p>Please go back to <a routerLink="/">home</a> to log in.</p> </div> </ng-template> </div>

5.4 Run the application#

If everything is set up and installed, run the application with

ng serve

You should see the following screen:

After successful sign up / login, you see the profile page:

Angular Icon

Add passkeys to your Angular app.

Start Free Trial

6. Conclusion#

This tutorial showed how easy it is to add passwordless authentication with passkeys to an Angular app using Corbado. Besides the passkey-first authentication, Corbado provides simple session management, that we used for a retrieval of basic user data. If you want to read more about how Corbado's session management please check the docs here.

Frequently Asked Questions#

What packages do I need to implement passkeys in Angular with Corbado?#

You need @corbado/web-js as a runtime dependency and @corbado/types, @types/react and @types/ua-parser-js as dev dependencies. The dev packages provide TypeScript types and fix TypeScript compatibility issues that arise from the Corbado web component.

How do I mount the Corbado passkey UI inside an Angular component?#

Use Angular's ViewChild decorator to get a reference to a div element in your login template, then call Corbado.mountAuthUI() inside ngAfterViewInit passing that element and an onLoggedIn callback. The callback should use Angular's Router to navigate to a protected route rather than manipulating window.location directly.

Why does my Angular app need to wait for Corbado to initialize before rendering routes?#

The Corbado.load() call must resolve before the Corbado UI components are available for mounting. Wrapping the <router-outlet> in an *ngIf="isInitialized" guard prevents rendering errors and ensures the passkey interface mounts correctly after the SDK is ready.

How do I handle logout after passkey authentication in an Angular app?#

Call await Corbado.logout() in an async method on your profile component, then use Angular's Router to navigate back to the root path. The Corbado.user value will be undefined after logout, which can drive conditional rendering in your profile template to handle the unauthenticated state.

Add passkeys to your app in <1 hour with our UI components, SDKs & guides.

Start Free Trial

Share this article


LinkedInTwitterFacebook