Featured resource
2026 Tech Forecast
2026 Tech Forecast

1,500+ tech insiders, business leaders, and Pluralsight Authors share their predictions on what’s shifting fastest and how to stay ahead.

Download the forecast
  • Lab
    • Libraries: If you want this lab, consider one of these libraries.
    • Core Tech
Labs

Build Secure Applications with Angular

In this Code Lab, learners secure an Angular application by adding protections for routing, user input, dynamic content, and API communication. They implement route and view access controls, validate untrusted input with forms and custom validators, safely handle dynamic content with Angular’s built-in security mechanisms, and centralize authorization header handling with an HTTP interceptor. The lab focuses on practical implementation of maintainable security patterns in Angular applications.

Lab platform
Lab Info
Level
Advanced
Last updated
May 05, 2026
Duration
45m

Contact sales

By clicking submit, you agree to our Privacy Policy and Terms of Use, and consent to receive marketing emails from Pluralsight.
Table of Contents
  1. Challenge

    Introduction

    Welcome to the Build Secure Applications with Angular Code Lab. In this hands-on lab, you analyze a customer portal application with security gaps, apply route and view access controls, validate untrusted user input, safely render dynamic content, and centralize authorization with an HTTP interceptor to harden the application against common client-side risks.

    About the tools and concepts
    • Route guards are functions Angular calls before activating a route. A guard returns true to allow navigation, false to block it, or a UrlTree to redirect. Guards are the standard way to gate access to authenticated or admin-only views.

    • Reactive form validators are functions that inspect a control's value and return either null for valid input or an error object for invalid input. Custom validators let you enforce rules that the built-in validators cannot, like rejecting characters that commonly appear in injection payloads.

    • Angular sanitization runs automatically on interpolated values and property bindings. The DomSanitizer exposes explicit bypassSecurityTrust* methods for the rare cases where you must mark a value as safe --- those calls should be guarded by a trust check on the input itself.

    • HTTP interceptors run on every outgoing request, which makes them the right place to attach authorization headers in a single, auditable location instead of scattering header logic across services.

    Prerequisites

    Before starting this lab, you should be comfortable with:

    • Angular basics --- components, templates, routing, and HTTP
    • TypeScript basics --- classes, interfaces, and imports
    • Forms basics --- user input, validation, and submission
    • Web security basics --- authentication, authorization, and common client-side risks

    The lab environment is ready to use. Run ng build from inside the SecureApp folder at any time to verify your changes compile.

    The Scenario

    You are a frontend developer at SecureApp Inc. working on the customer portal. A recent security audit identified four findings: routes that anyone can navigate to, forms that accept any input, dynamic content rendered without trust checks, and authorization headers added inconsistently across HTTP calls. Your job is to add route guards and conditional rendering, build custom form validators, route dynamic content through Angular's sanitization correctly, and centralize the authorization header in an HTTP interceptor.

    The Application Structure

    Key files in the lab environment
    • SecureApp/src/app/services/auth.service.ts --- an authentication service that exposes login state, the current user, and the auth token
    • SecureApp/src/app/services/data.service.ts --- an existing API service that currently attaches the Authorization header manually on every call
    • SecureApp/src/app/guards/auth.guard.ts --- route guards that need to enforce authentication and admin role
    • SecureApp/src/app/components/dashboard/ --- a dashboard that needs to show or hide sections based on the current user
    • SecureApp/src/app/validators/input.validators.ts --- custom validators that need to reject unsafe input and weak passwords
    • SecureApp/src/app/components/announcement/announcement.component.ts --- an announcement view that displays dynamic text and an embedded iframe
    • SecureApp/src/app/interceptors/auth.interceptor.ts --- an HTTP interceptor that needs to attach the auth token to outgoing API calls

    Complete the tasks in order. Each task builds on the previous one.

    Run the build at any point with:

    cd SecureApp && ng build
    

    Note: The first time you run ng build, the CLI asks whether you want to enable autocompletion. Type N and press Enter.

    info> If you get stuck, you can refer to the provided solution code for each task, available in the solutions folder.

  2. Challenge

    Protecting Routes and Views

    Understanding Route Guards

    Before any work happens inside a protected component, the router asks a guard whether navigation is allowed. A guard is a plain function that returns true to permit the navigation, false to block it, or a redirect target. This means the component never even loads when access is denied --- the protection happens at the router boundary, not inside the component.

    The authGuard checks whether a user is logged in and redirects to the login page when they are not. The adminGuard runs alongside authGuard on admin-only routes and adds a role check on top of the authentication check. Wiring both guards into a route gives you layered protection: the auth check guarantees there is a user, and the role check guarantees that user has the right permissions. ### Understanding Conditional Rendering

    Route guards stop unauthorized users from reaching a view, but a single view often contains sections that should only appear for certain roles --- admin controls inside an otherwise public dashboard, for example. Angular's *ngIf directive removes an element from the rendered DOM entirely when the bound expression is false, which is the right tool for hiding role-specific UI.

    To keep the template simple, the component class exposes plain getters that return the boolean values the template needs. Each getter delegates straight to AuthService, so login and role state stay in one place and the template stays focused on layout.

  3. Challenge

    Validating Untrusted User Input

    Understanding Custom Validators

    Angular's Validators namespace covers common cases like required fields and minimum length, but security rules usually need custom validators --- functions that inspect the control value and return either null for valid input or an error object that the template can display. A validator factory is a function that returns the actual validator, which lets you parameterize the rule and reuse it across forms.

    For input that flows into application logic or API calls, the safest approach is to reject characters commonly used in injection payloads at the form layer. The noScriptCharactersValidator does this with a single regular expression, returning a typed error key the template uses to show a message. ### Understanding Composite Rules

    Real-world validators usually check several rules at once and report a single error when any of them fail. The strongPasswordValidator enforces three rules --- minimum length, at least one uppercase letter, at least one digit --- and returns a single weakPassword error key when any rule fails. The template only needs to handle one error case, which keeps the UI simple.

    Each rule is computed into a separate boolean before the final return. This makes the logic easy to read and easy to extend: adding a fourth rule means adding one more boolean and including it in the final if check.

  4. Challenge

    Safely Rendering Dynamic Content

    Understanding Angular's Default Escaping

    Angular's interpolation syntax {{ value }} automatically escapes HTML characters before inserting them into the DOM. A user who types <script>alert(1)</script> into a field that flows back into an interpolated binding sees the text as-is --- the script tag is rendered as visible characters, not executed. This is the default behavior, and it is the right behavior for any text that originated from user input. The mistake to avoid is reaching for [innerHTML] or bypassSecurityTrustHtml when interpolation would do the job. Exposing the value through a plain getter keeps the template on the safe interpolation path and makes the trust boundary explicit in the component class.

  5. Challenge

    Centralizing Authorization with an Interceptor

    Understanding HTTP Interceptors

    The starter DataService attaches the Authorization header manually on every API call. That works, but the rule has to be repeated in every method, and any new service that forgets the header silently sends unauthenticated requests. An HTTP interceptor moves that rule to a single function the framework runs on every outgoing request --- services drop the header code and call http.get and http.post with plain URLs.

    An interceptor can inspect the request, modify it by cloning, and forward the result to the next handler in the chain. Centralizing the auth header in an interceptor means the rest of the application makes plain HTTP calls --- no service has to remember to add the header --- and the rule for which requests get the header lives in exactly one place.

    A safe interceptor never adds the auth token to arbitrary URLs. Sending an internal token to an external host is a credential leak, so the first thing the interceptor does is confirm the request targets a trusted API origin. Requests outside the allowlist get forwarded unchanged. ### Understanding Request Cloning

    HttpRequest instances are immutable, so adding a header means calling req.clone({ setHeaders: { ... } }) to produce a new request with the merged headers. Forwarding this cloned request (not the original) is what actually sends the header on the wire.

    Before cloning, the interceptor reads the current token from AuthService and short-circuits when no token is available. This handles the case of an anonymous user calling a public API endpoint that happens to live at a trusted origin: the request still goes through, just without an Authorization header.

  6. Challenge

    Conclusion

    Congratulations on completing the Build Secure Applications with Angular lab! You have added route and view access controls, validated untrusted input with custom validators, routed dynamic content through Angular's sanitization correctly, and centralized authorization in an HTTP interceptor.

    What You Have Accomplished

    1. Implemented Route Guards --- Completed authGuard and adminGuard so the router redirects anonymous users to the login page and blocks non-admins from admin-only routes.
    2. Added Conditional Rendering --- Exposed login and role state through component getters and used *ngIf to hide user-only and admin-only sections from users who should not see them.
    3. Built an Unsafe Characters Validator --- Created a custom validator that rejects characters commonly used in script injection attempts.
    4. Built a Strong Password Validator --- Composed three rules into a single validator that enforces minimum length and character variety.
    5. Routed Dynamic Text Through Safe Interpolation --- Exposed announcement text through a getter so Angular's default escaping handles the trust boundary.
    6. Added a Trust Check Around Bypassed Sanitization --- Validated embed URLs against an allowlisted prefix before calling bypassSecurityTrustResourceUrl.
    7. Filtered Requests by Trusted Origin --- Limited the auth interceptor to allowlisted API origins so external URLs never receive the auth token.
    8. Attached the Auth Header to Trusted Requests --- Cloned each trusted request with a Bearer token from AuthService, centralizing the header logic in one place.

    Key Takeaways

    • Route guards stop unauthorized users at the router boundary, before any component code runs.
    • Custom validators are the right place to enforce input rules that protect downstream code from unsafe values.
    • Angular's interpolation already escapes HTML characters; reach for bypassSecurityTrust* only when you have a separate trust check on the input.
    • Centralizing auth headers in an interceptor turns a per-call concern into a single, auditable rule --- and limiting that rule to a trusted-origin allowlist prevents credential leaks to external hosts.

    Experiment Before You Go

    You still have time in the lab environment. Try these explorations:

    • Add a roleGuard(role: string) factory that produces a guard for any role, not just admin
    • Extend noScriptCharactersValidator to accept a custom regular expression as a parameter
    • Add a second trusted prefix to the announcement embed allowlist and confirm both prefixes pass the trust check
    • Add a refresh-token branch to the auth interceptor that retries the original request after a 401 response
About the author

Angel Sayani is a Certified Artificial Intelligence Expert®, CEO of IntellChromatics, author of two books in cybersecurity and IT certifications, world record holder, and a well-known cybersecurity and digital forensics expert.

Real skill practice before real-world application

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Learn by doing

Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.

Follow your guide

All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.

Turn time into mastery

On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.

Get started with Pluralsight