public async Task <TResult> CreateOrUpdateWithAuthenticationAsync <TResult>(
            AzureApplication application, string method,
            IDictionary <string, string> extraParams,
            Func <Guid, Guid, string, string, AuthenticationActions, IProvideAuthorization, IDictionary <string, string>, Uri, TResult> onLogin,
            Func <Uri, string, IProvideAuthorization, IDictionary <string, string>, TResult> onLogout,
            LookupCredentialNotFoundDelegate <TResult> lookupCredentialNotFound,
            Func <string, TResult> onInvalidToken,
            Func <string, TResult> systemOffline,
            Func <string, TResult> onNotConfigured,
            Func <string, TResult> onFailure)
        {
            return(await await application.GetAuthorizationProviderAsync(method,
                                                                         async (provider) =>
            {
                return await await provider.RedeemTokenAsync(extraParams,
                                                             (subject, stateId, loginId, extraParamsWithRedemptionParams) =>
                                                             TokenRedeemedAsync(method, provider,
                                                                                subject, stateId, loginId, extraParamsWithRedemptionParams,
                                                                                onLogin,
                                                                                onLogout,
                                                                                lookupCredentialNotFound,
                                                                                onInvalidToken,
                                                                                onNotConfigured,
                                                                                onFailure,
                                                                                this.telemetry),
                                                             async(stateId, extraParamsWithRedemptionParams) =>
                {
                    telemetry.TrackEvent("Sessions.CreateOrUpdateWithAuthenticationAsync:  Not Authenticated");
                    if (!stateId.HasValue)
                    {
                        onLogout(default(Uri), "State id missing.", provider, extraParamsWithRedemptionParams);
                    }

                    return await dataContext.AuthenticationRequests.FindByIdAsync(stateId.Value,
                                                                                  (authRequest) => onLogout(authRequest.redirectLogout, $"Not authenticated. [{stateId.Value}]", provider, extraParamsWithRedemptionParams),
                                                                                  () => onLogout(default(Uri), $"Authentication request not found. [{stateId.Value}]", provider, extraParamsWithRedemptionParams));
                },
                                                             onInvalidToken.AsAsyncFunc(),
                                                             systemOffline.AsAsyncFunc(),
                                                             onNotConfigured.AsAsyncFunc(),
                                                             onFailure.AsAsyncFunc());
            },
                                                                         () => systemOffline($"The requested credential system is not enabled for this deployment. [{method}]").ToTask(),
                                                                         (why) => onNotConfigured(why).ToTask()));
        }
        public async Task <TResult> UpdateWithAuthenticationAsync <TResult>(
            Guid sessionId,
            AzureApplication application, string method,
            IDictionary <string, string> extraParams,
            Func <Guid, Guid, string, string, AuthenticationActions, IDictionary <string, string>, Uri, TResult> onLogin,
            Func <Uri, string, IDictionary <string, string>, TResult> onLogout,
            Func <string, TResult> onInvalidToken,
            Func <TResult> lookupCredentialNotFound,
            Func <string, TResult> systemOffline,
            Func <string, TResult> onNotConfigured,
            Func <string, TResult> onFailure)
        {
            return(await await application.GetAuthorizationProviderAsync(method,
                                                                         async (provider) =>
            {
                return await await provider.RedeemTokenAsync(extraParams,
                                                             async(subject, stateId, loginId, extraParamsWithRedemptionParams) =>
                {
                    if (stateId.HasValue)
                    {
                        if (stateId.Value != sessionId)
                        {
                            return onInvalidToken("The authorization flow did not match this resource");
                        }

                        return await AuthenticateStateAsync(stateId.Value, loginId, method, subject, extraParamsWithRedemptionParams,
                                                            onLogin,
                                                            onLogout,
                                                            onInvalidToken,
                                                            onNotConfigured,
                                                            onFailure);
                    }

                    return await await dataContext.CredentialMappings.LookupCredentialMappingAsync(method, subject, loginId,
                                                                                                   (authenticationId) =>
                    {
                        return context.Sessions.CreateSessionAsync(sessionId, authenticationId,
                                                                   (token, refreshToken) => onLogin(sessionId, authenticationId,
                                                                                                    token, refreshToken, AuthenticationActions.signin, extraParamsWithRedemptionParams,
                                                                                                    default(Uri)), // No redirect URL is available since an AuthorizationRequest was not provided
                                                                   onNotConfigured);
                    },
                                                                                                   () => onInvalidToken($"The token does not map to a user in this system.").ToTask());
                },
                                                             async(stateId, extraParamsWithRedemptionParams) =>
                {
                    if (!stateId.HasValue)
                    {
                        onLogout(default(Uri), "State id missing.", extraParamsWithRedemptionParams);
                    }

                    return await dataContext.AuthenticationRequests.FindByIdAsync(stateId.Value,
                                                                                  (authRequest) => onLogout(authRequest.redirectLogout, $"Not authenticated. [{stateId.Value}]", extraParamsWithRedemptionParams),
                                                                                  () => onLogout(default(Uri), $"Authentication request not found. [{stateId.Value}]", extraParamsWithRedemptionParams));
                },
                                                             onInvalidToken.AsAsyncFunc(),
                                                             systemOffline.AsAsyncFunc(),
                                                             onNotConfigured.AsAsyncFunc(),
                                                             onFailure.AsAsyncFunc());
            },
                                                                         () => systemOffline($"The requested credential system is not enabled for this deployment. [{method}]").ToTask(),
                                                                         (why) => onNotConfigured(why).ToTask()));
        }