DEV Community

Cover image for #05: Securing Static Web Apps
Nitya Narasimhan for Microsoft Azure

Posted on • Updated on • Originally published at azurestaticwebapps.dev

#05: Securing Static Web Apps

Welcome to Week 1, Day 5 of #30DaysOfSWA!!

So far, we've learnt to build/deploy a basic web app, add a serverless API endpoint and customize the configuration settings for both application behaviors and build workflows. But we forgot one thing - the user! To create differentiated experiences for users, we need ways to identify them and understand their role in the application context. We can then use that information to manage user access to application features (role-based authorization) as well as application access to user information (once authenticated).

Thankfully, Azure Static Web Apps makes this fairly painless. Let's see how.

What We'll Cover

  • How do we secure a SWA?
  • Managed authentication
  • Custom authentication
  • Managing user roles
  • Role-based authorization
  • Accessing user information

About the Author(s)

Today, I'm joined by Mitali Karmarkar, a Software Engineer at Microsoft working on the Azure App Service and Azure Static Web Apps products. Say hello and follow her @KarmarkarMitali on Twitter or here on dev.to:


Securing SWA

What does it mean to secure a Static Web App? It's three things:

  • Knowing User Identity - Having a way to determine the identity of the user using an authentication service or provider.
  • Knowing User Roles - Understanding what persona the user is taking on when (using the application), and customizing the experience accordingly.
  • Managing User Access - Making sure the authenticaton information is seamlessly accessible to all SWA components, allowing them to enforce rules that allow only authorized users or roles to access resources.

Let's dive into the three concepts that tackle these needs: Authentication, Role Assignment and Role-Based Authorization.


Managed Auth

Azure Static Web Apps comes with a default streamlined authentication experience that supports:

  • pre-configured providers: Twitter, GitHub, Azure Active Directory
  • pre-assigned roles: anonymous (guest) or authenticated (on login)
  • customizable rules: defined for routes, in staticwebapps.config.json

All pre-configured providers are active by default, with their own pre-defined API endpoints for Login, and a shared API endpoint for Logout.

  • Want to block a specific pre-configured provider? Just add a blocking rule to their login route to ensure no user is allowed access to it.
  • Want to send users to custom pages after successful or failed login attempts? Use query parameters and route rules to make this work.

This is the default managed authentication experience.


Custom Auth

But what if you want more flexibility with the registration process (used by a pre-configured provider) or want to add a new one (custom provider)?
This is where custom authentication options come in, allowing you to override the defaults.

You can configure one or more custom providers for this purpose. Azure Static Web Apps has built-in support for custom authentication using: Apple, Facebook, Google, Twitter, GitHub - and AAD! You can also configure custom providers that support OpenID Connect standard.

By configuring at least one custom provider, you are effectively disabling pre-configured provider options. To configure custom providers, add config information to the auth section of the staticwebapps.config.json file. This is also a good place to use Application Settings (environment variables) to store potentially sensitive configuration data in a privacy-preserving way.

Azure Static Web Apps makes custom registrations easy by providing standard route patterns for Login, Logout and User Profile requests, as well as redirect URLs for authentication callbacks (from the custom provider) on login/logout.


User Roles

There are three key concepts you need to know in this context:

  • Every Static Web Apps user has one or more roles assigned to them.
  • There are 2 built-in roles ("anonymous" and "authenticated")
  • Define custom roles & assign users by invitation or by-function.

Let's review these quickly.

  • All users accessing a Static Web App are in an anonymous role (guest) until authenticated by a pre-configured or custom provider.
  • Once authenticated, they have an authenticated role but can now be assigned custom roles by invitation (proactive) or by function (reactive)
  • Proactive invitations can be configured and sent from the Azure Portal, using provider-specific email addresses for the user. Users now click on the invite link to login with that custom role assigned automatically.
  • Reactive functions defer assignment to post-login, using an Azure Function that dynamically returns an assigned role (or roles) to the user on being given the authenticated user details.

The latter approach offers more flexibility, allowing you to use the function handler to invoke another service (like Microsoft Graph) to make the role-assignment decision for you. Read Role Management for more details - including steps to update role assignments or remove users from a role.


Role-Based Auth

Once the user has been assigned a role, managing user access based on that assignment becomes easy using the built-in support for routing rules based on the allowedRoles property attached to each route. For example, the following configuration setting (in staticwebapps.config.json) would restrict access to all routes that start with /profile* to only authenticated users.
)

{
  "route": "/profile*",
  "allowedRoles": ["authenticated"]
}
Enter fullscreen mode Exit fullscreen mode

Read more about securing routes with rules to understand various usage scenarios and configuration settings to enforce them.


Access User Info

One of the benefits of Azure Static Web Apps' seamless integration of application and API capabilities is that authenticated user information can be accessed transparently in two ways:

  • Using a direct access endpoint at /.auth/me that is automatically provisioned with the user's information when authenticated.
  • Using API functions with a fetch call to the /api/xxx endpoint, where xxx is a named function you implement to return user information.

How-Tos: Watch It!

Prefer a Video Walkthrough to understand the process? We have you covered with the Azure Tips And Tricks: Static Web Apps series. Check out the following videos:


Exercise: Try it!

One popular feature that modern web apps often support is the ability to assign a custom role to an authenticated user (based on some identifiable context) and then regulate their access to various routes or features in the application based on that assigned role. How can we make that happen in Static Web Apps?

There's a tutorial that teaches you how!

  • Authenticate the user using the managed Azure Active Directory API endpoint.
  • Query Microsoft Graph to determine their Active Directory group membership.
  • Use that membership to assign them a custom role.

Challenge Yourself!

Update the application behavior in the staticwebapp.config.json file to restrict user access to specific routes by specifying allowedRoles for those routes. Test what happens when the custom role above is added, and then removed, from the collection of allowedRoles.


Useful Resources

  1. Authentication and Authorization in SWA
  2. Accessing authenticated user information in SWA
  3. Implement custom authentication in SWA
  4. Tutorial: Assign custom roles using Microsoft Graph and AAD
  5. Video Series: Azure Tips And Tricks - Static Web Apps

Discussion (5)

Collapse
layzee profile image
Lars Gyrup Brink Nielsen

Thanks for this amazing article series! How would we set up authorized system-to-system API calls from an external system to the Azure Static Web App API?

Collapse
nitya profile image
Nitya Narasimhan Author

Thank you!! Genuinely made my day - you can tell this is a labor of love for all of us.

Just to clarify:
You want a client (System A) to invoke an API endpoint in the SWA (System B)
where the API endpoint requires you to be authenticated before you can use it?

I see the workflow being something like:

  • The SWA would have the API route endpoint set up to require an allowedRole of "authenticated" - which means anyone trying to access it would be redirected to the login API endpoint before they are allowed to proceed.
  • The client would then invoke the API endpoint - and if it is already authenticated, it gets a valid response, else it will be asked to login first, then redirected to the API when done. See: Securing Routes with Roles

However, I think you may be asking if there are ways to customize that authentication workflow - that would require the SWA implementor to explore custom authentication options.

For instance - if AAD is used, the SWA can configure the types of accounts that can sign in and streamline the login process for trusted organizations.

Does this help? If not, perhaps you can give me an example use case and I'd be happy to follow up :-)

Collapse
layzee profile image
Lars Gyrup Brink Nielsen

I'm thinking of the OAuth 2.0 Client Credentials flow.

Say my Azure Static Web App has a connected Azure AD, an Azure AD B2C provider, or is there a built-in identity provider?

External Service B wants to access Static Web App API A:

  1. External Service B goes where to request an access token using client credentials (client ID + client secret)?
  2. External Service B attaches the Bearer access token to the Authorization HTTP request header for Static Web App API A?
  3. How does Azure Static Web App API A validate the access token?
  4. How does the Azure Static Web API A authorize the access token permissions?
Thread Thread
mkarmark profile image
mkarmark

We currently only support browser logins for authentication. We do not have support for service to service auth, or any form of token validation.

Thread Thread
layzee profile image
Lars Gyrup Brink Nielsen

Thank you for clarifying and once again thank you for this article. The role assignment by Function is interesting 👀