protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var body = await context.Request.GetBodyAsStringAsync(cancellationToken);

            var model    = PostBodyParser.ToModel <RegisterPostModel>(body, bodyContentType, _logger);
            var formData = Serializer.DeserializeDictionary(body);

            var allNonEmptyFieldNames = formData.Where(f => !string.IsNullOrEmpty(f.Value.ToString())).Select(f => f.Key).ToList();

            var providedCustomFields = new Dictionary <string, object>();

            foreach (var item in formData.Where(x => !DefaultFields.Contains(x.Key)))
            {
                providedCustomFields.Add(item.Key, item.Value);
            }

            var customDataObject = formData.Get <IDictionary <string, object> >("customData");

            if (customDataObject != null && customDataObject.Any())
            {
                foreach (var item in customDataObject)
                {
                    providedCustomFields.Add(item.Key, item.Value);
                }
            }

            var jsonErrorHandler = new Func <string, CancellationToken, Task>((message, ct)
                                                                              => Error.Create(context, new BadRequest(message), ct));

            var newAccount = await InstantiateLocalAccount(
                context,
                model,
                allNonEmptyFieldNames,
                providedCustomFields,
                client,
                jsonErrorHandler,
                cancellationToken);

            if (newAccount == null)
            {
                return(true); // Some error occurred and the handler was invoked
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var executor = new RegisterExecutor(client, _configuration, _handlers, _logger);

            var createdAccount = await executor.HandleRegistrationAsync(context, application, newAccount, cancellationToken);

            await executor.HandlePostRegistrationAsync(context, createdAccount, cancellationToken);

            var sanitizer     = new AccountResponseSanitizer();
            var responseModel = new
            {
                account = sanitizer.Sanitize(createdAccount)
            };

            return(await JsonResponse.Ok(context, responseModel));
        }
Пример #2
0
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var model = await PostBodyParser.ToModel <LoginPostModel>(context, bodyContentType, _logger, cancellationToken);

            if (model.ProviderData != null)
            {
                return(await HandleSocialLogin(context, client, model, cancellationToken));
            }

            var jsonErrorHandler = new Func <string, CancellationToken, Task>((message, ct)
                                                                              => Error.Create(context, new BadRequest(message), ct));

            bool missingLoginOrPassword = string.IsNullOrEmpty(model.Login) || string.IsNullOrEmpty(model.Password);

            if (missingLoginOrPassword)
            {
                await jsonErrorHandler("Missing login or password.", cancellationToken);

                return(true);
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var executor = new LoginExecutor(client, _configuration, _handlers, _logger);

            var grantResult = await executor.PasswordGrantAsync(
                context,
                application,
                jsonErrorHandler,
                model.Login,
                model.Password,
                cancellationToken);

            if (grantResult == null)
            {
                return(true); // The error handler was invoked
            }

            await executor.HandlePostLoginAsync(context, grantResult, cancellationToken);

            var token = await grantResult.GetAccessTokenAsync(cancellationToken);

            var account = await token.GetAccountAsync(cancellationToken);

            var sanitizer     = new AccountResponseSanitizer();
            var responseModel = new
            {
                account = sanitizer.Sanitize(account)
            };

            return(await JsonResponse.Ok(context, responseModel));
        }
Пример #3
0
        private async Task <bool> HandleSocialLogin(IOwinEnvironment context, IClient client, LoginPostModel model,
                                                    CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(model.ProviderData.ProviderId))
            {
                return(await Error.Create(context, new BadRequest("No provider specified"), cancellationToken));
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var socialExecutor = new SocialExecutor(client, _configuration, _handlers, _logger);

            try
            {
                IProviderAccountRequest providerRequest;

                switch (model.ProviderData.ProviderId)
                {
                case "facebook":
                {
                    providerRequest = client.Providers()
                                      .Facebook()
                                      .Account()
                                      .SetAccessToken(model.ProviderData.AccessToken)
                                      .Build();
                    break;
                }

                case "google":
                {
                    providerRequest = client.Providers()
                                      .Google()
                                      .Account()
                                      .SetCode(model.ProviderData.Code)
                                      .Build();
                    break;
                }

                case "github":
                {
                    providerRequest = client.Providers()
                                      .Github()
                                      .Account()
                                      .SetAccessToken(model.ProviderData.AccessToken)
                                      .Build();
                    break;
                }

                case "linkedin":
                {
                    providerRequest = client.Providers()
                                      .LinkedIn()
                                      .Account()
                                      .SetAccessToken(model.ProviderData.AccessToken)
                                      .Build();
                    break;
                }

                default:
                    providerRequest = null;
                    break;
                }

                if (providerRequest == null)
                {
                    return(await Error.Create(context,
                                              new BadRequest($"Unknown provider '{model.ProviderData.ProviderId}'"), cancellationToken));
                }

                var loginResult =
                    await socialExecutor.LoginWithProviderRequestAsync(context, providerRequest, cancellationToken);

                await socialExecutor.HandleLoginResultAsync(
                    context,
                    application,
                    loginResult,
                    cancellationToken);

                var sanitizer     = new AccountResponseSanitizer();
                var responseModel = new
                {
                    account = sanitizer.Sanitize(loginResult.Account)
                };

                return(await JsonResponse.Ok(context, responseModel));
            }
            catch (ResourceException rex)
            {
                // TODO improve error logging (include request id, etc)
                _logger.Error(rex.DeveloperMessage, source: nameof(HandleSocialLogin));
                return(await Error.Create(context, new BadRequest("An error occurred while processing the login"), cancellationToken));
            }
            catch (Exception ex)
            {
                _logger.Error(ex, source: nameof(HandleSocialLogin));
                return(await Error.Create(context, new BadRequest("An error occurred while processing the login"), cancellationToken));
            }
        }
Пример #4
0
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var body = await context.Request.GetBodyAsStringAsync(cancellationToken);

            var model    = PostBodyParser.ToModel <RegisterPostModel>(body, bodyContentType, _logger);
            var formData = Serializer.DeserializeDictionary(body);

            var sanitizedFormData = new Dictionary <string, string>();
            var customFields      = new Dictionary <string, string>();

            // Look for a root object called "customData"
            var customDataObject = formData.Get <IDictionary <string, object> >("customData");

            if (customDataObject != null && customDataObject.Any())
            {
                foreach (var field in customDataObject)
                {
                    TryAdd(formData, field.Key, field.Value);
                }
            }

            foreach (var field in formData)
            {
                // The key "customData" is a special case, see above
                if (field.Key.Equals("customData", StringComparison.Ordinal))
                {
                    continue;
                }

                if (!DefaultFields.Contains(field.Key))
                {
                    TryAdd(customFields, field.Key, field.Value?.ToString());
                }

                TryAdd(sanitizedFormData, field.Key, field.Value?.ToString());
            }

            var allNonEmptyFieldNames = sanitizedFormData
                                        .Where(f => !string.IsNullOrEmpty(f.Value.ToString()))
                                        .Select(f => f.Key)
                                        .Distinct()
                                        .ToArray();

            var jsonErrorHandler = new Func <string, CancellationToken, Task>((message, ct)
                                                                              => Error.Create(context, new BadRequest(message), ct));

            var newAccount = await InstantiateLocalAccount(
                context,
                model,
                allNonEmptyFieldNames,
                customFields,
                client,
                jsonErrorHandler,
                cancellationToken);

            if (newAccount == null)
            {
                return(true); // Some error occurred and the handler was invoked
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var executor = new RegisterExecutor(client, _configuration, _handlers, _logger);

            var formDataForHandler = sanitizedFormData
                                     .ToDictionary(kv => kv.Key, kv => kv.Value?.ToString());

            var createdAccount = await executor.HandleRegistrationAsync(
                context,
                application,
                formDataForHandler,
                newAccount,
                jsonErrorHandler,
                cancellationToken);

            if (createdAccount == null)
            {
                return(true); // Some error occurred and the handler was invoked
            }

            await executor.HandlePostRegistrationAsync(context, createdAccount, cancellationToken);

            var sanitizer     = new AccountResponseSanitizer();
            var responseModel = new
            {
                account = sanitizer.Sanitize(createdAccount)
            };

            return(await JsonResponse.Ok(context, responseModel));
        }