private object RequestAccessToken(IServiceBase authService, IAuthSession session, string code,
                                          IAuthTokens tokens)
        {
            try
            {
                var appDirectory = GetDirectoryNameFromUsername(session.UserName);

                var appRegistry = authService.TryResolve <IApplicationRegistryService>();
                if (appRegistry == null)
                {
                    throw new InvalidOperationException(
                              $"No {nameof(IApplicationRegistryService)} found registered in AppHost.");
                }

                var registration = appRegistry.GetApplicationByDirectoryName(appDirectory);
                if (registration == null)
                {
                    throw new UnauthorizedAccessException($"Authorization for directory @{appDirectory} failed.");
                }

                try
                {
                    var now           = DateTimeOffset.UtcNow;
                    var tokenResponse = _graphService.RequestAuthToken(new AuthTokenRequest
                    {
                        CallbackUrl  = CallbackUrl,
                        Registration = registration,
                        RequestCode  = code,
                        Scopes       = Scopes
                    });


                    tokens.AccessTokenSecret = tokenResponse.AccessToken;
                    tokens.RefreshToken      = tokenResponse.RefreshToken;

                    var tokenCache = authService.TryResolve <ITokenCache>();
                    tokenCache.UpdateTokenCache(new UserAuthTokenCache
                    {
                        AccessToken            = tokenResponse.AccessToken,
                        RefreshToken           = tokenResponse.RefreshToken,
                        AccessTokenExpiration  = now.AddSeconds(int.Parse(tokenResponse.TokenExpirationSeconds)),
                        RefreshTokenExpiration = now.AddSeconds(TimeSpan.FromDays(14).TotalSeconds - 1),
                        IdToken  = tokenResponse.IdToken,
                        UserName = session.UserName
                    });

                    return(OnAuthenticated(authService, session, tokens, tokenResponse.AuthData.ToDictionary())
                           ??
                           authService.Redirect(SuccessRedirectUrlFilter(this, session.ReferrerUrl.SetParam("s", "1"))));
                }
                catch (AzureServiceException ase)
                {
                    return(RedirectDueToFailure(authService, session, ase.ErrorData));
                }

//                var postData =
//                    $"grant_type=authorization_code&redirect_uri={CallbackUrl.UrlEncode()}&code={code}&client_id={registration.ClientId}&client_secret={registration.ClientSecret.UrlEncode()}&scope={BuildScopesFragment()}";
//                var result = MsGraph.TokenUrl.PostToUrl(postData);
//
//                var authInfo = JsonObject.Parse(result);
//                var authInfoNvc = authInfo.ToNameValueCollection();
//                if (HasError(authInfoNvc))
//                    return RedirectDueToFailure(authService, session, authInfoNvc);
//                tokens.AccessTokenSecret = authInfo["access_token"];
//                tokens.RefreshToken = authInfo["refresh_token"];
//                return OnAuthenticated(authService, session, tokens, authInfo.ToDictionary())
//                       ?? authService.Redirect(SuccessRedirectUrlFilter(this, session.ReferrerUrl.SetParam("s", "1")));
            }
            catch (WebException webException)
            {
                if (webException.Response == null)
                {
                    return(RedirectDueToFailure(authService, session, new NameValueCollection
                    {
                        { "error", webException.GetType().ToString() },
                        { "error_description", webException.Message }
                    }));
                }
                Log.Error("Auth Failure", webException);
                var response     = ((HttpWebResponse)webException.Response);
                var responseText = Encoding.UTF8.GetString(
                    response.GetResponseStream().ReadFully());
                var errorInfo = JsonObject.Parse(responseText).ToNameValueCollection();
                return(RedirectDueToFailure(authService, session, errorInfo));
            }
        }
        private object RequestAccessToken(IServiceBase authService, IAuthSession session, string code,
                                          IAuthTokens tokens, Authenticate request)
        {
            try
            {
                var appRegistry = authService.TryResolve <IApplicationRegistryService>();
                if (appRegistry == null)
                {
                    throw new InvalidOperationException(
                              $"No {nameof(IApplicationRegistryService)} found registered in AppHost.");
                }

                var registration = ApplicationDirectoryResolver(authService, appRegistry, session);
                if (registration == null)
                {
                    throw new UnauthorizedAccessException($"Authorization for directory failed.");
                }

                try
                {
                    var tokenResponse = _graphService.RequestAuthToken(new AuthTokenRequest
                    {
                        CallbackUrl  = CallbackUrl,
                        Registration = registration,
                        RequestCode  = code,
                        Scopes       = Scopes
                    });


                    tokens.AccessTokenSecret = tokenResponse.AccessToken;
                    tokens.RefreshToken      = tokenResponse.RefreshToken;

                    var res = OnAuthenticated(authService, session, tokens, tokenResponse.AuthData.ToDictionary());

                    if (res == null)
                    {
                        return(authService.Redirect(SuccessRedirectUrlFilter(this, session.ReferrerUrl.SetParam("s", "1"))));
                    }

                    if (!registration.AllowAllWindowsAuthUsers)
                    {
                        if (!tokens.Items.ContainsKey("security-groups"))
                        {
                            throw HttpError.Unauthorized(ErrorMessages.WindowsAuthFailed);
                        }

                        var groups = JsonSerializer.DeserializeFromString <string[]>(tokens.Items["security-groups"]);
                        foreach (var requiredRole in registration.LimitAccessToRoles)
                        {
                            if (groups.Contains(requiredRole))
                            {
                                return(res);
                            }
                        }

                        throw HttpError.Unauthorized(ErrorMessages.WindowsAuthFailed);
                    }

                    return(res);
                }
                catch (AzureServiceException ase)
                {
                    return(RedirectDueToFailure(authService, session, ase.ErrorData));
                }
            }
            catch (WebException webException)
            {
                if (webException.Response == null)
                {
                    return(RedirectDueToFailure(authService, session, new NameValueCollection
                    {
                        { "error", webException.GetType().ToString() },
                        { "error_description", webException.Message }
                    }));
                }
                Log.Error("Auth Failure", webException);
                var response     = (HttpWebResponse)webException.Response;
                var responseText = Encoding.UTF8.GetString(
                    response.GetResponseStream().ReadFully());
                var errorInfo = JsonObject.Parse(responseText).ToNameValueCollection();
                return(RedirectDueToFailure(authService, session, errorInfo));
            }
        }