public void Json_preferred_and_in_produces() { var result = ContentNegotiation.NegotiateAcceptHeader(ApplicationJson, DefaultProduces, logger: null); result.Success.Should().BeTrue(); result.ContentType.ToString().Should().Be(ApplicationJson); }
public void StarStar_header_serves_first_produces() { var result = ContentNegotiation.NegotiateAcceptHeader(null, DefaultProduces, logger: null); result.Success.Should().BeTrue(); result.ContentType.ToString().Should().Be(DefaultProduces.First()); }
public void Form_urlencoded_is_valid_post_body_type() { var result = ContentNegotiation.DetectBodyType(FormUrlEncoded); result.Success.Should().BeTrue(); result.ContentType.ToString().Should().Be(FormUrlEncoded); }
public void Json_is_valid_post_body_type() { var result = ContentNegotiation.DetectBodyType(ApplicationJson); result.Success.Should().BeTrue(); result.ContentType.ToString().Should().Be(ApplicationJson); }
/// <summary> /// Redirects or responds to an unauthorized request. /// </summary> /// <remarks>Uses the Actions passed to the <see cref="RouteProtector"/> to execute this logic in a framework-agnostic way.</remarks> /// <param name="acceptHeader">The HTTP <c>Accept</c> header of this request.</param> /// <param name="requestPath">The OWIN request path of this request.</param> public void OnUnauthorized(string acceptHeader, string requestPath) { _deleteCookie(_configuration.Web.AccessTokenCookie); _deleteCookie(_configuration.Web.RefreshTokenCookie); var contentNegotiationResult = ContentNegotiation.NegotiateAcceptHeader(acceptHeader, _configuration.Web.Produces, _logger); bool isHtmlRequest = contentNegotiationResult.Success && contentNegotiationResult.ContentType == ContentType.Html; if (isHtmlRequest) { var redirectTokenBuilder = new StateTokenBuilder(_client, _configuration.Client.ApiKey) { Path = requestPath }; var loginUri = $"{_configuration.Web.Login.Uri}?{StringConstants.StateTokenName}={redirectTokenBuilder}"; _setStatusCode(302); _redirect(loginUri); } else { _setStatusCode(401); _setHeader("WWW-Authenticate", $"Bearer realm=\"{_configuration.Application.Name}\""); } }
public void Html_preferred_but_not_in_produces() { var producesOnlyJson = new string[] { ApplicationJson }; var result = ContentNegotiation.NegotiateAcceptHeader("text/html", producesOnlyJson, logger: null); result.Success.Should().BeFalse(); }
public void Json_preferred_but_not_in_produces() { var producesOnlyHtml = new string[] { TextHtml }; var result = ContentNegotiation.NegotiateAcceptHeader(ApplicationJson, producesOnlyHtml, logger: null); result.Success.Should().BeFalse(); }
public void Complex_scenario_1_is_html() { var headerValue = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; var result = ContentNegotiation.NegotiateAcceptHeader(headerValue, DefaultProduces, logger: null); result.Success.Should().BeTrue(); result.ContentType.ToString().Should().Be(TextHtml); }
public void Json_preferred_with_implicit_quality_factor() { var headerValue = "text/html; q=0.8, application/json"; var result = ContentNegotiation.NegotiateAcceptHeader(headerValue, DefaultProduces, logger: null); result.Success.Should().BeTrue(); result.ContentType.ToString().Should().Be(ApplicationJson); }
public void Html_preferred_with_higher_quality_factor() { var headerValue = "application/json; q=0.8, text/html;q=0.9"; var result = ContentNegotiation.NegotiateAcceptHeader(headerValue, DefaultProduces, logger: null); result.Success.Should().BeTrue(); result.ContentType.ToString().Should().Be(TextHtml); }
public async Task <bool> InvokeAsync(IOwinEnvironment owinContext) { if (!_initialized) { throw new InvalidOperationException("Route has not been initialized."); } var acceptHeader = owinContext.Request.Headers.GetString("Accept"); var contentNegotiationResult = ContentNegotiation.NegotiateAcceptHeader(acceptHeader, _configuration.Web.Produces, _logger); if (!contentNegotiationResult.Success) { _logger.Trace($"Content negotiation failed for request {owinContext.Request.Path}. Skipping", nameof(InvokeAsync)); return(false); } try { return(await HandleRequestAsync(owinContext, _client, contentNegotiationResult, owinContext.CancellationToken)); } catch (ResourceException rex) { if (contentNegotiationResult.ContentType == ContentType.Json) { // Sanitize Stormpath API errors await Error.CreateFromApiError(owinContext, rex, owinContext.CancellationToken); return(true); } else { // todo handle framework errors _logger.Error(rex, source: nameof(InvokeAsync)); throw; } } catch (Exception ex) { if (contentNegotiationResult.ContentType == ContentType.Json) { // Sanitize framework-level errors await Error.Create(owinContext, 400, ex.Message, owinContext.CancellationToken); return(true); } else { // todo handle framework errors _logger.Error(ex, source: nameof(InvokeAsync)); throw; } } }
public void TestContentNegotiation(string accept, string acceptable, bool result) { var headerDict = new HeaderDictionary(); headerDict.Add(KeyValuePair.Create <string, StringValues>("Accept", accept)); var mockRequest = new Mock <HttpRequest>(); mockRequest.Setup(x => x.Headers).Returns(headerDict); var acc = ContentNegotiation.IsAcceptable(mockRequest.Object, acceptable); Assert.Equal(result, acc); }
protected virtual Task <bool> PostAsync(IOwinEnvironment context, IClient client, ContentNegotiationResult contentNegotiationResult, CancellationToken cancellationToken) { var rawBodyContentType = context.Request.Headers.GetString("Content-Type"); var bodyContentTypeDetectionResult = ContentNegotiation.DetectBodyType(rawBodyContentType); if (!bodyContentTypeDetectionResult.Success) { throw new Exception($"The Content-Type '{rawBodyContentType}' is invalid."); } if (contentNegotiationResult.ContentType == ContentType.Json) { return(PostJsonAsync(context, client, bodyContentTypeDetectionResult.ContentType, cancellationToken)); } if (contentNegotiationResult.ContentType == ContentType.Html) { return(PostHtmlAsync(context, client, bodyContentTypeDetectionResult.ContentType, cancellationToken)); } // Do nothing and pass on to next middleware. return(Task.FromResult(false)); }
public void TextHtml_is_valid_post_body_type() { var result = ContentNegotiation.DetectBodyType(TextHtml); result.Success.Should().BeFalse(); }
public void TextPlain_is_valid_post_body_type() { var result = ContentNegotiation.DetectBodyType("text/plain"); result.Success.Should().BeFalse(); }
public void Unsupported_header_fails() { var result = ContentNegotiation.NegotiateAcceptHeader("foo/bar", DefaultProduces, logger: null); result.Success.Should().BeFalse(); }
public static void Configure(HttpConfiguration httpConfiguration) { ContentNegotiation.Configure(httpConfiguration); Formatters.Configure(httpConfiguration); Routing.Configure(httpConfiguration); }
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)); }
public static void AddJwtAuth(this IServiceCollection services, JwtSettings settings) { services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(x => { x.RequireHttpsMetadata = false; x.SaveToken = true; var jwtSharedKey = System.Text.Encoding.UTF8.GetBytes(settings.Secret); x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(jwtSharedKey), ValidateIssuer = true, ValidIssuer = settings.Issuer, ValidateAudience = false }; x.Events = new JwtBearerEvents { OnChallenge = c => { // if this is a browser request the auth-redirect process should be started if (ContentNegotiation.IsAcceptable(c.Request, "text/html")) { return(Task.FromException(new LoginChallengeException("Browser login challenge start"))); } return(Task.CompletedTask); }, OnTokenValidated = c => { if (c.Principal.Identity.IsAuthenticated) { // after authentication is performed ensure that the user // has the necessary rights to access the resources var user = c.Principal.Get(); var principal = Authorization.IsAuthorized(c.Principal, settings.Claims, settings.Issuer); if (principal == null) { return(Task.FromException(new AuthorizationException("Browser login challenge start"))); } c.Principal = principal; return(Task.FromResult(true)); } return(Task.FromResult(false)); }, OnMessageReceived = c => { if (string.IsNullOrEmpty(c.Token)) { // the token was not received from the "expected location" // fetch the token from the cookie instead! var jwtCookiePayload = c.Request.Cookies[settings.CookieName]; if (!string.IsNullOrEmpty(jwtCookiePayload)) { c.Token = jwtCookiePayload; } } if (string.IsNullOrEmpty(c.Token)) { return(Task.FromResult(false)); } return(Task.FromResult(true)); } }; }); }