Deep linking with Azure Static Web Apps and Easy Auth :

Deep linking with Azure Static Web Apps and Easy Auth
blow post content copied from  I CAN MAKE THIS WORK
click here to view original post

Azure Static Web Apps doesn't support deep linking with authentication. This is a problem for many applications. This post describes how to work around this limitation.

title image reading "Docusaurus: Using fontaine to reduce custom font cumulative layout shift" in a ridiculous font with the Docusaurus logo and a screenshot of a preload link HTML element

Deep linking

Imagine the situation: your colleague sends you You click the link and you're presented with a login screen. You login and you're presented with a page, but not the one your colleague meant you to see. What do you do now? If you realise what's happened, you'll likely paste the URL into the address bar again so you end up where you hope to. But what if you don't realise what's happened? Answer: confusion and frustration.

If you're using Azure Static Web Apps, you're likely to have this problem. Azure Static Web Apps doesn't support deep linking with authentication. When you get redirected you'll find you are (at best) missing the query parameters. If you take a look at the link here you'll see a suggested workaround. We're going to develop that idea in this post.

The workaround

The idea of the workaround is this:

  • at the start of the authentication process, store the URL you're trying to get to in local storage
  • when the authentication process completes, redirect to the URL you stored in local storage

The post suggested a React specific approach. We'd like something that is framework agnostic. So if you're running with Svelte, Vue, Angular or something else, you can use this approach too.

The implementation

We're going to need to make sure our staticwebapp.config.json is set up to support our goal:

"auth": {
"identityProviders": {
"azureActiveDirectory": {
"registration": {
"openIdIssuer": "",
"clientIdSettingName": "AAD_CLIENT_ID",
"clientSecretSettingName": "AAD_CLIENT_SECRET"
"navigationFallback": {
"rewrite": "index.html"
"routes": [
"route": "/login",
"rewrite": "/.auth/login/aad",
"allowedRoles": ["anonymous", "authenticated"]
"route": "/.auth/login/github",
"statusCode": 404
"route": "/.auth/login/twitter",
"statusCode": 404
"route": "/logout",
"redirect": "/.auth/logout",
"allowedRoles": ["anonymous", "authenticated"]
"route": "/*.json",
"allowedRoles": ["authenticated"]
"responseOverrides": {
"401": {
"redirect": "/login",
"statusCode": 302
"globalHeaders": {
"content-security-policy": "default-src https: 'unsafe-eval' 'unsafe-inline'; object-src 'none'"
"mimeTypes": {
".json": "text/json",
".md": "text/markdown",
".xml": "application/xml"

There's a number of things to note here:

  • we're using Azure Active Directory as our identity provider (and disabling others) - the approach in this post will work with any identity provider; this is just the one I'm using
  • we're creating a /login route to redirect to the Azure AD login page - you don't have to do this, but it's a nice touch
  • we're protecting the *.json files with authentication - this is because our JSON files actually contain secure information. If we were using say an API instead, we'd protect that with authentication instead. Crucially, access to HTML / JS / CSS is not protected. This is important, because we need to be able to access our index.html file and associated JavaScript to store the URL we're trying to get to in local storage.

With this in place, we can implement our workaround. Let's create a file called deeplink.ts:

const deeplinkPathAndQueryKey = 'deeplink:pathAndQuery';

* If authenticated, redirect to the path and query string stored in local storage.
* If not authenticated, store the current path and query string in local storage and redirect to the login page.
* @param loginUrl The URL to redirect to if the user is not authenticated
export async function deeplink(loginUrl: string) {
if (!loginUrl) {
throw new Error('loginUrl is required');

const pathAndQuery = location.pathname +;
console.log(`deeplink: URL before: ${pathAndQuery}`);

const deeplinkPathAndQuery = localStorage.getItem(deeplinkPathAndQueryKey);

const isAuth = await isAuthenticated();

if (isAuth) {
if (deeplinkPathAndQuery && pathAndQuery === '/') {
console.log(`deeplink: Redirecting to ${deeplinkPathAndQuery}`);
history.replaceState(null, '', deeplinkPathAndQuery);
} else if (!deeplinkPathAndQuery) {
if (pathAndQuery !== '/' && pathAndQuery !== loginUrl) {
`deeplink: Storing redirect URL of ${pathAndQuery} and redirecting to ${loginUrl}`
localStorage.setItem(deeplinkPathAndQueryKey, pathAndQuery);
location.href = loginUrl;
} else {
console.log(`deeplink: Redirecting to ${loginUrl}`);
location.href = loginUrl;

async function isAuthenticated() {
try {
const response = await fetch('/.auth/me');
const authMe = (await response.json()) as AuthMe;
const isAuth = authMe.clientPrincipal !== null;
return isAuth;
} catch (error) {
console.error('Failed to fetch /.auth/me', error);
return false;

interface AuthMe {
clientPrincipal: null | {
claims: {
typ: string;
val: string;
identityProvider: string;
userDetails: string;
userId: string;
userRoles: string[];

The code above implements our workaround. It does the following:

  • it checks whether a user is authenticated by hitting the /.auth/me endpoint that is provided by the Static Web Apps authentication system
  • if users are not authenticated, it:
    • stores the path and query string in localStorage and
    • redirects them to the login page
  • when they return post-authentication it retrieves the path and query string from localStorage and sets the URL to that

What does usage look like? Well let's take the root of a simple React app:

import { StrictMode } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { createRoot } from 'react-dom/client';
import App from './App';
import { deeplink } from 'easyauth-deeplink';

function main() {
const container = document.getElementById('root');
if (container) {
const root = createRoot(container);
<App />


You can see here that the first thing we do is call deeplink with the URL of the login page (/login in our case). This will redirect the user to the login page if they're not authenticated, and will redirect them to the URL they were trying to access if they are authenticated. Once that's done, we render our app.

You should be able to apply this regardless of your framework. The important thing is that you call deeplink before you render your app.

I've created a package called easyauth-deeplink that implements the workaround above. You can install it with npm install easyauth-deeplink or yarn add easyauth-deeplink. It's a single file, so you can just copy and paste it into your project if you prefer.

It would be tremendous if this became a feature that was built into Azure Static Web Apps. Maybe one day it will be. In the meantime, I hope this workaround helps you.

December 04, 2022 at 05:30AM
Click here for more details...

The original post is available in I CAN MAKE THIS WORK by
this post has been published as it is through automation. Automation script brings all the top bloggers post under a single umbrella.
The purpose of this blog, Follow the top Salesforce bloggers and collect all blogs in a single place through automation.