public async Task<bool> RenderAsync(string name, object model, IOwinEnvironment context, CancellationToken cancellationToken) { var httpContext = context.Request[MicrosoftHttpContextKey] as HttpContext; if (httpContext == null) { _logger.Error($"Request dictionary does not contain '{MicrosoftHttpContextKey}'", nameof(RazorViewRenderer)); return false; } // TODO ideally this would be done by the existing middleware pipeline // if authentication and view rendering were split up GetUserIdentity(httpContext, _logger); var actionContext = GetActionContext(httpContext); ViewEngineResult viewEngineResult; if (IsApplicationRelativePath(name)) { var basePath = Directory.GetCurrentDirectory(); _logger.Trace($"Getting view '{name}' relative to '{basePath}'"); viewEngineResult = _viewEngine.GetView(basePath, name, true); } else { viewEngineResult = _viewEngine.FindView(actionContext, name, true); } if (!viewEngineResult.Success) { _logger.Trace($"Could not find Razor view '{name}'", nameof(RazorViewRenderer)); return false; } var view = viewEngineResult.View; using (var writer = new StreamWriter(context.Response.Body)) { var viewDataDictionary = new ViewDataDictionary( new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model }; var viewContext = new ViewContext( actionContext, view, viewDataDictionary, new TempDataDictionary(actionContext.HttpContext, _tempDataProvider), writer, new HtmlHelperOptions()); cancellationToken.ThrowIfCancellationRequested(); await view.RenderAsync(viewContext); return true; } }
public Task <bool> HandleRedirectAsync(IOwinEnvironment context, string nextUri = null) { // Use the provided next URI, or default to stormpath.web.login.nextUri var parsedNextUri = string.IsNullOrEmpty(nextUri) ? new Uri(_configuration.Web.Login.NextUri, UriKind.Relative) : new Uri(nextUri, UriKind.RelativeOrAbsolute); // Ensure this is a relative URI var nextLocation = parsedNextUri.IsAbsoluteUri ? parsedNextUri.PathAndQuery : parsedNextUri.OriginalString; return(HttpResponse.Redirect(context, nextLocation)); }
protected override async Task <bool> GetHtmlAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken) { var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger); var stateToken = queryString.GetString("state"); var parsedStateToken = new StateTokenParser(client, _configuration.Client.ApiKey, stateToken, _logger); if (!parsedStateToken.Valid) { _logger.Warn("State token was invalid", nameof(GoogleCallbackRoute)); return(await HttpResponse.Redirect(context, SocialExecutor.CreateErrorUri(_configuration.Web.Login, stateToken: null))); } var code = queryString.GetString("code"); if (string.IsNullOrEmpty(code)) { _logger.Warn("Social code was empty", nameof(GithubCallbackRoute)); return(await HttpResponse.Redirect(context, SocialExecutor.CreateErrorUri(_configuration.Web.Login, stateToken))); } var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); var socialExecutor = new SocialExecutor(client, _configuration, _handlers, _logger); try { var providerRequest = client.Providers() .Google() .Account() .SetCode(code) .Build(); var loginResult = await socialExecutor.LoginWithProviderRequestAsync(context, providerRequest, cancellationToken); await socialExecutor.HandleLoginResultAsync( context, application, loginResult, cancellationToken); return(await socialExecutor.HandleRedirectAsync(client, context, loginResult, parsedStateToken.Path, cancellationToken)); } catch (Exception ex) { _logger.Warn($"Got '{ex.Message}' during social login request", source: nameof(GoogleCallbackRoute)); return(await HttpResponse.Redirect(context, SocialExecutor.CreateErrorUri(_configuration.Web.Login, stateToken))); } }
public async Task <bool> RenderAsync(string name, object model, IOwinEnvironment context, CancellationToken cancellationToken) { foreach (var renderer in _renderers) { if (await renderer.RenderAsync(name, model, context, cancellationToken)) { _logger.Info($"Rendered view '{name}' using {_rendererNames[renderer]}", nameof(CompositeViewRenderer)); return(true); } } _logger.Error($"Could not render view '{name}' using any available renderer", nameof(CompositeViewRenderer)); return(false); }
protected override Task <bool> PostAsync( IOwinEnvironment context, IClient client, ContentNegotiationResult contentNegotiationResult, CancellationToken cancellationToken) { // The Stormpath middleware uses POSTs to /logout to avoid GETs mutating state, // so we need to account for that here var options = _options as IdSiteRedirectOptions ?? new IdSiteRedirectOptions(); return(options.Logout ? HandleIdSiteRedirectAsync(context, client, cancellationToken) : Task.FromResult(false)); }
public static void AddTokenCookiesToResponse(IOwinEnvironment context, IClient client, IOauthGrantAuthenticationResult grantResult, StormpathConfiguration configuration, ILogger logger) { if (!string.IsNullOrEmpty(grantResult.AccessTokenString)) { var expirationDate = client.NewJwtParser().Parse(grantResult.AccessTokenString).Body.Expiration; SetTokenCookie(context, configuration.Web.AccessTokenCookie, grantResult.AccessTokenString, expirationDate, IsSecureRequest(context), logger); } if (!string.IsNullOrEmpty(grantResult.RefreshTokenString)) { var expirationDate = client.NewJwtParser().Parse(grantResult.RefreshTokenString).Body.Expiration; SetTokenCookie(context, configuration.Web.RefreshTokenCookie, grantResult.RefreshTokenString, expirationDate, IsSecureRequest(context), logger); } }
private async Task <bool> LoginAndRedirectAsync( IOwinEnvironment context, IClient client, IOauthGrantAuthenticationResult grantResult, string nextPath, CancellationToken cancellationToken) { var executor = new LoginExecutor(client, _configuration, _handlers, _logger); await executor.HandlePostLoginAsync(context, grantResult, cancellationToken); await executor.HandleRedirectAsync(context, nextPath); return(true); }
protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken) { var model = await PostBodyParser.ToModel <VerifyEmailPostModel>(context, bodyContentType, _logger, cancellationToken); var jsonSuccessHandler = new Func <CancellationToken, Task <bool> >(ct => JsonResponse.Ok(context)); return(await ResendVerification( email : model.Email, client : client, environment : context, errorHandler : null, // Errors are caught in AbstractRouteMiddleware successHandler : jsonSuccessHandler, cancellationToken : cancellationToken)); }
public async Task HandlePostLoginAsync( IOwinEnvironment context, IOauthGrantAuthenticationResult grantResult, CancellationToken cancellationToken) { var accessToken = await grantResult.GetAccessTokenAsync(cancellationToken); var account = await accessToken.GetAccountAsync(cancellationToken); var postLoginHandlerContext = new PostLoginContext(context, account); await _handlers.PostLoginHandler(postLoginHandlerContext, cancellationToken); // Add Stormpath cookies Cookies.AddTokenCookiesToResponse(context, _client, grantResult, _configuration, _logger); }
public async Task <bool> HandleRedirectAsync( IClient client, IOwinEnvironment environment, ExternalLoginResult loginResult, string nextUri, CancellationToken cancellationToken) { var loginExecutor = new LoginExecutor(_client, _configuration, _handlers, _logger); var defaultNextPath = loginResult.IsNewAccount ? _configuration.Web.Register.NextUri : _configuration.Web.Login.NextUri; return(await loginExecutor.HandleRedirectAsync(environment, nextUri, defaultNextPath)); }
protected virtual Task <bool> GetAsync(IOwinEnvironment context, IClient client, ContentNegotiationResult contentNegotiationResult, CancellationToken cancellationToken) { if (contentNegotiationResult.ContentType == ContentType.Json) { return(GetJsonAsync(context, client, cancellationToken)); } if (contentNegotiationResult.ContentType == ContentType.Html) { return(GetHtmlAsync(context, client, cancellationToken)); } // Do nothing and pass on to next middleware. return(Task.FromResult(false)); }
public async Task <ExternalLoginResult> LoginWithProviderRequestAsync( IOwinEnvironment environment, IProviderAccountRequest providerRequest, CancellationToken cancellationToken) { var application = await _client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); var result = await application.GetAccountAsync(providerRequest, cancellationToken); return(new ExternalLoginResult { Account = result.Account, IsNewAccount = result.IsNewAccount }); }
private async Task <bool> ExecuteRefreshFlow(IOwinEnvironment context, IClient client, string refreshToken, CancellationToken cancellationToken) { var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); var refreshGrantRequest = OauthRequests.NewRefreshGrantRequest() .SetRefreshToken(refreshToken) .Build(); var tokenResult = await application.NewRefreshGrantAuthenticator() .AuthenticateAsync(refreshGrantRequest, cancellationToken); var sanitizer = new GrantResultResponseSanitizer(); return(await JsonResponse.Ok(context, sanitizer.SanitizeResponseWithRefreshToken(tokenResult)).ConfigureAwait(false)); }
private string CreateFullUserAgent(IOwinEnvironment context) { var callingAgent = string.Empty; if (context != null) { callingAgent = string .Join(" ", context.Request.Headers.Get("X-Stormpath-Agent") ?? new string[0]) .Trim(); } return(string .Join(" ", callingAgent, userAgentBuilder.GetUserAgent()) .Trim()); }
public async Task <IOauthGrantAuthenticationResult> PasswordGrantAsync( IOwinEnvironment environment, IApplication application, Func <string, CancellationToken, Task> errorHandler, string login, string password, CancellationToken cancellationToken) { var preLoginHandlerContext = new PreLoginContext(environment) { Login = login }; await _handlers.PreLoginHandler(preLoginHandlerContext, cancellationToken); if (preLoginHandlerContext.Result != null) { if (!preLoginHandlerContext.Result.Success) { var message = string.IsNullOrEmpty(preLoginHandlerContext.Result.ErrorMessage) ? "An error has occurred. Please try again." : preLoginHandlerContext.Result.ErrorMessage; await errorHandler(message, cancellationToken); return(null); } } var passwordGrantRequest = OauthRequests.NewPasswordGrantRequest() .SetLogin(preLoginHandlerContext.Login) .SetPassword(password); if (preLoginHandlerContext.AccountStore != null) { passwordGrantRequest.SetAccountStore(preLoginHandlerContext.AccountStore); } if (!string.IsNullOrEmpty(preLoginHandlerContext.OrganizationNameKey)) { passwordGrantRequest.SetOrganizationNameKey(preLoginHandlerContext.OrganizationNameKey); } var passwordGrantAuthenticator = application.NewPasswordGrantAuthenticator(); var grantResult = await passwordGrantAuthenticator .AuthenticateAsync(passwordGrantRequest.Build(), cancellationToken); return(grantResult); }
public static async Task <bool> Create(IOwinEnvironment context, int statusCode, string message, CancellationToken cancellationToken) { context.Response.StatusCode = statusCode; context.Response.Headers.SetString("Content-Type", Constants.JsonContentType); Caching.AddDoNotCacheHeaders(context); var errorModel = new { status = statusCode, message = message }; await context.Response.WriteAsync(Serializer.Serialize(errorModel), Encoding.UTF8, cancellationToken); return(true); }
public Task <bool> HandleRedirectAsync( IOwinEnvironment environment, IApplication application, IAccount createdAccount, RegisterPostModel postModel, Func <string, CancellationToken, Task> errorHandler, string stateToken, CancellationToken cancellationToken) { if (_configuration.Web.Register.AutoLogin && createdAccount.Status != AccountStatus.Unverified) { return(HandleAutologinAsync(environment, application, errorHandler, postModel, stateToken, cancellationToken)); } string nextUri; if (createdAccount.Status == AccountStatus.Enabled) { nextUri = $"{_configuration.Web.Login.Uri}?status=created"; } else if (createdAccount.Status == AccountStatus.Unverified) { nextUri = $"{_configuration.Web.Login.Uri}?status=unverified"; } else { nextUri = _configuration.Web.Login.Uri; } // Preserve the state token so that the login page can redirect after login if necessary if (!string.IsNullOrEmpty(stateToken)) { if (nextUri.Contains("?")) { nextUri += "&"; } else { nextUri += "?"; } nextUri += $"{StringConstants.StateTokenName}={stateToken}"; } return(HttpResponse.Redirect(environment, nextUri)); }
private async Task <bool> LoginAndRedirectAsync( IOwinEnvironment context, IClient client, IOauthGrantAuthenticationResult grantResult, bool isNewAccount, string nextPath, CancellationToken cancellationToken) { var executor = new LoginExecutor(client, _configuration, _handlers, _logger); await executor.HandlePostLoginAsync(context, grantResult, cancellationToken); var defaultNextPath = isNewAccount ? _configuration.Web.Register.NextUri : _configuration.Web.Login.NextUri; return(await executor.HandleRedirectAsync(context, nextPath, defaultNextPath)); }
protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken) { var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); try { var model = await PostBodyParser.ToModel <ForgotPasswordPostModel>(context, bodyContentType, _logger, cancellationToken); await application.SendPasswordResetEmailAsync(model.Email, cancellationToken); } catch (Exception ex) { _logger.Error(ex, source: "ForgotRoute.PostJson"); } return(await JsonResponse.Ok(context)); }
private async Task <IAccount> ValidateApiCredentialsAsync( IOwinEnvironment context, IClient client, string id, string secret, CancellationToken cancellationToken) { var application = await client .GetApplicationAsync(Configuration.Application.Href, cancellationToken) .ConfigureAwait(false); var apiKey = await application .GetApiKeys() .Where(x => x.Id == id) .SingleOrDefaultAsync(cancellationToken) .ConfigureAwait(false); if (apiKey == null) { logger.Info($"API key with ID {id} was not found", nameof(ValidateApiCredentialsAsync)); return(null); } if (apiKey.Status != ApiKeyStatus.Enabled) { logger.Info($"API key with ID {id} was found, but was disabled", nameof(ValidateApiCredentialsAsync)); return(null); } if (!apiKey.Secret.Equals(secret, StringComparison.Ordinal)) { logger.Info($"API key with ID {id} was found, but secret did not match", nameof(ValidateApiCredentialsAsync)); return(null); } var account = await apiKey.GetAccountAsync(cancellationToken).ConfigureAwait(false); if (account.Status != AccountStatus.Enabled) { logger.Info($"API key with ID {id} was found, but the account is not enabled", nameof(ValidateApiCredentialsAsync)); return(null); } return(account); }
private async Task <IAccount> ValidateAccessTokenAsync(IOwinEnvironment context, IClient client, string accessTokenJwt) { var request = OauthRequests.NewJwtAuthenticationRequest() .SetJwt(accessTokenJwt) .Build(); var application = await client.GetApplicationAsync(this.Configuration.Application.Href, context.CancellationToken); var authenticator = application.NewJwtAuthenticator(); if (this.Configuration.Web.Oauth2.Password.ValidationStrategy == WebOauth2TokenValidationStrategy.Local) { authenticator.WithLocalValidation(); } IAccessToken result = null; try { result = await authenticator.AuthenticateAsync(request, context.CancellationToken); } catch (InvalidJwtException jwex) { logger.Info($"Failed to authenticate the request due to a malformed or expired access token. Message: '{jwex.Message}'", nameof(ValidateAccessTokenAsync)); return(null); } catch (ResourceException rex) { logger.Warn(rex, "Failed to authenticate the request. Invalid access_token found.", nameof(ValidateAccessTokenAsync)); return(null); } IAccount account = null; try { account = await GetExpandedAccountAsync(client, result, context.CancellationToken); } catch (ResourceException ex) { logger.Error(ex, $"Failed to get account {result.AccountHref}", nameof(ValidateAccessTokenAsync)); } return(account); }
public static async Task <bool> Create(IOwinEnvironment context, AbstractError error, CancellationToken cancellationToken) { context.Response.StatusCode = error.StatusCode; if (error.Body != null) { context.Response.Headers.SetString("Content-Type", Constants.JsonContentType); Caching.AddDoNotCacheHeaders(context); await context.Response.WriteAsync(Serializer.Serialize(error.Body), Encoding.UTF8, cancellationToken); return(true); } else { return(true); } }
public async Task <bool> RenderAsync(string name, object model, IOwinEnvironment context, CancellationToken cancellationToken) { var view = ViewResolver.GetView(name); if (view == null) { _logger.Trace($"View '{name}' is not a precompiled view", nameof(PrecompiledViewRenderer)); return(false); } cancellationToken.ThrowIfCancellationRequested(); _logger.Trace($"Rendering precompiled view '{name}'", nameof(PrecompiledViewRenderer)); await view.ExecuteAsync(model, context.Response.Body); return(true); }
private Task <bool> HandleRequestAsync(IOwinEnvironment context, IClient scopedClient, ContentNegotiationResult contentNegotiationResult, CancellationToken cancellationToken) { var method = context.Request.Method; if (method.Equals("GET", StringComparison.OrdinalIgnoreCase)) { return(GetAsync(context, scopedClient, contentNegotiationResult, cancellationToken)); } if (method.Equals("POST", StringComparison.OrdinalIgnoreCase)) { return(PostAsync(context, scopedClient, contentNegotiationResult, cancellationToken)); } // Do nothing and pass on to next middleware. _logger.Trace("Request method was not GET or POST", nameof(HandleRequestAsync)); return(Task.FromResult(false)); }
protected override async Task <bool> PostAsync( IOwinEnvironment context, IClient client, ContentNegotiationResult acceptContentNegotiationResult, CancellationToken cancellationToken) { var executor = new LogoutExecutor(client, _configuration, _handlers, _logger); await executor.HandleLogoutAsync(context, cancellationToken); if (acceptContentNegotiationResult.ContentType == ContentType.Html) { return(await executor.HandleRedirectAsync(context)); } await JsonResponse.Ok(context); return(true); }
protected override async Task <bool> GetJsonAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken) { var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger); var spToken = queryString.GetString("sptoken"); if (string.IsNullOrEmpty(spToken)) { return(await Error.Create(context, new BadRequest("sptoken parameter not provided."), cancellationToken)); } var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); await application.VerifyPasswordResetTokenAsync(spToken, cancellationToken); // Errors are caught in AbstractRouteMiddleware return(await JsonResponse.Ok(context)); }
private Task <IAccount> TryBasicAuthenticationAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken) { try { var basicHeaderParser = new BasicAuthenticationParser(context.Request.Headers.GetString("Authorization"), logger); if (!basicHeaderParser.IsValid) { return(Task.FromResult <IAccount>(null)); } logger.Info("Using Basic header to authenticate request", nameof(TryBasicAuthenticationAsync)); return(ValidateApiCredentialsAsync(context, client, basicHeaderParser.Username, basicHeaderParser.Password, cancellationToken)); } catch (Exception ex) { logger.Warn(ex, source: nameof(TryBasicAuthenticationAsync)); return(Task.FromResult <IAccount>(null)); } }
protected override async Task <bool> GetJsonAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken) { var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger); var spToken = queryString.GetString("sptoken"); if (string.IsNullOrEmpty(spToken)) { return(await Error.Create(context, new BadRequest("sptoken parameter not provided."), cancellationToken)); } var account = await client.VerifyAccountEmailAsync(spToken, cancellationToken); // Errors are caught in AbstractRouteMiddleware var postVerifyEmailContext = new PostVerifyEmailContext(context, account); await _handlers.PostVerifyEmailHandler(postVerifyEmailContext, cancellationToken); return(await JsonResponse.Ok(context)); }
protected override async Task <bool> GetJsonAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken) { Caching.AddDoNotCacheHeaders(context); var stormpathAccount = context.Request[OwinKeys.StormpathUser] as IAccount; var expansionOptions = _configuration.Web.Me.Expand; if (expansionOptions.Any(e => e.Value)) { stormpathAccount = await GetExpandedAccount(stormpathAccount.Href, client, expansionOptions, cancellationToken); } var responseModel = new { account = await SanitizeExpandedAccount(stormpathAccount, expansionOptions, cancellationToken) }; return(await JsonResponse.Ok(context, responseModel)); }
private async Task RevokeHeaderToken(IOwinEnvironment context, IClient client, CancellationToken cancellationToken) { var bearerHeaderParser = new BearerAuthenticationParser(context.Request.Headers.GetString("Authorization"), _logger); if (!bearerHeaderParser.IsValid) { return; } var revoker = new TokenRevoker(client, _logger) .AddToken(bearerHeaderParser.Token); try { await revoker.Revoke(cancellationToken); } catch (Exception ex) { _logger.Info(ex.Message, source: nameof(RevokeCookieTokens)); } }
protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken) { var model = await PostBodyParser.ToModel <ChangePasswordPostModel>(context, bodyContentType, _logger, cancellationToken); var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken); var account = await application.VerifyPasswordResetTokenAsync(model.SpToken, cancellationToken); // Errors are caught in AbstractRouteMiddleware var preChangePasswordContext = new PreChangePasswordContext(context, account); await _handlers.PreChangePasswordHandler(preChangePasswordContext, cancellationToken); await application.ResetPasswordAsync(model.SpToken, model.Password, cancellationToken); var postChangePasswordContext = new PostChangePasswordContext(context, account); await _handlers.PostChangePasswordHandler(postChangePasswordContext, cancellationToken); // TODO autologin return(await JsonResponse.Ok(context)); }