Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is Azure App Service ARR Affinity Required to be Enabled? #1160

Closed
krispenner opened this issue Apr 23, 2021 · 8 comments
Closed

Is Azure App Service ARR Affinity Required to be Enabled? #1160

krispenner opened this issue Apr 23, 2021 · 8 comments
Labels
answered App Services Auth question Further information is requested

Comments

@krispenner
Copy link

For my web app, the redirect from Azure AD back to the web app after successful sign-in requires that I enable ARR Affinity on the web app if it is scaled out to more than one instance, otherwise an infinite redirect loop between my web app and Azure AD ensues. I don't believe this should be a requirement so I'd like to understand what I have misconfigured. There should be no problem with a different backend instance of a web app handling the redirect back from Azure AD and accepting the JWT token.

Which Version of MSAL are you using ?
Microsoft.Identity.Client 4.30.0
Microsoft.Identity.Web 1.9.1
Microsoft.Identity.WebUI 1.9.1

Platform
netcore 3.1 on Linux Docker container in Azure App Service.

What authentication flow has the issue?

  • Web App
    • Whatever is the default

Is this a new or existing app?
This is a new app or experiment

Repro

services.AddMicrosoftIdentityWebAppAuthentication(Configuration);
    "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "Domain": "XXX",
        "TenantId": "XXX",
        "ClientId": "XXX",
        "CallbackPath": "/signin",
        "SignedOutCallbackPath": "/signout"
    },

Web App scaled out to 2 instances, disable ARR Affinity on web app

Expected behavior
App redirects to Azure AD to sign-in user, authenticated user is redirected back to web app and can now use app.

Actual behavior

  • App redirects to Azure AD to sign-in user, authenticated user is redirected back to web app.
  • App redirects to Azure AD to sign-in user, authenticated user is redirected back to web app.
  • App redirects to Azure AD to sign-in user, authenticated user is redirected back to web app.
  • ... (loop)

Web App scaled out to 2 instances, enable ARR Affinity on web app

Expected and Actual behavior
App redirects to Azure AD to sign-in user, authenticated user is redirected back to web app and can now use app.

Web App scaled down to 1 instance, disable ARR Affinity on web app

Expected and Actual behavior
App redirects to Azure AD to sign-in user, authenticated user is redirected back to web app and can now use app.

@jmprieur jmprieur transferred this issue from AzureAD/microsoft-authentication-library-for-dotnet Apr 24, 2021
@jmprieur
Copy link
Collaborator

@krispenner transferred this issue to Microsoft.Identity.web.
I think that you'll find answers to your question in this article: https://github.com/AzureAD/microsoft-identity-web/wiki/Deploying-Web-apps-to-App-services-as-Linux-containers

@jmprieur jmprieur added answered question Further information is requested labels Apr 24, 2021
@krispenner
Copy link
Author

Hi @jmprieur thanks for transferring the issue to the appropriate team. Your suggested answer however is not related to my issue of session affinity. It relates to proxies and I already have that part working on my Linux containers.

@jmprieur jmprieur removed the answered label Apr 25, 2021
@jmprieur
Copy link
Collaborator

@krispenner I though this was related to load balancers? You could ask the ASP.NET Core team? I don't think that this is related to Microsoft.Identity.Web.

@navyasric : do you have an idea?

@krispenner
Copy link
Author

krispenner commented Apr 27, 2021

@jmprieur So after enabling verbose logging for Microsoft.Identity.Web I see the below error as the redirects ping back and forth between Azure AD and two backend App Service instances (as I have my App Service Plan scaled to 2 instances for testing this).

Error from RemoteAuthentication: Unable to unprotect the message.State.

This causes a failure to authorize and a redirect back to Azure AD which re-authenticates the user and redirects them back to my app, this time hitting the other App Service backend instance and causing the same error above. And into a redirect loop I go.

This sounds like the Data Protection keys of ASP.NET Core are not in sync across the instances which are Linux containers. Can you confirm if Microsoft.Identity.Web or MSAL.NET uses the Data Protection library of ASP.NET Core 3.1 or some other protection library that I need to sync keys across instances with? ASP.NET Core Data Protection in Azure is suppose to be sync'd automatically I thought. Or do you think this is something else?

Although, the fact it says "Error From RemoteAuthentication" makes me think this is Azure AD throwing the error and Microsoft.Identity.Web is just reporting it... thoughts?

@krispenner
Copy link
Author

I found this in MS docs regarding the state parameter in the Open ID Connect message.
image

I also found this article which says:

Upon receiving the response from Azure AD, the middleware takes care of validating the ‘state’ parameter to prevent cross-site forgery attack... The OpenID Connect OWIN middleware use .Net framework’s Data Protection API to encrypt the value stored in the ‘state’ parameter.

This points the finger in my mind that the data protection keys are not being sync'd across my Azure backend instances automatically.

@krispenner
Copy link
Author

So it seems that the ASP .NET Core data protection (DP) keys are not automatically sync'd across backend App Service instances of the same app. I'm sure this is meant to be automatic, but maybe not for Linux based App Services (containers) but only for Windows based web apps. Anyways, I have added my own encryption key to be shared across instances and it's hosted in blob storage and secured via key vault. By ensuring the DP key is shared across all instances of the Linux App Service the Open ID Connect message state parameter is being properly decrypted on any backend instance of the web app.

@jmprieur I'd suggest you make note of this in your documentation for anyone trying to use Microsoft.Identity.Web in a scaled out Linux App Service as this is required unless they enable the session affinity cookie on the web app which is not ideal.

services.AddDataProtection()
    .SetApplicationName("MyApp")
    .SetDefaultKeyLifetime(TimeSpan.FromDays(30))
    .PersistKeysToAzureBlobStorage(new Uri("https://mystore.blob.core.windows.net/keyrings/master.xml"), new DefaultAzureCredential())
    .ProtectKeysWithAzureKeyVault(new Uri("https://myvault.vault.azure.net/keys/MasterEncryptionKey"), new DefaultAzureCredential());

@jmprieur
Copy link
Collaborator

Thanks very much @krispenner for these detailed analysis and explanations.
I've added the explanations to the wiki: https://github.com/AzureAD/microsoft-identity-web/wiki/Deploying-web-apps-to-App-Services-as-Linux-containers#issue-with-scaled-out-web-apps-in-app-services

@royarin
Copy link

royarin commented Jul 13, 2022

I have the same issue and we stumbled on the wiki and eventually this issue. While the fix works for us when we scale to 2 instances, anything beyond 2 results in the behavior as described by @krispenner. Any clues there?
Running .netcore 3.1 and Microsoft.identity.Web 1.22.3 on web app for containers running Linux containers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
answered App Services Auth question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants