public static async Task <IHttpResponse> Get(
            [OptionalQueryParameter(Name = ProvideLoginMock.extraParamState)] IRefOptional <Authorization> authorizationRef,
            [QueryParameter(Name = ProvideLoginMock.extraParamToken)] string token,
            IAzureApplication application, IProvideUrl urlHelper,
            IHttpRequest request,
            RedirectResponse redirectResponse,
            ServiceUnavailableResponse onNoServiceResponse,
            BadRequestResponse onBadCredentials,
            GeneralConflictResponse onFailure)
        {
            var authentication = EastFive.Azure.Auth.Method.ByMethodName(
                ProvideLoginMock.IntegrationName, application);
            var parameters = new Dictionary <string, string>()
            {
                { ProvideLoginMock.extraParamToken, token },
            };

            if (authorizationRef.HasValue)
            {
                parameters.Add(ProvideLoginMock.extraParamState, authorizationRef.id.ToString());
            }

            return(await Redirection.ProcessRequestAsync(authentication,
                                                         parameters,
                                                         application,
                                                         request, urlHelper,
                                                         (redirect) =>
            {
                var response = redirectResponse(redirect);
                return response;
            },
                                                         (why) => onBadCredentials().AddReason($"Bad credentials:{why}"),
                                                         (why) => onNoServiceResponse().AddReason(why),
                                                         (why) => onFailure(why)));
        }
Exemple #2
0
        public static async Task <IHttpResponse> PostAsync(
            [Property(Name = id_token)] string idToken,
            [Property(Name = state)] IRef <Authorization> authorization,
            IAzureApplication application, IProvideUrl urlHelper,
            IHttpRequest request, IInvokeApplication endpoints,
            RedirectResponse onRedirectResponse,
            ServiceUnavailableResponse onNoServiceResponse,
            BadRequestResponse onBadCredentials,
            GeneralConflictResponse onFailure)
        {
            var parameters = new Dictionary <string, string>
            {
                { id_token, idToken },
                { state, authorization.id.ToString("N") },
            };
            var method = EastFive.Azure.Auth.Method.ByMethodName(
                AzureADB2CProvider.IntegrationName, application);

            return(await EastFive.Azure.Auth.Redirection.ProcessRequestAsync(method, parameters,
                                                                             application, request, endpoints, urlHelper,
                                                                             (redirect, accountIdMaybe) => onRedirectResponse(redirect),
                                                                             (why) => onBadCredentials().AddReason($"Bad credentials:{why}"),
                                                                             (why) => onNoServiceResponse().AddReason(why),
                                                                             (why) => onFailure(why)));
        }
Exemple #3
0
        public static async Task <IHttpResponse> CreateAccountAsync(
            [Property(Name = UserNamePropertyName)] string username,
            [Property(Name = PasswordPropertyName)] string password,
            IAzureApplication application, IHttpRequest httpRequest,
            CreatedBodyResponse <Auth.Session> onCreated,
            AlreadyExistsResponse onUsernameAlreadyTaken,
            GeneralConflictResponse onInvalidPassword)
        {
            if (password.IsNullOrWhiteSpace())
            {
                return(onInvalidPassword("Password cannot be empty"));
            }

            return(await Account
                   .GetRef(username)
                   .StorageCreateOrUpdateAsync(
                       async(created, account, saveAsync) =>
            {
                if (!created)
                {
                    return onUsernameAlreadyTaken();
                }

                account.userIdentification = username;
                account.password = Account.GeneratePasswordHash(username, password);
                await saveAsync(account);
                var session = await CreateSession(username, application, httpRequest);
                return onCreated(session);
            }));
        }
        public static async Task <TResult> IdentifyAccountAsync <TResult>(Authorization authorization,
                                                                          Method authenticationMethod, string externalAccountKey,
                                                                          IDictionary <string, string> extraParams,
                                                                          IAzureApplication application,
                                                                          IProvideLogin loginProvider,
                                                                          IHttpRequest request,
                                                                          Func <Guid, IDictionary <string, string>, TResult> onLocated,
                                                                          Func <Uri, Guid, IDictionary <string, string>, TResult> onInterupted,
                                                                          Func <string, TResult> onGeneralFailure,
                                                                          TelemetryClient telemetry)
        {
            if (!(application is IProvideAccountInformation))
            {
                authorization.authorized             = true;
                authorization.LocationAuthentication = null;
                // return await OnLegacy();
                return(onGeneralFailure($"{application.GetType().FullName} does not implement {nameof(IProvideAccountInformation)}."));
            }
            var accountInfoProvider = (IProvideAccountInformation)application;

            return(await accountInfoProvider.FindOrCreateAccountByMethodAndKeyAsync(
                       authenticationMethod, externalAccountKey,
                       authorization, extraParams,
                       loginProvider, request,
                       PopulateAccount,
                       onAccountReady : (internalAccountId, claims) =>
            {
                return onLocated(internalAccountId, claims);
            },
                       onInterceptProcess : (url, internalAccountId, claims) =>
            {
                return onInterupted(url, internalAccountId, claims);
            },
                       onReject : onGeneralFailure));

            IAccount PopulateAccount(IAccount account)
            {
                account.AccountLinks = new AccountLinks
                {
                    accountLinks = new AccountLink[]
                    {
                        new AccountLink()
                        {
                            externalAccountKey = externalAccountKey,
                            method             = authenticationMethod.authenticationId,
                        }
                    }
                };

                if (!(loginProvider is IProvideClaims))
                {
                    return(account);
                }
                var claimProvider = (IProvideClaims)loginProvider;

                var accountPopulatedFromClaims = claimProvider.PopulateResourceFromClaims(account, extraParams);

                return(accountPopulatedFromClaims);
            }
        }
        public static async Task <IHttpResponse> EnqueueAsync(
            [UpdateId] IRef <InvocationMessage> invocationMessageRef,
            IAzureApplication application,
            NoContentResponse onNoContent)
        {
            await SendToQueueAsync(invocationMessageRef, application);

            return(onNoContent());
        }
Exemple #6
0
        private static async Task <Auth.Session> CreateSession(string userIdentification,
                                                               IAzureApplication application, IHttpRequest request)
        {
            var authentication = new Authentication
            {
                authenticationRef  = Ref <Authentication> .SecureRef(),
                authenticated      = DateTime.UtcNow,
                userIdentification = userIdentification,
                token = SecureGuid.Generate().ToString("N"),
            };

            return(await await authentication
                   .StorageCreateAsync(
                       async (authenticationDiscard) =>
            {
                var method = EastFive.Azure.Auth.Method.ByMethodName(
                    CredentialProvider.IntegrationName, application);

                var parameters = new Dictionary <string, string>()
                {
                    { "state", authentication.authenticationRef.id.ToString() },
                    { "token", authentication.token },
                    { CredentialProvider.referrerKey, "https://example.com/internal" }
                };


                return await await method.RedeemTokenAsync(parameters, application,
                                                           async(externalAccountKey, authorizationRefMaybe, loginProvider, extraParams) =>
                {
                    var authorization = new Auth.Authorization
                    {
                        authorizationRef = new Ref <Auth.Authorization>(Security.SecureGuid.Generate()),
                        Method = method.authenticationId,
                        parameters = extraParams,
                        authorized = true,
                    };

                    return await await Auth.Redirection.AuthorizeWithAccountAsync(
                        authorization,
                        async(authorizationToSave) =>
                    {
                        bool created = await authorizationToSave.StorageCreateAsync(
                            discard => true);
                    },
                        method,
                        externalAccountKey, extraParams,
                        application, request, loginProvider,
                        request.RequestUri,
                        async(accountId, authorizationUpdated) =>
                    {
                        return await CreateSessionAsync(authorization);
                    },
                        (interruptTo, accountId, authorizationUpdated) => throw new Exception($"Cannot redirect to `{interruptTo}`"),
                        (why, authorizationUpdated) => throw new Exception(why),
Exemple #7
0
        public static async Task <IHttpResponse> Post(
            [PropertyOptional(Name = StatePropertyName)] string state,
            [PropertyOptional(Name = CodePropertyName)] string code,
            [PropertyOptional(Name = TokenPropertyName)] string token,
            [PropertyOptional(Name = UserPropertyName)] string user,
            IAzureApplication application,
            IHttpRequest request,
            IProvideUrl urlHelper,
            IInvokeApplication endpoints,
            RedirectResponse onRedirectResponse,
            BadRequestResponse onBadCredentials,
            HtmlResponse onCouldNotConnect,
            HtmlResponse onGeneralFailure)
        {
            var method = EastFive.Azure.Auth.Method.ByMethodName(
                AppleProvider.IntegrationName, application);
            var requestParams = new Dictionary <string, string>();

            if (state.HasBlackSpace())
            {
                requestParams.Add(AppleProvider.responseParamState, state);
            }
            if (code.HasBlackSpace())
            {
                requestParams.Add(AppleProvider.responseParamCode, code);
            }
            if (token.HasBlackSpace())
            {
                requestParams.Add(AppleProvider.responseParamIdToken, token);
            }
            if (user.HasBlackSpace())
            {
                requestParams.Add(AppleProvider.responseParamUser, user);
            }

            return(await ProcessRequestAsync(method,
                                             requestParams,
                                             application, request, endpoints, urlHelper,
                                             (redirect, accountIdMaybe) =>
            {
                return onRedirectResponse(redirect);
            },
                                             (why) => onBadCredentials().AddReason(why),
                                             (why) =>
            {
                return onCouldNotConnect(why);
            },
                                             (why) =>
            {
                return onGeneralFailure(why);
            }));
        }
Exemple #8
0
 public static async Task <IHttpResponse> AuthenticateAsync(
     [Property(Name = UserNamePropertyName)] string username,
     [Property(Name = PasswordPropertyName)] string password,
     IAzureApplication application, IHttpRequest httpRequest,
     CreatedBodyResponse <Auth.Session> onSuccess,
     GeneralConflictResponse onInvalidUserNameOrPassword)
 {
     return(await await Authentication.CheckCredentialsAsync(username, password,
                                                             async account =>
     {
         var session = await CreateSession(username, application, httpRequest);
         return onSuccess(session);
     },
                                                             why => onInvalidUserNameOrPassword(why).AsTask()));
 }
        public static async Task <TResult> ProcessAsync <TResult>(Authorization authorization,
                                                                  Func <Authorization, Task> saveAsync,
                                                                  Method authenticationMethod, string externalAccountKey,
                                                                  IDictionary <string, string> extraParams,
                                                                  IAzureApplication application, IHttpRequest request,
                                                                  IInvokeApplication endpoints, IProvideLogin loginProvider,
                                                                  Uri baseUri,
                                                                  Func <Uri, Guid?, Func <IHttpResponse, IHttpResponse>, TResult> onRedirect,
                                                                  Func <string, TResult> onGeneralFailure,
                                                                  TelemetryClient telemetry)
        {
            return(await await AuthorizeWithAccountAsync(
                       authorization, saveAsync,
                       authenticationMethod, externalAccountKey, extraParams,
                       application, request, loginProvider, baseUri,

                       onAccountLocated : (internalAccountId, authorizationUpdated) =>
            {
                return CreateLoginResponseAsync(
                    internalAccountId, extraParams,
                    authenticationMethod, authorizationUpdated,
                    application, request, endpoints, baseUri, loginProvider,
                    (url, modifier) =>
                {
                    // await saveAsync(authorization);
                    return onRedirect(url, internalAccountId, modifier);
                },
                    (why) =>
                {
                    //await saveAsync(authorization);
                    return onGeneralFailure(why);
                },
                    telemetry);
            },

                       onInterupted : (interceptionUrl, internalAccountId, authorizationUpdated) =>
            {
                return onRedirect(interceptionUrl, internalAccountId, m => m).AsTask();
            },

                       onGeneralFailure : (why, authorizationUpdated) =>
            {
                return onGeneralFailure(why).AsTask();
            },
                       telemetry : telemetry));
        }
        public static async Task <TResult> AuthorizeWithAccountAsync <TResult>(Authorization authorization,
                                                                               Func <Authorization, Task> saveAsync,
                                                                               Method authenticationMethod, string externalAccountKey,
                                                                               IDictionary <string, string> extraParams,
                                                                               IAzureApplication application, IHttpRequest request,
                                                                               IProvideLogin loginProvider,
                                                                               Uri baseUri,
                                                                               Func <Guid, Authorization, TResult> onAccountLocated,
                                                                               Func <Uri, Guid, Authorization, TResult> onInterupted,
                                                                               Func <string, Authorization, TResult> onGeneralFailure,
                                                                               TelemetryClient telemetry)
        {
            return(await await IdentifyAccountAsync(authorization,
                                                    authenticationMethod, externalAccountKey, extraParams,
                                                    application, loginProvider, request,

                                                    onLocated : async(internalAccountId, claims) =>
            {
                authorization.parameters = extraParams;
                authorization.accountIdMaybe = internalAccountId;
                authorization.authorized = true;
                authorization.claims = claims;
                await saveAsync(authorization);
                return onAccountLocated(internalAccountId, authorization);
            },

                                                    onInterupted : async(interceptionUrl, internalAccountId, claims) =>
            {
                authorization.parameters = extraParams;
                authorization.accountIdMaybe = internalAccountId;
                authorization.authorized = true;
                authorization.claims = claims;
                await saveAsync(authorization);
                return onInterupted(interceptionUrl, internalAccountId, authorization);
            },

                                                    onGeneralFailure : async(why) =>
            {
                // Save params so they can be used later
                authorization.parameters = extraParams;
                await saveAsync(authorization);
                return onGeneralFailure(why, authorization);
            },
                                                    telemetry : telemetry));
        }
Exemple #11
0
        public InvokeFunction(IAzureApplication application, Uri serverUrl, string apiRouteName, int executionLimit = 1)
            : base(serverUrl, apiRouteName)
        {
            IAzureApplication GetApplication()
            {
                if (application is FunctionApplication)
                {
                    return(application);
                }

                var newApp = Activator.CreateInstance(application.GetType()) as IAzureApplication;

                createdByThis = true;
                //newApp.ApplicationStart();

                return(newApp);
            }

            this.azureApplication = application; //  GetApplication();
            this.executionLimit   = executionLimit;
        }
Exemple #12
0
        public static async Task <IHttpResponse> Get(
            //[QueryParameter(Name = ProvideLoginMock.extraParamState)]IRefOptional<Authorization> authorizationRef,
            //[QueryParameter(Name = ProvideLoginMock.extraParamToken)]string token,
            IAzureApplication application, IProvideUrl urlHelper,
            IInvokeApplication endpoints,
            IHttpRequest request,
            RedirectResponse onRedirectResponse,
            ServiceUnavailableResponse onNoServiceResponse,
            BadRequestResponse onBadCredentials,
            GeneralConflictResponse onFailure)
        {
            var parameters = request.RequestUri.ParseQuery();
            var method     = EastFive.Azure.Auth.Method.ByMethodName(
                AzureADB2CProvider.IntegrationName, application);

            return(await EastFive.Azure.Auth.Redirection.ProcessRequestAsync(method, parameters,
                                                                             application, request, endpoints, urlHelper,
                                                                             (redirect, accountIdMaybe) => onRedirectResponse(redirect),
                                                                             (why) => onBadCredentials().AddReason($"Bad credentials:{why}"),
                                                                             (why) => onNoServiceResponse().AddReason(why),
                                                                             (why) => onFailure(why)));
        }
Exemple #13
0
        public static async Task <IHttpResponse> LaunchAsync(

            [Api.Meta.Flows.WorkflowParameter(Value = "{{AuthenticationMethod}}")]
            [QueryParameter(Name = "method")] IRef <Method> methodRef,

            RequestMessage <AccountRequest> api,
            IHttpRequest request,
            IAzureApplication application,
            IProvideUrl urlHelper,
            [Api.Meta.Flows.WorkflowVariableRedirectUrl(
                 VariableName = Workflows.AuthorizationFlow.Variables.RedirectUrl)]
            RedirectResponse onLaunched,
            BadRequestResponse onInvalidMethod)
        {
            return(await await Method.ById(methodRef, application,
                                           async method =>
            {
                var authRef = Ref <Authorization> .SecureRef();
                var authorization = new Authorization
                {
                    authorizationRef = authRef,
                    LocationAuthenticationReturn = api
                                                   // .Where(query => query.authorization == authRef)
                                                   .HttpAction(ResponseAction)
                                                   .CompileRequest(request)
                                                   .RequestUri,
                    Method = methodRef,
                };

                return await await authorization.StorageCreateAsync(
                    async(discard) =>
                {
                    var redir = await method.GetLoginUrlAsync(
                        application, urlHelper, authRef.id);
                    return onLaunched(redir);
                });
            },
                                           () => onInvalidMethod().AsTask()));
        }
Exemple #14
0
        public static async Task <IHttpResponse> PatchAsync(
            IAzureApplication application, IProvideUrl urlHelper,
            IHttpRequest request,
            IInvokeApplication endpoints,
            RedirectResponse onRedirectResponse,
            ServiceUnavailableResponse onNoServiceResponse,
            BadRequestResponse onBadCredentials,
            GeneralConflictResponse onFailure)
        {
            var parameters = request.RequestUri.ParseQuery();

            parameters.Add(CredentialProvider.referrerKey, request.RequestUri.AbsoluteUri);
            var authentication = EastFive.Azure.Auth.Method.ByMethodName(
                CredentialProvider.IntegrationName, application);

            return(await EastFive.Azure.Auth.Redirection.ProcessRequestAsync(authentication,
                                                                             parameters,
                                                                             application,
                                                                             request, endpoints, urlHelper,
                                                                             (redirect, accountIdMaybe) => onRedirectResponse(redirect).AddReason("success"),
                                                                             (why) => onBadCredentials().AddReason($"Bad credentials:{why}"),
                                                                             (why) => onNoServiceResponse().AddReason(why),
                                                                             (why) => onFailure(why)));
        }
Exemple #15
0
 public void Write(JsonWriter writer, JsonSerializer serializer,
                   IHttpRequest httpRequest, IAzureApplication application)
 {
     writer.WriteValue(sasUrl);
 }
Exemple #16
0
        public static async Task <IHttpResponse> Redirected(
            [QueryParameter(Name = StatePropertyName)] string state,
            [QueryParameter(Name = CodePropertyName)] string code,
            [QueryParameter(Name = ScopePropertyName)] string scope,
            [OptionalQueryParameter(Name = AuthUserPropertyName)] string authUser,
            [OptionalQueryParameter(Name = PromptPropertyName)] string prompt,
            [OptionalQueryParameter(Name = HdPropertyName)] string hd,
            IAzureApplication application,
            IHttpRequest request,
            IProvideUrl urlHelper,
            IInvokeApplication endpoints,
            RedirectResponse onRedirectResponse,
            BadRequestResponse onBadCredentials,
            HtmlResponse onCouldNotConnect,
            HtmlResponse onGeneralFailure)
        {
            var method = EastFive.Azure.Auth.Method.ByMethodName(
                GoogleProvider.IntegrationName, application);
            var requestParams = new Dictionary <string, string>();

            if (state.HasBlackSpace())
            {
                requestParams.Add(GoogleProvider.responseParamState, state);
            }
            if (code.HasBlackSpace())
            {
                requestParams.Add(GoogleProvider.responseParamCode, code);
            }
            if (scope.HasBlackSpace())
            {
                requestParams.Add(GoogleProvider.responseParamScope, scope);
            }
            if (authUser.HasBlackSpace())
            {
                requestParams.Add(AuthUserPropertyName, authUser);
            }
            if (prompt.HasBlackSpace())
            {
                requestParams.Add(PromptPropertyName, prompt);
            }
            if (hd.HasBlackSpace())
            {
                requestParams.Add(HdPropertyName, hd);
            }

            var builder = new UriBuilder(request.RequestUri);

            builder.Query = string.Empty;
            requestParams.Add(GoogleProvider.responseParamRedirectUri, builder.Uri.AbsoluteUri);

            return(await ProcessRequestAsync(method,
                                             requestParams,
                                             application, request, endpoints, urlHelper,
                                             (redirect, accountIdMaybe) =>
            {
                return onRedirectResponse(redirect);
            },
                                             (why) => onBadCredentials().AddReason(why),
                                             (why) =>
            {
                return onCouldNotConnect(why);
            },
                                             (why) =>
            {
                return onGeneralFailure(why);
            }));
        }
        public static async Task <IHttpResponse> ProcessRequestAsync(
            EastFive.Azure.Auth.Method method,
            IDictionary <string, string> values,
            IAzureApplication application,
            IHttpRequest request,
            IInvokeApplication endpoints,
            IProvideUrl urlHelper,
            Func <Uri, Guid?, IHttpResponse> onRedirect,
            Func <string, IHttpResponse> onAuthorizationnotFound,
            Func <string, IHttpResponse> onCouldNotConnect,
            Func <string, IHttpResponse> onFailure)
        {
            //var authorizationRequestManager = application.AuthorizationRequestManager;

            var telemetry = application.Telemetry;

            telemetry.TrackEvent($"ResponseController.ProcessRequestAsync - Requesting credential manager.");

            var requestId = Guid.NewGuid();

            request.TryGetReferer(out Uri referer);
            var redirection = new Redirection
            {
                webDataRef     = requestId.AsRef <Redirection>(),
                method         = method.authenticationId,
                values         = values,
                redirectedFrom = referer,
            };

            return(await await redirection.StorageCreateAsync(
                       discard =>
            {
                return EastFive.Azure.AppSettings.Auth.PauseRedirections.ConfigurationBoolean(
                    async pauseRedirections =>
                {
                    if (pauseRedirections)
                    {
                        return request.CreateResponse(System.Net.HttpStatusCode.OK, $"All logins have been paused for this system.  Request ID `{requestId}`");
                    }
                    return await ContinueAsync();
                },
                    why => ContinueAsync(),
                    ContinueAsync);

                Task <IHttpResponse> ContinueAsync()
                {
                    var baseUri = request.RequestUri;
                    return AuthenticationAsync(
                        method, values, application, request, endpoints,
                        request.RequestUri,
                        RefOptional <Authorization> .Empty(),
                        (uri, accountIdMaybe, modifier) =>
                    {
                        var response = onRedirect(uri, accountIdMaybe);
                        return modifier(response);
                    },
                        () => onAuthorizationnotFound("Authorization not found"),
                        onCouldNotConnect,
                        onFailure);
                }
            },
                       () => onFailure("GUID NOT UNIQUE").AsTask()));
        }
        public async static Task <TResult> AuthenticationAsync <TResult>(
            EastFive.Azure.Auth.Method authentication, IDictionary <string, string> values,
            IAzureApplication application, IHttpRequest request,
            IInvokeApplication endpoints, Uri baseUri,
            IRefOptional <Authorization> authorizationRefToCreate,
            Func <Uri, Guid?, Func <IHttpResponse, IHttpResponse>, TResult> onRedirect,
            Func <TResult> onAuthorizationNotFound,
            Func <string, TResult> onCouldNotConnect,
            Func <string, TResult> onGeneralFailure)
        {
            var telemetry = application.Telemetry;

            return(await await authentication.RedeemTokenAsync(values, application,
                                                               async (externalAccountKey, authorizationRefMaybe, loginProvider, extraParams) =>
            {
                #region Handle case where there was a direct link or a POST

                if (!authorizationRefMaybe.HasValue)
                {
                    var authorization = new Authorization
                    {
                        authorizationRef = authorizationRefToCreate.HasValue?
                                           authorizationRefToCreate.Ref
                                :
                                           new Ref <Authorization>(Security.SecureGuid.Generate()),
                        Method = authentication.authenticationId,
                        parameters = extraParams,
                        authorized = true,
                    };
                    return await ProcessAsync(authorization,
                                              async(authorizationUpdated) =>
                    {
                        bool created = await authorizationUpdated.StorageCreateAsync(
                            authIdDiscard =>
                        {
                            return true;
                        },
                            () =>
                        {
                            //if(authorizationRefToCreate.HasValueNotNull())
                            //    throw new Exception("Authorization to create already exists.");
                            //throw new Exception("Duplicated update from ProcessAsync.");
                            return false;
                        });
                    },
                                              authentication, externalAccountKey, extraParams,
                                              application, request, endpoints, loginProvider, baseUri,
                                              onRedirect,
                                              onGeneralFailure,
                                              telemetry);
                }

                #endregion

                var authorizationRef = authorizationRefMaybe.Ref;
                return await authorizationRef.StorageUpdateAsync(
                    async(authorization, saveAsync) =>
                {
                    return await ProcessAsync(authorization,
                                              saveAsync,
                                              authentication, externalAccountKey, extraParams,
                                              application, request, endpoints, loginProvider, baseUri,
                                              onRedirect,
                                              onGeneralFailure,
                                              telemetry);
                },
                    () =>
                {
                    return onAuthorizationNotFound();
                });
            },
                                                               (authorizationRef, extraparams) => onGeneralFailure("Cannot use logout to authenticate").AsTask(),
                                                               (why) => onCouldNotConnect(why).AsTask(),
                                                               (why) => onGeneralFailure(why).AsTask()));
        }