Azure AD Auth (microsoft graph) with different subdomain SPA

I have a SPA on the main domain (www.mydomain.com) and the API on api.mydomain.com.

When using credentials auth, meddling with the cookies / CORS allowed me to pass the cookies to my SPA and everything worked fine (I can access api.mydomain.com from mydomain.com)

But we’ve now set up our AAD tenant and need to move to AD OAuth. Everything on the Auth side works (hitting api.mydomain.com/auth/aad, sends to AD login, etc…), but how do I pass back control / cookies / session to www.mydomain.com?

Could you provide details of your setup with CorsFeature plugin? Is that what you mean regarding meddling with the cookies / CORS allowed ?

Code of your Plugins.Add(new AuthFeature .. and Plugins.Add(new CorsFeature.. will make it easier to test and try to help out.

Yeah I just meant when using JsonServiceClient to authenticate with CredentialsAuth, I had to get the cookies to act right for CORS so that my SPA application could communicate authenticated with my API application. Now that I’m using Microsoft graph, that doesn’t seem to carry over.

Startup:

public override void CookieOptionsFilter(Cookie cookie, CookieOptions cookieOptions)
        {
            cookieOptions.SameSite = SameSiteMode.None;
        }        
SetConfig(new HostConfig
            {
                UseSameSiteCookies = false,
                UseSecureCookies = true,
                DebugMode = AppSettings.Get(nameof(HostConfig.DebugMode), HostingEnvironment.IsDevelopment()),
            });
appHost.Plugins.Add(new CorsFeature(
                allowOriginWhitelist: new List<string>() {"http://localhost:3000", "https://localhost:3000", "https://dev.mydomain.com"},
                allowCredentials: true));

Ahh I see, thanks for the context.

And to confirm, your application is redirecting on successful AAD auth to api.mydomain.com and then redirecting to your front end domain?

Example of requests (sanitized of course) from your front end along with responses and code would be appreciated. Creating a reproduction is pretty time consuming so trying to get enough information to build a minimum reproduction.

The way you shared session cookies before should also apply if you’re using a custom Auth Provider as it results in the same Authenticated Session referenced by your ss-id/ss-pid Session Cookies. Although cross sub domain cookies are generally problematic, but I’d typically expect you’d also need to configure Config.RestrictAllCookiesToDomain for cookies to apply across sub domains.

So I’m not sure why your Session Cookies that was working before authenticating at a different sub domain isn’t working now (IMO you’d need to dive into HTTP Headers to compare how Cookies were being set before vs after), but the other approach for being able to transfer authentication into a different domains is to use the JWT Auth Provider where you can convert your authenticated session into a JWT Token that you can use transfer into a different clients bearerToken. We used to do this on TechStacks when hosting a Netlify CDN on a different domain.

Well there are a lot of requests happening, I can send you a HAR file. But the flow all works just as expected, except on the last redirect back to the SPA (http://localhost:3000), there are no cookies set. So:

  1. (SPA) https://localhost:3000/ Dashboard, when unauthenticated, redirects to
  2. (SPA) https://localhost:3000/login, has a button to Sign In with Microsoft
  3. (API) https://localhost:5001/auth/microsoftgraph, redirects to AAD auth, does its thing, redirects to
  4. (API) https://localhost:5001/auth/microsoftgraph (to finish setting up the session), then looks at the referrer which was https://localhost:3000/login and redirects back to it with the ?s=1 param.

The problem is that no cookies are set afterwards.

The link on #2 above is just an a href to https://localhost:5001/auth/microsoftgraph

Using different ports doesn’t provide origin policy isolation so the cookies set in one port should still be accessible in the other. Was authentication successful, i.e. does https://localhost:5001/auth return an Authenticated session?

Note: ss-id/ss-pid Cookies are only set if they need to be, e.g. if the request doesn’t contain them

It does, I found the issue.

In case anyone else runs into this: both your SPA and API need to be HTTPS if using UseSecureCookies = true. Mine have both been running localhost on https, but something happened to my SPA and the certificate went bad. Once this was fixed the cookies got set as expected.

Thanks for the help!

2 Likes