protected override async Task <bool> PostHtmlAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken) { var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); try { var body = await context.Request.GetBodyAsStringAsync(cancellationToken); var model = PostBodyParser.ToModel <ForgotPasswordPostModel>(body, bodyContentType, _logger); var formData = FormContentParser.Parse(body, _logger); var stateToken = formData.GetString(StringConstants.StateTokenName); var parsedStateToken = new StateTokenParser(client, _configuration.Client.ApiKey, stateToken, _logger); if (!parsedStateToken.Valid) { var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger); var viewModelBuilder = new ForgotPasswordFormViewModelBuilder(client, _configuration, queryString); var viewModel = viewModelBuilder.Build(); viewModel.Errors.Add("An error occurred. Please try again."); await RenderViewAsync(context, _configuration.Web.ForgotPassword.View, viewModel, cancellationToken); return(true); } await application.SendPasswordResetEmailAsync(model.Email, cancellationToken); } catch (Exception ex) { _logger.Error(ex, source: "ForgotRoute.PostHtml"); } return(await HttpResponse.Redirect(context, _configuration.Web.ForgotPassword.NextUri)); }
protected override async Task <bool> PostHtmlAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken) { var htmlErrorHandler = new Func <string, CancellationToken, Task <bool> >(async(error, ct) => { var viewModelBuilder = new VerifyEmailFormViewModelBuilder(client, _configuration); var verifyEmailViewModel = viewModelBuilder.Build(); verifyEmailViewModel.Errors.Add(error); await RenderViewAsync(context, _configuration.Web.VerifyEmail.View, verifyEmailViewModel, cancellationToken); return(true); }); var body = await context.Request.GetBodyAsStringAsync(cancellationToken); var model = PostBodyParser.ToModel <VerifyEmailPostModel>(body, bodyContentType, _logger); var formData = FormContentParser.Parse(body, _logger); var stateToken = formData.GetString(StringConstants.StateTokenName); var parsedStateToken = new StateTokenParser(client, _configuration.Client.ApiKey, stateToken, _logger); if (!parsedStateToken.Valid) { await htmlErrorHandler("An error occurred. Please try again.", cancellationToken); return(true); } var htmlSuccessHandler = new Func <CancellationToken, Task <bool> >( ct => HttpResponse.Redirect(context, $"{_configuration.Web.Login.Uri}?status=unverified")); return(await ResendVerification( model.Email, client, context, htmlErrorHandler, htmlSuccessHandler, cancellationToken)); }
protected override async Task <bool> PostHtmlAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken) { var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger); var body = await context.Request.GetBodyAsStringAsync(cancellationToken); var model = PostBodyParser.ToModel <ChangePasswordPostModel>(body, bodyContentType, _logger); var formData = FormContentParser.Parse(body, _logger); var stateToken = formData.GetString(StringConstants.StateTokenName); var parsedStateToken = new StateTokenParser(client, _configuration.Client.ApiKey, stateToken, _logger); if (!parsedStateToken.Valid) { var viewModelBuilder = new ChangePasswordFormViewModelBuilder(client, _configuration); var changePasswordViewModel = viewModelBuilder.Build(); changePasswordViewModel.Errors.Add("An error occurred. Please try again."); await RenderViewAsync(context, _configuration.Web.ChangePassword.View, changePasswordViewModel, cancellationToken); return(true); } if (!model.Password.Equals(model.ConfirmPassword, StringComparison.Ordinal)) { var viewModelBuilder = new ChangePasswordFormViewModelBuilder(client, _configuration); var changePasswordViewModel = viewModelBuilder.Build(); changePasswordViewModel.Errors.Add("Passwords do not match."); await RenderViewAsync(context, _configuration.Web.ChangePassword.View, changePasswordViewModel, cancellationToken); return(true); } var spToken = queryString.GetString("sptoken"); var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); IAccount account; try { account = await application.VerifyPasswordResetTokenAsync(spToken, cancellationToken); } catch (ResourceException) { return(await HttpResponse.Redirect(context, _configuration.Web.ChangePassword.ErrorUri)); } var preChangePasswordContext = new PreChangePasswordContext(context, account); await _handlers.PreChangePasswordHandler(preChangePasswordContext, cancellationToken); try { await application.ResetPasswordAsync(spToken, model.Password, cancellationToken); } catch (ResourceException rex) { var viewModelBuilder = new ChangePasswordFormViewModelBuilder(client, _configuration); var changePasswordViewModel = viewModelBuilder.Build(); changePasswordViewModel.Errors.Add(rex.Message); await RenderViewAsync(context, _configuration.Web.ChangePassword.View, changePasswordViewModel, cancellationToken); return(true); } var postChangePasswordContext = new PostChangePasswordContext(context, account); await _handlers.PostChangePasswordHandler(postChangePasswordContext, cancellationToken); // TODO autologin return(await HttpResponse.Redirect(context, _configuration.Web.ChangePassword.NextUri)); }
protected override async Task <bool> PostAsync(IOwinEnvironment context, IClient client, ContentNegotiationResult contentNegotiationResult, CancellationToken cancellationToken) { Caching.AddDoNotCacheHeaders(context); var rawBodyContentType = context.Request.Headers.GetString("Content-Type"); var bodyContentTypeDetectionResult = ContentNegotiation.DetectBodyType(rawBodyContentType); var isValidContentType = bodyContentTypeDetectionResult.Success && bodyContentTypeDetectionResult.ContentType == ContentType.FormUrlEncoded; if (!isValidContentType) { await Error.Create <OauthInvalidRequest>(context, cancellationToken); return(true); } var requestBody = await context.Request.GetBodyAsStringAsync(cancellationToken); var formData = FormContentParser.Parse(requestBody, _logger); var grantType = formData.GetString("grant_type"); if (string.IsNullOrEmpty(grantType)) { await Error.Create <OauthInvalidRequest>(context, cancellationToken); return(true); } try { if (grantType.Equals("client_credentials", StringComparison.OrdinalIgnoreCase) && _configuration.Web.Oauth2.Client_Credentials.Enabled) { await ExecuteClientCredentialsFlow(context, client, cancellationToken); return(true); } if (grantType.Equals("password", StringComparison.OrdinalIgnoreCase) && _configuration.Web.Oauth2.Password.Enabled) { var username = WebUtility.UrlDecode(formData.GetString("username")); var password = WebUtility.UrlDecode(formData.GetString("password")); await ExecutePasswordFlow(context, client, username, password, cancellationToken); return(true); } if (grantType.Equals("refresh_token", StringComparison.OrdinalIgnoreCase) && _configuration.Web.Oauth2.Password.Enabled) { var refreshToken = WebUtility.UrlDecode(formData.GetString("refresh_token")); await ExecuteRefreshFlow(context, client, refreshToken, cancellationToken); return(true); } } catch (ResourceException rex) { // Special handling of API errors for the OAuth route return(await Error.Create(context, new OauthError(rex.Message, rex.GetProperty("error")), cancellationToken)); } return(await Error.Create <OauthUnsupportedGrant>(context, cancellationToken)); }
protected override async Task <bool> PostHtmlAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken) { var body = await context.Request.GetBodyAsStringAsync(cancellationToken); var model = PostBodyParser.ToModel <LoginPostModel>(body, bodyContentType, _logger); var formData = FormContentParser.Parse(body, _logger); var htmlErrorHandler = new Func <string, CancellationToken, Task>((message, ct) => { var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger); return(RenderLoginViewAsync( client, context, cancellationToken, queryString, formData, errors: new[] { message })); }); var stateToken = formData.GetString(StringConstants.StateTokenName); var parsedStateToken = new StateTokenParser(client, _configuration.Client.ApiKey, stateToken, _logger); if (!parsedStateToken.Valid) { await htmlErrorHandler("An error occurred. Please try again.", cancellationToken); return(true); } bool missingLoginOrPassword = string.IsNullOrEmpty(model.Login) || string.IsNullOrEmpty(model.Password); if (missingLoginOrPassword) { await htmlErrorHandler("The login and password fields are required.", cancellationToken); return(true); } var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); var executor = new LoginExecutor(client, _configuration, _handlers, _logger); try { var grantResult = await executor.PasswordGrantAsync( context, application, htmlErrorHandler, model.Login, model.Password, cancellationToken); if (grantResult == null) { return(true); // The error handler was invoked } await executor.HandlePostLoginAsync(context, grantResult, cancellationToken); } catch (ResourceException rex) { await htmlErrorHandler(rex.Message, cancellationToken); return(true); } var nextUri = parsedStateToken.Path; // Might be null return(await executor.HandleRedirectAsync(context, nextUri)); }
protected override async Task <bool> PostHtmlAsync(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 = FormContentParser.Parse(body, _logger); var htmlErrorHandler = new Func <string, CancellationToken, Task>((message, ct) => { var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger); var viewModelBuilder = new RegisterFormViewModelBuilder(client, _configuration, queryString, formData, _logger); var registerViewModel = viewModelBuilder.Build(); registerViewModel.Errors.Add(message); return(RenderViewAsync(context, _configuration.Web.Register.View, registerViewModel, cancellationToken)); }); var stateToken = formData.GetString(StringConstants.StateTokenName); var parsedStateToken = new StateTokenParser(client, _configuration.Client.ApiKey, stateToken, _logger); if (!parsedStateToken.Valid) { await htmlErrorHandler("An error occurred. Please try again.", cancellationToken); return(true); } var allNonEmptyFieldNames = formData .Where(f => !string.IsNullOrEmpty(string.Join(",", f.Value))) .Select(f => f.Key) .Except(new [] { StringConstants.StateTokenName }) .ToList(); var providedCustomFields = new Dictionary <string, string>(); var nonCustomFields = DefaultFields.Concat(new[] { StringConstants.StateTokenName }).ToArray(); foreach (var item in formData.Where(f => !nonCustomFields.Contains(f.Key))) { providedCustomFields.Add(item.Key, string.Join(",", item.Value)); } var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); var executor = new RegisterExecutor(client, _configuration, _handlers, _logger); try { var newAccount = await InstantiateLocalAccount( context, model, allNonEmptyFieldNames, providedCustomFields, client, htmlErrorHandler, cancellationToken); if (newAccount == null) { return(true); // Some error occurred and the handler was invoked } var formDataForHandler = formData .ToDictionary(kv => kv.Key, kv => string.Join(",", kv.Value)); var createdAccount = await executor.HandleRegistrationAsync( context, application, formDataForHandler, newAccount, htmlErrorHandler, cancellationToken); if (createdAccount == null) { return(true); // Some error occurred and the handler was invoked } await executor.HandlePostRegistrationAsync(context, createdAccount, cancellationToken); return(await executor.HandleRedirectAsync( context, application, createdAccount, model, htmlErrorHandler, stateToken, cancellationToken)); } catch (ResourceException rex) { await htmlErrorHandler(rex.Message, cancellationToken); return(true); } }