/// <summary> /// Validates the specified request. /// </summary> /// <param name="request">The <see cref="HttpRequestMessage"/> to validate</param> /// <param name="resolver">An account name to shared secret resolver.</param> /// <param name="maxAge">The maximum age of a message that will be accepted</param> /// <returns>A ClaimsPrincipal for the the identity which owns the message.</returns> public static ClaimsPrincipal Validate(HttpRequestMessage request, Func <string, byte[]> resolver, TimeSpan maxAge) { AuthenticationHeaderValue authenticationHeader = null; if (request.Headers != null) { authenticationHeader = request.Headers.Authorization; } string accountName; byte[] sentHmac; if (request.Headers != null && DateTime.Now - request.Headers.Date > maxAge) { throw new ForbiddenException("Request expired."); } if (authenticationHeader == null || string.IsNullOrWhiteSpace(authenticationHeader.Parameter) || authenticationHeader.Scheme != SharedKeyAuthentication.Scheme || !SharedKeyAuthentication.TryParse(authenticationHeader.Parameter, out accountName, out sentHmac)) { return(AnonymousPrincipal); } byte[] sharedKey = resolver(accountName); if (sharedKey == null || sharedKey.Length == 0) { // Account not found throw new UnauthorizedException(); } if (request.Headers.TransferEncodingChunked == null || !(bool)request.Headers.TransferEncodingChunked) { if (request.Content.Headers.ContentLength != null && (long)request.Content.Headers.ContentLength > 0) { var sentHash = request.Content.Headers.ContentMD5; if (sentHash == null) { throw new ForbiddenException( "Content-MD5 header must be specified when a request body is included."); } if (!CompareHash(sentHash, SignatureValidator.CalculateBodyMd5(request).Result)) { throw new PreconditionFailedException("Content-MD5 does not match the request body."); } } } // Now check the actual auth signature. byte[] calculatedHmac = SharedKeySignature.Calculate(request, accountName, sharedKey); if (!CompareHash(sentHmac, calculatedHmac)) { throw new ForbiddenException("Token validation failed."); } var claims = new List <Claim> { new Claim(ClaimTypes.Name, accountName) }; var claimsIdentity = new ClaimsIdentity(claims, SharedKeyAuthentication.Scheme); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); return(claimsPrincipal); }