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"]
}
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, wherexxx
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.
Top comments (5)
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?
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:
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 :-)
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:
Authorization
HTTP request header for Static Web App API A?We currently only support browser logins for authentication. We do not have support for service to service auth, or any form of token validation.
Thank you for clarifying and once again thank you for this article. The role assignment by Function is interesting 👀