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)); }
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)); }
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)); } }
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)); }