jfoshee / ServiceStack.Authentication.Aad

Azure Active Directory Authentication plugin for ServiceStack
MIT License
20 stars 10 forks source link

SessionID changes after redirecting from AAD #10

Open slovely opened 3 years ago

slovely commented 3 years ago

No idea if you can help with this, but any ideas would be massively appreciated.

I am using your provider and all seems to be OK, except when it calls back into the provider after authenticating with AD it hits this:

                var state = query["state"];
                if (state != userSession.State)
                {
                    session.IsAuthenticated = false;
                    throw new UnauthorizedAccessException("Mismatched state in code response.");
                }

... and it always fails as .State is null, because the SessionId has changed. Interestingly, the new SessionId is exactly the same as the ID generated in RequestCode:

        {
            var state = Guid.NewGuid().ToString("N");
            userSession.State = state;

At this point I figured maybe something was messed-up our side that was somehow using the 'State' property as the SessionId, so created a custom AuthUserSession with a different property to store the NewGuid() in, so that I could change the code to:

            userSession.MyCustomProperty = state;

but STILL when I return from AD auth it changes the SessionID to that same guid!

Do you have any idea what we might be doing to cause that to happen, or even just an idea on things I can look at?

If I comment-out the check against the state BTW, it all works as expected.

slovely commented 3 years ago

Always the way, as soon as you ask a question the answer appears :)

            {
                var state = authService.Request.QueryString[Keywords.State];
                if (!string.IsNullOrEmpty(state))
                {
                    (authService.Request.Response as IHttpResponse)?.ClearCookies();
                    authService.Request.CreateTemporarySessionId(state);
                    session = authService.Request.GetSession(reload:true);
                }
            }

We are using SameSiteCookies, which clears the cookies, and creates a new with the ID of the value on the state parameter.

I propose this change, and it will work regardless of the SameSite setting. Let me know if you would like a PR

            private object RequestCode(IServiceBase authService, IAuthSession session, AuthUserSession userSession, IAuthTokens tokens)
            {
                var state = HostContext.Config?.UseSameSiteCookies == true ? session.Id : Guid.NewGuid().ToString("N");
                userSession.State = state;