public async override Task Invoke(IOwinContext context)
        {
            string code = context.Request.Query["code"];

            if (code != null)
            {
                //extract state
                string state = HttpUtility.UrlDecode(context.Request.Query["state"]);

                string          signedInUserID = context.Authentication.User.FindFirst(System.IdentityModel.Claims.ClaimTypes.NameIdentifier).Value;
                HttpContextBase hcb            = context.Environment["System.Web.HttpContextBase"] as HttpContextBase;

                //validate state
                CodeRedemptionData crd = OAuth2RequestManager.ValidateState(state, hcb);

                if (crd != null)
                {
                    //if valid, redeem code

                    IConfidentialClientApplication cc = await MsalAppBuilder.BuildConfidentialClientApplication();

                    AuthenticationResult result = await cc.AcquireTokenByAuthorizationCode(crd.Scopes, code).ExecuteAsync().ConfigureAwait(false);

                    //redirect to original requestor
                    context.Response.StatusCode = 302;
                    context.Response.Headers.Set("Location", crd.RequestOriginatorUrl);
                }
                else
                {
                    context.Response.StatusCode = 302;
                    context.Response.Headers.Set("Location", "/Error?message=" + "code_redeem_failed");
                }
            }
            else
            {
                await Next.Invoke(context);
            }
        }