Search code examples
azureopenid-connectazure-web-app-serviceazure-cdn

Unable to get App Service CDN to work with authentication


I have an asp.net core web application hosted in azure as an app service. I've configured the application to use OpenId Connect with Azure AD as the authority. The authentication happens within my application (I am not configuring the app service itself to handle the authentication).

Everything works fine when I hit the app service directly (or even if I use a custom domain name).

I've enabled the CDN service within the app service. Once the initial propagation finished, I open a browser and navigate to the CDN address ([name].azureedge.net).

I get a redirect to Azure AD, but once I finish the authentication process, I get an error.

It looks like when the redirect to Azure AD came back from the CDN, the app service's URL was set as the return_url. So when Azure AD redirected me, I was no longer hitting the CDN. When the redirect to Azure AD happens, there's a cookie placed in my browser; I suspect my site is looking for that cookie, but the browser didn't send it because it was set by a different domain.

I've tried configuring the CallbackPath in the OpenIdConnectOptions to the full URL (schema, host, domain, etc), but when my application initializes, and error is thrown saying that the path must start with a '/' (presumably it's expecting a path from the root of the domain in the request).

Hopefully someone else has come across this problem and can tell me what I'm doing wrong.

Per request, here's my OIDC configuration:

var openIdOptions = new OpenIdConnectOptions
{
    ClientId = adSettings.ClientId,
    ClientSecret = adSettings.ClientSecret,
    Authority = adSettings.Authority,
    CallbackPath = adSettings.CallbackPath,
    ResponseType = OpenIdConnectResponseType.CodeIdToken,                
    Events = new OpenIdConnectEvents { OnTicketReceived = AddApplicationRolesToUserClaimsAsync, OnAuthorizationCodeReceived = RedeemCodeAsync }
};

foreach (var scope in adSettings.Scopes.Concat(settings.MicrosoftGraph.Scopes))
    openIdOptions.Scope.Add(scope);

application.UseOpenIdConnectAuthentication(openIdOptions);

adSettings is a POCO that is hydrated from the following appsettings.json:

"AzureAd": {
  "AADInstance": "https://login.microsoftonline.com/",
  "ClientSecret": "REDACTED",
  "CallbackPath": "/signin-oidc",
  "ClientId": "REDACTED",      
  "TenantId": "REDACTED",      
  "Scopes": [
    "openid",
    "profile",
    "offline_access"
  ]
}

adSettings.Authority is defined in the POCO as:

public string Authority => $"{AADInstance}{TenantId}/v2.0";

Solution

  • After digging around a bit, I found the answer.

    The OpenIdConnectOptions.Events property allows you to hook into various events that happen throughout the lifecycle of authentication. One callback is called OnRedirectToIdentityProvider. It provides a RedirectContext. On that object you can read/write to a property called ProtocolMessage.RedirectUri. That property allows you to specify a full URL which is used as the return_url when the user is forwarded to AAD.

    It's worth noting that I'm using the Microsoft.AspNetCore.Authorization.OpenIdConnect packge from Nuget. There are other packages available that provide similar functionality that do allow you to set a full URL in the options object.