authenticationazure-ad-b2cazure-static-web-app

Azure Static Web App - Only Allow Authenticated Users (Entra, B2C)


Problem: I am trying to setup an Azure Static Web App so the html content of it would be only accessible to the authenticated (Entra B2C) users:

1. What I have:

I have a static web app in Azure (mkdocs site) deployed with the following config file:

Here is the content of staticwebapp.config.json file

{
  "navigationFallback": {
    "rewrite": "/index.html",
    "exclude": ["/images/*.{png,jpg,gif}", "/css/*"]
  },
  "routes": [
    {
      "route": "/*",
      "allowedRoles": ["authenticated"]
    }
  ],
  "responseOverrides": {
    "401": {
      "statusCode": 302,
      "redirect": "/.auth/login/aad"
    }
  },
  "auth": {
    "identityProviders": {
      "customOpenIdConnectProviders": {
        "aadb2c": {
          "registration": {
            "clientIdSettingName": "AZURE_CLIENT_ID",
            "clientCredential": {
              "clientSecretSettingName": "AZURE_CLIENT_SECRET"
            },
            "openIdConnectConfiguration": {
              "wellKnownOpenIdConfiguration": "https://mytenantb2c.b2clogin.com/mytenantb2c.onmicrosoft.com/B2C_1_SiIn/v2.0/.well-known/openid-configuration"
            }
          },
          "login": {
            "nameClaimType": "emails",
            "scopes": ["openid"],
            "loginParameterNames": []
          }
        }
      }
    }
  },
  "globalHeaders": {
    "Content-Security-Policy": "default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com",
    "X-Content-Type-Options": "nosniff",
    "X-Frame-Options": "DENY"
  }
}

2. What works:

I am able to see /.auth/me which will show if I am not authenticated with:

{
  "clientPrincipal": null
}

then when I go to .auth/login/aad, it will properly allow me to login, and then the .auth/me will show this:

{
  "clientPrincipal": {
    "identityProvider": "aad",
    "userId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "userDetails": "xxxxxxxxxxxx@xxxxxxx.xxx",
    "userRoles": [
      "anonymous",
      "authenticated"
    ]
  }
}

so the process of the authentication seems to work and it has the context of the authenticated user.

3. What does not work:

I open a private/incognito/ window (or my phone), and I am able to access all of the pages on the website, without any authentication.

Somehow my Static Web App is using staticwebapp.config.json to have the login and have the user content functionality but it is not applied to the content of the website.


What am I missing?

I hope it is not the reverse proxy that I am missing, but a configuration or a header that I need to add to each html page.


Tried: I open a private/incognito/ window (or my phone), and I am able to access all of the pages on the website, without any authentication.

Expected: Login prompt on page access, similar to calling .auth/login/aad


Solution

  • The first thing that I forgot was to actually copy the staticwebapp.config.json file into the site folder before it gets published as the Static Web App after mkdocs has build it:

        steps:
          - uses: actions/checkout@v3
            with:
              submodules: true
              lfs: false
          
          - name: Build Site Using mkdocs
            run: | 
              pip install mkdocs
              pip install mkdocs-material
              cd src
              mkdocs build
    
          - name: Copy Config File
            working-directory: src
            run: |
              cp ./staticwebapp.config.json site
              
          - name: Deploy Static Web App
            uses: Azure/static-web-apps-deploy@v1
            with:
              azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_PINK_SEA_123456 }}
              repo_token: ${{ secrets.GITHUB_TOKEN }}
              action: "upload"
              app_location: 'src/site'
    
    

    Here is the content of the file that works with B2C authentication. It is blocking twitter and github auth, and only allows b2c. Every page on the website will only be available after b2c authentication:

    {
      "navigationFallback": {
        "rewrite": "/index.html",
        "exclude": ["/images/*.{png,jpg,gif}", "/css/*", "/js/*", "/assets/*"]
      },
      "routes": [
        {
          "route": "/.auth/login/twitter",
          "statusCode": 404
        },
        {
          "route": "/.auth/login/github",
          "statusCode": 404
        },
        {
          "route": "/.auth/login/*",
          "statusCode": 200
        },
        {
          "route": "/assets/*",
          "statusCode": 200
        },
        {
          "route": "/*",
          "allowedRoles": ["authenticated"]
        }
      ],
      "auth": {
        "identityProviders": {
          "customOpenIdConnectProviders": {
            "aadb2c": {
              "registration": {
                "clientIdSettingName": "AADB2C_PROVIDER_CLIENT_ID",
                "clientCredential": {
                  "clientSecretSettingName": "AADB2C_PROVIDER_CLIENT_SECRET"
                },
                "openIdConnectConfiguration": {
                  "wellKnownOpenIdConfiguration": "https://{TENANT}.b2clogin.com/{TENANT}.onmicrosoft.com/{USER_FLOW}/v2.0/.well-known/openid-configuration"
                }
              },
              "login": {
                "nameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
                "scopes": [],
                "loginParameterNames": []
              }
            }
          }
        }
      },
      "responseOverrides": {
        "401": {
          "redirect": "/.auth/login/aadb2c"
        }
      },
      "globalHeaders": {
        "Content-Security-Policy": "default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com",
        "X-Content-Type-Options": "nosniff",
        "X-Frame-Options": "DENY",
         "Access-Control-Allow-Origin": "https://example.com",
        "Access-Control-Allow-Methods": "POST, GET, OPTIONS"
      }
    }
    

    additional information about the configuration and instructions on how to create the b2c authentication app can be found here:

    https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-authentication-in-azure-static-app