示例#1
0
 public HttpResult(byte[] responseBytes, string contentType)
     : this(null, contentType, HttpStatusCode.OK)
 {
     this.AllowsPartialResponse = true;
     this.ResponseStream        = MemoryStreamFactory.GetStream(responseBytes);
 }
示例#2
0
        private void HandleResponseError <TResponse>(Exception exception, AsyncState <TResponse> state)
        {
            var webEx = exception as WebException;

            if (PclExportClient.Instance.IsWebException(webEx))
            {
                var errorResponse = (HttpWebResponse)webEx.Response;
                Log.Error(webEx);
                if (Log.IsDebugEnabled)
                {
                    Log.DebugFormat("Status Code : {0}", errorResponse.StatusCode);
                    Log.DebugFormat("Status Description : {0}", errorResponse.StatusDescription);
                }

                var serviceEx = new WebServiceException(errorResponse.StatusDescription)
                {
                    StatusCode        = (int)errorResponse.StatusCode,
                    StatusDescription = errorResponse.StatusDescription,
                    ResponseHeaders   = errorResponse.Headers
                };

                try
                {
                    using (var stream = errorResponse.GetResponseStream())
                    {
                        var bytes = stream.ReadFully();
                        serviceEx.ResponseBody = bytes.FromUtf8Bytes();
                        var errorResponseType = WebRequestUtils.GetErrorResponseDtoType <TResponse>(state.Request);

                        if (stream.CanSeek)
                        {
                            PclExport.Instance.ResetStream(stream);
                            serviceEx.ResponseDto = this.StreamDeserializer(errorResponseType, stream);
                        }
                        else //Android
                        {
                            using (var ms = MemoryStreamFactory.GetStream(bytes))
                            {
                                serviceEx.ResponseDto = this.StreamDeserializer(errorResponseType, ms);
                            }
                        }
                        state.HandleError(serviceEx.ResponseDto, serviceEx);
                    }
                }
                catch (Exception innerEx)
                {
                    // Oh, well, we tried
                    Log.Debug(string.Format("WebException Reading Response Error: {0}", innerEx.Message), innerEx);
                    state.HandleError(default(TResponse), new WebServiceException(errorResponse.StatusDescription, innerEx)
                    {
                        StatusCode        = (int)errorResponse.StatusCode,
                        StatusDescription = errorResponse.StatusDescription,
                        ResponseHeaders   = errorResponse.Headers
                    });
                }
                return;
            }

            var authEx = exception as AuthenticationException;

            if (authEx != null)
            {
                var customEx = WebRequestUtils.CreateCustomException(state.Url, authEx);

                Log.Debug(string.Format("AuthenticationException: {0}", customEx.Message), customEx);
                state.HandleError(default(TResponse), authEx);
            }

            Log.Debug(string.Format("Exception Reading Response Error: {0}", exception.Message), exception);
            state.HandleError(default(TResponse), exception);

            CancelAsyncFn = null;
        }
        private async Task <T> SendWebRequestAsync <T>(string httpMethod, string absoluteUrl, object request, CancellationToken token, bool recall = false)
        {
            if (httpMethod == null)
            {
                throw new ArgumentNullException(nameof(httpMethod));
            }

            this.PopulateRequestMetadata(request);

            var requestUri     = absoluteUrl;
            var hasQueryString = request != null && !HttpUtils.HasRequestBody(httpMethod);

            if (hasQueryString)
            {
                var queryString = QueryStringSerializer.SerializeToString(request);
                if (!string.IsNullOrEmpty(queryString))
                {
                    requestUri += "?" + queryString;
                }
            }

            var webReq = this.CreateHttpWebRequest(requestUri);

            var    timedOut = false;
            ITimer timer    = null;

            timer = PclExportClient.Instance.CreateTimer(state =>
            {
                timedOut = true;
                webReq?.Abort();
                webReq = null;
                timer?.Cancel();
                timer = null;
            }, this.Timeout.GetValueOrDefault(DefaultTimeout), this);

            Exception ResolveException(Exception ex)
            {
                if (token.IsCancellationRequested)
                {
                    return(new OperationCanceledException(token));
                }
                if (timedOut)
                {
                    return(PclExportClient.Instance.CreateTimeoutException(ex, "The request timed out"));
                }
                return(ex);
            }

            bool            returningWebResponse = false;
            HttpWebResponse webRes = null;

            T Complete(T response)
            {
                timer.Cancel();
                PclExportClient.Instance.SynchronizeCookies(this);
                ResultsFilterResponse?.Invoke(webRes, response, httpMethod, absoluteUrl, request);
                return(response);
            }

            webReq.Accept = ContentType;

            if (this.EmulateHttpViaPost)
            {
                webReq.Method = "POST";
                webReq.Headers[HttpHeaders.XHttpMethodOverride] = httpMethod;
            }
            else
            {
                webReq.Method = httpMethod;
            }

            PclExportClient.Instance.AddHeader(webReq, Headers);
            PclExport.Instance.Config(webReq, userAgent: UserAgent);

            if (this.authInfo != null && !string.IsNullOrEmpty(this.UserName))
            {
                webReq.AddAuthInfo(this.UserName, this.Password, authInfo);
            }
            else if (this.BearerToken != null)
            {
                webReq.Headers[HttpHeaders.Authorization] = "Bearer " + this.BearerToken;
            }
            else if (this.Credentials != null)
            {
                webReq.Credentials = this.Credentials;
            }
            else if (this.AlwaysSendBasicAuthHeader)
            {
                webReq.AddBasicAuth(this.UserName, this.Password);
            }

            if (!DisableAutoCompression)
            {
                PclExport.Instance.AddCompression(webReq);
            }

            ApplyWebRequestFilters(webReq);

            try
            {
                if (HttpUtils.HasRequestBody(webReq.Method))
                {
                    webReq.ContentType = ContentType;

                    if (RequestCompressionType != null)
                    {
                        webReq.Headers[HttpHeaders.ContentEncoding] = RequestCompressionType;
                    }

                    using (var requestStream = await webReq.GetRequestStreamAsync().ConfigureAwait(false))
                    {
                        token.ThrowIfCancellationRequested();
                        if (request != null)
                        {
                            StreamSerializer(null, request, requestStream);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug($"Error Sending Request: {ex.Message}", ex);
                }

                throw HandleResponseError <T>(ResolveException(ex), requestUri, request);
            }

            try
            {
                webRes = (HttpWebResponse)await webReq.GetResponseAsync().ConfigureAwait(false);

                {
                    token.ThrowIfCancellationRequested();

                    ApplyWebResponseFilters(webRes);

                    returningWebResponse = typeof(T) == typeof(HttpWebResponse);
                    if (returningWebResponse)
                    {
                        return(Complete((T)(object)webRes));
                    }

                    var responseStream = webRes.ResponseStream();

                    var responseBodyLength = webRes.ContentLength;
                    var bufferRead         = new byte[BufferSize];

                    var totalRead = 0;
                    int read;
                    var ms = MemoryStreamFactory.GetStream();

                    while ((read = await responseStream.ReadAsync(bufferRead, 0, bufferRead.Length, token).ConfigureAwait(false)) != 0)
                    {
                        ms.Write(bufferRead, 0, read);
                        totalRead += read;
                        OnDownloadProgress?.Invoke(totalRead, responseBodyLength);
                    }

                    try
                    {
                        ms.Position = 0;
                        if (typeof(T) == typeof(Stream))
                        {
                            return(Complete((T)(object)ms));
                        }
                        else
                        {
                            var stream = ms;
                            try
                            {
                                if (typeof(T) == typeof(string))
                                {
                                    return(Complete((T)(object)stream.ReadToEnd()));
                                }
                                else if (typeof(T) == typeof(byte[]))
                                {
                                    return(Complete((T)(object)stream.ToArray()));
                                }
                                else
                                {
                                    return(Complete((T)this.StreamDeserializer(typeof(T), stream)));
                                }
                            }
                            finally
                            {
                                if (stream.CanRead)
                                {
                                    stream.Dispose(); // Not yet disposed, but could've been.
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug($"Error Reading Response Error: {ex.Message}", ex);
                        }

                        throw;
                    }
                    finally
                    {
                        responseStream.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                var webEx     = ex as WebException;
                var firstCall = !recall;
                if (firstCall && WebRequestUtils.ShouldAuthenticate(webEx,
                                                                    (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password)) ||
                                                                    Credentials != null ||
                                                                    BearerToken != null ||
                                                                    RefreshToken != null ||
                                                                    OnAuthenticationRequired != null))
                {
                    try
                    {
                        if (RefreshToken != null)
                        {
                            var refreshRequest = new GetAccessToken {
                                RefreshToken = RefreshToken
                            };
                            var uri = this.RefreshTokenUri ??
                                      this.BaseUri.CombineWith(refreshRequest.ToPostUrl());

                            GetAccessTokenResponse tokenResponse;
                            try
                            {
                                tokenResponse = uri.PostJsonToUrl(refreshRequest)
                                                .FromJson <GetAccessTokenResponse>();
                            }
                            catch (WebException refreshEx)
                            {
                                var webServiceEx = ServiceClientBase.ToWebServiceException(refreshEx,
                                                                                           stream => StreamDeserializer(typeof(T), stream),
                                                                                           ContentType);

                                if (webServiceEx != null)
                                {
                                    throw new RefreshTokenException(webServiceEx);
                                }

                                throw new RefreshTokenException(refreshEx.Message, refreshEx);
                            }

                            var accessToken = tokenResponse?.AccessToken;
                            if (string.IsNullOrEmpty(accessToken))
                            {
                                throw new RefreshTokenException("Could not retrieve new AccessToken from: " + uri);
                            }

                            var refreshClient = webReq = (HttpWebRequest)WebRequest.Create(requestUri);
                            if (this.CookieContainer.GetTokenCookie(BaseUri) != null)
                            {
                                this.CookieContainer.SetTokenCookie(accessToken, BaseUri);
                                refreshClient.CookieContainer.SetTokenCookie(BaseUri, accessToken);
                            }
                            else
                            {
                                refreshClient.AddBearerToken(this.BearerToken = accessToken);
                            }

                            return(await SendWebRequestAsync <T>(httpMethod, absoluteUrl, request, token, recall : true).ConfigureAwait(false));
                        }

                        OnAuthenticationRequired?.Invoke();

                        var newReq = (HttpWebRequest)WebRequest.Create(requestUri);

                        if (StoreCookies)
                        {
                            newReq.CookieContainer = CookieContainer;
                        }

                        HandleAuthException(ex, webReq);

                        return(await SendWebRequestAsync <T>(httpMethod, absoluteUrl, request, token, recall : true).ConfigureAwait(false));
                    }
                    catch (WebServiceException)
                    {
                        throw;
                    }
                    catch (Exception /*subEx*/)
                    {
                        throw HandleResponseError <T>(ResolveException(ex), requestUri, request);
                    }
                }

                if (ExceptionFilter != null && webEx?.Response != null)
                {
                    var cachedResponse = ExceptionFilter(webEx, webEx.Response, requestUri, typeof(T));
                    if (cachedResponse is T variable)
                    {
                        return(variable);
                    }
                }

                throw HandleResponseError <T>(ResolveException(ex), requestUri, request);
            }
            finally
            {
                if (!returningWebResponse)
                {
                    webRes?.Dispose();
                }
            }
        }
        private Exception HandleResponseError <TResponse>(Exception exception, string url, object request)
        {
            var webEx = exception as WebException;

            if (PclExportClient.Instance.IsWebException(webEx))
            {
                var errorResponse = (HttpWebResponse)webEx.Response;
                Log.Error(webEx);
                if (Log.IsDebugEnabled)
                {
                    Log.Debug($"Status Code : {errorResponse.StatusCode}");
                    Log.Debug($"Status Description : {errorResponse.StatusDescription}");
                }

                var serviceEx = new WebServiceException(errorResponse.StatusDescription)
                {
                    StatusCode        = (int)errorResponse.StatusCode,
                    StatusDescription = errorResponse.StatusDescription,
                    ResponseHeaders   = errorResponse.Headers
                };

                try
                {
                    using (var stream = errorResponse.ResponseStream())
                    {
                        var bytes = stream.ReadFully();
                        serviceEx.ResponseBody = bytes.FromUtf8Bytes();
                        var errorResponseType = WebRequestUtils.GetErrorResponseDtoType <TResponse>(request);

                        if (stream.CanSeek)
                        {
                            PclExport.Instance.ResetStream(stream);
                            serviceEx.ResponseDto = this.StreamDeserializer(errorResponseType, stream);
                        }
                        else //Android
                        {
                            using (var ms = MemoryStreamFactory.GetStream(bytes))
                            {
                                serviceEx.ResponseDto = this.StreamDeserializer(errorResponseType, ms);
                            }
                        }
                        return(serviceEx);
                    }
                }
                catch (Exception innerEx)
                {
                    // Oh, well, we tried
                    Log.Debug($"WebException Reading Response Error: {innerEx.Message}", innerEx);
                    return(new WebServiceException(errorResponse.StatusDescription, innerEx)
                    {
                        StatusCode = (int)errorResponse.StatusCode,
                        StatusDescription = errorResponse.StatusDescription,
                        ResponseHeaders = errorResponse.Headers
                    });
                }
            }

            if (exception is AuthenticationException authEx)
            {
                var customEx = WebRequestUtils.CreateCustomException(url, authEx);

                Log.Debug($"AuthenticationException: {customEx.Message}", customEx);
                return(authEx);
            }

            Log.Debug($"Exception Reading Response Error: {exception.Message}", exception);
            return(exception);
        }
        public override async Task ProcessRequestAsync(IRequest httpReq, IResponse httpRes, string operationName)
        {
            if (Page == null && pagePath != null)
            {
                var pages = httpReq.TryResolve <ITemplatePages>();
                Page = pages.GetPage(pagePath)
                       ?? throw new FileNotFoundException($"Template Page not found '{pagePath}'");

                if (!string.IsNullOrEmpty(layoutPath))
                {
                    LayoutPage = pages.GetPage(layoutPath)
                                 ?? throw new FileNotFoundException($"Template Page not found '{layoutPath}'");
                }
            }

            var feature = HostContext.GetPlugin <TemplatePagesFeature>();

            var args = httpReq.GetTemplateRequestParams(importRequestParams: feature.ImportRequestParams);

            if (Args != null)
            {
                foreach (var entry in Args)
                {
                    args[entry.Key] = entry.Value;
                }
            }

            var pageResult = new PageResult(Page)
            {
                Args       = args,
                LayoutPage = LayoutPage,
                Model      = Model,
            };

            try
            {
                httpRes.ContentType = Page.Format.ContentType;
                if (OutputStream != null)
                {
                    await pageResult.WriteToAsync(OutputStream);
                }
                else
                {
                    // Buffering improves perf when running behind a reverse proxy (recommended for .NET Core)
                    using (var ms = MemoryStreamFactory.GetStream())
                    {
                        await pageResult.WriteToAsync(ms);

                        if (pageResult.Args.TryGetValue(TemplateConstants.Return, out var response))
                        {
                            if (response is Task <object> responseTask)
                            {
                                response = await responseTask;
                            }
                            if (response is IRawString raw)
                            {
                                response = raw.ToRawString();
                            }

                            if (response != null)
                            {
                                var httpResult = TemplateApiPagesService.ToHttpResult(pageResult, response);
                                await httpRes.WriteToResponse(httpReq, httpResult);

                                return;
                            }
                        }

                        ms.Position = 0;
                        await ms.WriteToAsync(httpRes.OutputStream);
                    }
                }
            }
            catch (Exception ex)
            {
                await Page.Format.OnViewException(pageResult, httpReq, ex);
            }
        }
示例#6
0
 public override MemoryStream ToMemoryStream(ReadOnlySpan <byte> source) =>
 MemoryStreamFactory.GetStream(source.ToArray());
示例#7
0
        public static string CreateEncryptedJweToken(JsonObject jwtPayload, RSAParameters publicKey)
        {
            //From: http://self-issued.info/docs/draft-ietf-jose-json-web-encryption-09.html#RSACBCExample
            var jweHeader = new JsonObject
            {
                { "alg", "RSA-OAEP" },
                { "enc", "A128CBC-HS256" },
                { "kid", Convert.ToBase64String(publicKey.Modulus).Substring(0, 3) },
            };

            var jweHeaderBase64Url = jweHeader.ToJson().ToUtf8Bytes().ToBase64UrlSafe();

            var authKey          = new byte[128 / 8];
            var cryptKey         = new byte[128 / 8];
            var cryptAuthKeys256 = AesUtils.CreateKey();

            Buffer.BlockCopy(cryptAuthKeys256, 0, authKey, 0, authKey.Length);
            Buffer.BlockCopy(cryptAuthKeys256, authKey.Length, cryptKey, 0, cryptKey.Length);

            var aes = Aes.Create();

            aes.KeySize   = 128;
            aes.BlockSize = 128;
            aes.Mode      = CipherMode.CBC;
            aes.Padding   = PaddingMode.PKCS7;
            using (aes)
            {
                aes.GenerateIV();
                var iv = aes.IV;
                aes.Key = cryptKey;

                var jweEncKey          = RsaUtils.Encrypt(cryptAuthKeys256, publicKey, UseRsaKeyLength);
                var jweEncKeyBase64Url = jweEncKey.ToBase64UrlSafe();
                var ivBase64Url        = iv.ToBase64UrlSafe();

                var aad          = jweHeaderBase64Url + "." + jweEncKeyBase64Url;
                var aadBytes     = aad.ToUtf8Bytes();
                var payloadBytes = jwtPayload.ToJson().ToUtf8Bytes();

                using (var cipherStream = MemoryStreamFactory.GetStream())
                    using (var encrypter = aes.CreateEncryptor(cryptKey, iv))
                        using (var cryptoStream = new CryptoStream(cipherStream, encrypter, CryptoStreamMode.Write))
                            using (var writer = new BinaryWriter(cryptoStream))
                            {
                                writer.Write(payloadBytes);
                                cryptoStream.FlushFinalBlock();

                                using (var hmac = new HMACSHA256(authKey))
                                    using (var encryptedStream = MemoryStreamFactory.GetStream())
                                        using (var bw = new BinaryWriter(encryptedStream))
                                        {
                                            bw.Write(aadBytes);
                                            bw.Write(iv);
                                            bw.Write(cipherStream.GetBuffer(), 0, (int)cipherStream.Length);
                                            bw.Flush();

                                            var tag = hmac.ComputeHash(encryptedStream.GetBuffer(), 0, (int)encryptedStream.Length);

                                            var cipherTextBase64Url = cipherStream.ToBase64UrlSafe();
                                            var tagBase64Url        = tag.ToBase64UrlSafe();

                                            var jweToken = jweHeaderBase64Url + "."
                                                           + jweEncKeyBase64Url + "."
                                                           + ivBase64Url + "."
                                                           + cipherTextBase64Url + "."
                                                           + tagBase64Url;

                                            return(jweToken);
                                        }
                            }
            }
        }
示例#8
0
 internal static MemoryStream CreateBufferedStream(this IResponse response)
 {
     return(MemoryStreamFactory.GetStream());
 }
示例#9
0
        public static void WriteQueryString(TextWriter writer, object value)
        {
            try
            {
                JsState.QueryStringMode = true;
                var i = 0;
                foreach (var propertyWriter in PropertyWriters)
                {
                    var propertyValue = propertyWriter.GetterFn((T)value);
                    if (propertyValue == null)
                    {
                        continue;
                    }

                    if (i++ > 0)
                    {
                        writer.Write('&');
                    }

                    var propertyType = propertyValue.GetType();
                    var strValue     = propertyValue as string;
                    var isEnumerable = strValue == null &&
                                       !(propertyType.IsValueType()) &&
                                       propertyType.HasInterface(typeof(IEnumerable));

                    if (QueryStringSerializer.ComplexTypeStrategy != null &&
                        !isEnumerable && (propertyType.IsUserType() || propertyType.IsInterface()))
                    {
                        if (QueryStringSerializer.ComplexTypeStrategy(writer, propertyWriter.PropertyName, propertyValue))
                        {
                            continue;
                        }
                    }

                    Serializer.WritePropertyName(writer, propertyWriter.PropertyName);
                    writer.Write('=');

                    if (strValue != null)
                    {
                        writer.Write(strValue.UrlEncode());
                    }
                    else if (!isEnumerable)
                    {
                        propertyWriter.WriteFn(writer, propertyValue);
                    }
                    else
                    {
                        //Trim brackets in top-level lists in QueryStrings, e.g: ?a=[1,2,3] => ?a=1,2,3
                        using (var ms = MemoryStreamFactory.GetStream())
                        {
                            var enumerableWriter = new StreamWriter(ms); //ms disposed in using
                            propertyWriter.WriteFn(enumerableWriter, propertyValue);
                            enumerableWriter.Flush();
                            var output = ms.ToArray().FromUtf8Bytes();
                            output = output.Trim(ArrayBrackets);
                            writer.Write(output);
                        }
                    }
                }
            }
            finally
            {
                JsState.QueryStringMode = false;
            }
        }
        public static IMessage <T> ToMessage <T>(this BasicGetResult msgResult)
        {
            if (msgResult == null)
            {
                return(null);
            }

            var props = msgResult.BasicProperties;
            T   body;

            if (string.IsNullOrEmpty(props.ContentType) || props.ContentType.MatchesContentType(MimeTypes.Json))
            {
                var json = msgResult.Body.FromUtf8Bytes();
                body = json.FromJson <T>();
            }
            else
            {
                var deserializer = HostContext.ContentTypes.GetStreamDeserializer(props.ContentType);
                if (deserializer == null)
                {
                    throw new NotSupportedException("Unknown Content-Type: " + props.ContentType);
                }

                var ms = MemoryStreamFactory.GetStream(msgResult.Body);
                body = (T)deserializer(typeof(T), ms);
                ms.Dispose();
            }

            var message = new Message <T>(body)
            {
                Id = props.MessageId != null?Guid.Parse(props.MessageId) : new Guid(),
                         CreatedDate   = ((int)props.Timestamp.UnixTime).FromUnixTime(),
                         Priority      = props.Priority,
                         ReplyTo       = props.ReplyTo,
                         Tag           = msgResult.DeliveryTag.ToString(),
                         RetryAttempts = msgResult.Redelivered ? 1 : 0,
            };

            if (props.CorrelationId != null)
            {
                message.ReplyId = Guid.Parse(props.CorrelationId);
            }

            if (props.Headers != null)
            {
                foreach (var entry in props.Headers)
                {
                    if (entry.Key == "Error")
                    {
                        var errors = entry.Value;
                        if (errors != null)
                        {
                            var errorsJson = errors is byte[] errorBytes
                                ? errorBytes.FromUtf8Bytes()
                                : errors.ToString();

                            message.Error = errorsJson.FromJson <ResponseStatus>();
                        }
                    }
                    else
                    {
                        if (message.Meta == null)
                        {
                            message.Meta = new Dictionary <string, string>();
                        }

                        var value = entry.Value is byte[] bytes
                            ? bytes.FromUtf8Bytes()
                            : entry.Value?.ToString();

                        message.Meta[entry.Key] = value;
                    }
                }
            }

            return(message);
        }
示例#11
0
        public void ThrowWebServiceException <TResponse>(HttpResponseMessage httpRes, object request, string requestUri, object response)
        {
            if (log.IsDebugEnabled)
            {
                log.DebugFormat("Status Code : {0}", httpRes.StatusCode);
                log.DebugFormat("Status Description : {0}", httpRes.ReasonPhrase);
            }

            var serviceEx = new WebServiceException(httpRes.ReasonPhrase)
            {
                StatusCode        = (int)httpRes.StatusCode,
                StatusDescription = httpRes.ReasonPhrase,
                ResponseHeaders   = httpRes.Headers.ToWebHeaderCollection()
            };

            try
            {
                var contentType = httpRes.GetContentType();

                var bytes = GetResponseBytes(response);
                if (bytes != null)
                {
                    if (string.IsNullOrEmpty(contentType) || contentType.MatchesContentType(ContentType))
                    {
                        using (__requestAccess())
                        {
                            var stream = MemoryStreamFactory.GetStream(bytes);
                            serviceEx.ResponseBody = bytes.FromUtf8Bytes();
                            serviceEx.ResponseDto  = JsonSerializer.DeserializeFromStream <TResponse>(stream);

                            if (stream.CanRead)
                            {
                                stream.Dispose(); //alt ms throws when you dispose twice
                            }
                        }
                    }
                    else
                    {
                        serviceEx.ResponseBody = bytes.FromUtf8Bytes();
                    }
                }
            }
            catch (Exception innerEx)
            {
                // Oh, well, we tried
                throw new WebServiceException(httpRes.ReasonPhrase, innerEx)
                      {
                          StatusCode        = (int)httpRes.StatusCode,
                          StatusDescription = httpRes.ReasonPhrase,
                          ResponseBody      = serviceEx.ResponseBody
                      };
            }

            //Escape deserialize exception handling and throw here
            throw serviceEx;

            //var authEx = ex as AuthenticationException;
            //if (authEx != null)
            //{
            //    throw WebRequestUtils.CreateCustomException(requestUri, authEx);
            //}
        }
示例#12
0
        public async Task Any(EvalScript request)
        {
            var feature = HostContext.AssertPlugin <DesktopFeature>();

            RequestUtils.AssertAccessRole(base.Request, accessRole: feature.AccessRole, authSecret: request.AuthSecret);

            var    appHost = HostContext.AppHost;
            string script;
            var    method = ((script = request.EvaluateScript) != null
                 ? nameof(request.EvaluateScript)
                 : (script = request.EvaluateCode) != null
                     ? nameof(request.EvaluateCode)
                     : (script = request.EvaluateLisp) != null
                         ? nameof(request.EvaluateLisp)
                         : (script = request.RenderScript) != null
                             ? nameof(request.RenderScript)
                             : (script = request.RenderCode) != null
                                 ? nameof(request.RenderCode)
                                 : (script = request.RenderLisp) != null
                                     ? nameof(request.RenderLisp)
                                     : null) ??
                            ((script = request.EvaluateScriptAsync) != null
                 ? nameof(request.EvaluateScriptAsync)
                 : (script = request.EvaluateCodeAsync) != null
                     ? nameof(request.EvaluateCodeAsync)
                     : (script = request.EvaluateLispAsync) != null
                         ? nameof(request.EvaluateLispAsync)
                         : (script = request.RenderScriptAsync) != null
                             ? nameof(request.RenderScriptAsync)
                             : (script = request.RenderCodeAsync) != null
                                 ? nameof(request.RenderCodeAsync)
                                 : (script = request.RenderLispAsync) != null
                                     ? nameof(request.RenderLispAsync)
                                     : null)
                            ?? throw new ArgumentNullException(nameof(request.EvaluateCode));

            async Task HandleExceptionAsync(Exception e)
            {
                log.Error(e.Message, e);
                base.Response.StatusCode        = 500;
                base.Response.StatusDescription = e.GetType().Name;
                base.Response.ContentType       = MimeTypes.PlainText;
                await base.Response.OutputStream.WriteAsync(MemoryProvider.Instance.ToUtf8(e.ToString().AsSpan()));

                await base.Response.EndRequestAsync(skipHeaders : true);
            }

            async Task SetResult(object value, string resultType = " result")
            {
                base.Response.ContentType       = MimeTypes.Json;
                base.Response.StatusCode        = 200;
                base.Response.StatusDescription = method + resultType;
                await base.Response.EndRequestAsync(skipHeaders : false, async res => {
                    using var ms = MemoryStreamFactory.GetStream();
                    JsonSerializer.SerializeToStream(value, ms);
                    ms.Position = 0;
                    await ms.CopyToAsync(base.Response.OutputStream);
                });
            }

            async Task SetOutput(PageResult result)
            {
                base.Response.StatusCode        = 200;
                base.Response.StatusDescription = method + " result";
                base.Response.ContentType       = MimeTypes.PlainText;
                await base.Response.EndRequestAsync(skipHeaders : false, async res => {
                    using var ms = MemoryStreamFactory.GetStream();
                    await result.RenderToStreamAsync(ms);
                    ms.Position = 0;
                    await ms.CopyToAsync(res.OutputStream);
                });
            }

            var args = new Dictionary <string, object> {
                [ScriptConstants.Request] = base.Request,
            };

            if (method.EqualsIgnoreCase(nameof(ScriptTemplateUtils.EvaluateScript)))
            {
                await SetResult(await appHost.ScriptContext.EvaluateAsync(script, args));
            }
            else if (method.EqualsIgnoreCase(nameof(ScriptTemplateUtils.RenderScript)))
            {
                await SetOutput(new PageResult(appHost.ScriptContext.SharpScriptPage(script)).AssignArgs(args));
            }

            else if (method.EqualsIgnoreCase(nameof(ScriptCodeUtils.EvaluateCode)))
            {
                await SetResult(await appHost.ScriptContext.EvaluateCodeAsync(ScriptCodeUtils.EnsureReturn(script), args));
            }
            else if (method.EqualsIgnoreCase(nameof(ScriptCodeUtils.RenderCode)))
            {
                await SetOutput(new PageResult(appHost.ScriptContext.CodeSharpPage(script)).AssignArgs(args));
            }

            else if (method.EqualsIgnoreCase(nameof(ScriptLispUtils.EvaluateLisp)))
            {
                await SetResult(await appHost.ScriptContext.EvaluateLispAsync(ScriptLispUtils.EnsureReturn(script), args));
            }
            else if (method.EqualsIgnoreCase(nameof(ScriptLispUtils.RenderLisp)))
            {
                await SetOutput(new PageResult(appHost.ScriptContext.LispSharpPage(script)).AssignArgs(args));
            }

            if (base.Response.IsClosed)
            {
                return;
            }

            async Task setResultAsync(Task <object> valueTask, string resultType = " result")
            {
                try
                {
                    base.Response.ContentType       = MimeTypes.Json;
                    base.Response.StatusCode        = 200;
                    base.Response.StatusDescription = method + resultType;
                    await base.Response.EndRequestAsync(skipHeaders : false, async res => {
                        using var ms = MemoryStreamFactory.GetStream();
                        JsonSerializer.SerializeToStream(await valueTask, ms);
                        await ms.CopyToAsync(base.Response.OutputStream);
                    });
                }
                catch (Exception e)
                {
                    await HandleExceptionAsync(e);
                }
            }

            async Task setOutputAsync(PageResult result)
            {
                try
                {
                    base.Response.StatusCode        = 200;
                    base.Response.StatusDescription = method + " async result";
                    base.Response.ContentType       = MimeTypes.PlainText;
                    await base.Response.EndRequestAsync(skipHeaders : false, async res => {
                        using var ms = MemoryStreamFactory.GetStream();
                        await result.RenderToStreamAsync(ms);
                        await ms.CopyToAsync(res.OutputStream);
                    });
                }
                catch (Exception e)
                {
                    await HandleExceptionAsync(e);
                }
            }

            if (method.EqualsIgnoreCase(nameof(ScriptTemplateUtils.EvaluateScriptAsync)))
            {
                await Task.Run(async() => await setResultAsync(appHost.ScriptContext.EvaluateAsync(script, args), " async result"));
            }
            else if (method.EqualsIgnoreCase(nameof(ScriptTemplateUtils.RenderScriptAsync)))
            {
                await Task.Run(async() => await setOutputAsync(new PageResult(appHost.ScriptContext.SharpScriptPage(script)).AssignArgs(args)));
            }

            else if (method.EqualsIgnoreCase(nameof(ScriptCodeUtils.EvaluateCodeAsync)))
            {
                await Task.Run(async() => await setResultAsync(appHost.ScriptContext.EvaluateCodeAsync(ScriptCodeUtils.EnsureReturn(script), args), " async result"));
            }
            else if (method.EqualsIgnoreCase(nameof(ScriptCodeUtils.RenderCodeAsync)))
            {
                await Task.Run(async() => await setOutputAsync(new PageResult(appHost.ScriptContext.CodeSharpPage(script)).AssignArgs(args)));
            }

            else if (method.EqualsIgnoreCase(nameof(ScriptLispUtils.EvaluateLispAsync)))
            {
                await Task.Run(async() => await setResultAsync(appHost.ScriptContext.EvaluateLispAsync(ScriptLispUtils.EnsureReturn(script), args), " async result"));
            }
            else if (method.EqualsIgnoreCase(nameof(ScriptLispUtils.RenderLispAsync)))
            {
                await Task.Run(async() => await setOutputAsync(new PageResult(appHost.ScriptContext.LispSharpPage(script)).AssignArgs(args)));
            }
            else
            {
                throw new NotSupportedException($"Unsupported script API '{method}', supported: " +
                                                "EvaluateScript/Async, EvaluateCode/Async, EvaluateLisp/Async");
            }
        }
示例#13
0
        public static void WriteQueryString(TextWriter writer, object instance)
        {
            try
            {
                JsState.QueryStringMode = true;
                var config = JsConfig <T> .GetConfig();

                var i             = 0;
                var typedInstance = (T)instance;
                foreach (var propertyWriter in PropertyWriters)
                {
                    var propertyValue = propertyWriter.GetterFn(typedInstance);
                    if (propertyValue == null)
                    {
                        continue;
                    }

                    if (i++ > 0)
                    {
                        writer.Write('&');
                    }

                    var propertyType = propertyValue.GetType();
                    var strValue     = propertyValue as string;
                    var isEnumerable = strValue == null &&
                                       !propertyType.IsValueType &&
                                       propertyType.HasInterface(typeof(IEnumerable));

                    if (QueryStringSerializer.ComplexTypeStrategy != null)
                    {
                        var nonEnumerableUserType = !isEnumerable && (propertyType.IsUserType() || propertyType.IsInterface);
                        if (nonEnumerableUserType || propertyType.IsOrHasGenericInterfaceTypeOf(typeof(IDictionary <,>)))
                        {
                            if (QueryStringSerializer.ComplexTypeStrategy(writer, propertyWriter.GetPropertyName(config), propertyValue))
                            {
                                continue;
                            }
                        }
                    }

                    Serializer.WritePropertyName(writer, propertyWriter.GetPropertyName(config));
                    writer.Write('=');

                    if (strValue != null)
                    {
                        writer.Write(strValue.UrlEncode());
                    }
                    else if (!isEnumerable)
                    {
                        propertyWriter.WriteFn(writer, propertyValue);
                    }
                    else
                    {
                        //Trim brackets in top-level lists in QueryStrings, e.g: ?a=[1,2,3] => ?a=1,2,3
                        using (var ms = MemoryStreamFactory.GetStream())
                        {
                            var enumerableWriter = new StreamWriter(ms); //ms disposed in using
                            propertyWriter.WriteFn(enumerableWriter, propertyValue);
                            enumerableWriter.Flush();
                            var output = ms.ReadToEnd();
                            output = output.Trim(ArrayBrackets);
                            writer.Write(output);
                        }
                    }
                }
            }
            finally
            {
                JsState.QueryStringMode = false;
            }
        }
 public override Stream OpenRead()
 {
     return(MemoryStreamFactory.GetStream(ByteContents ?? (TextContents ?? "").ToUtf8Bytes()));
 }
        public void PreAuthenticate(IRequest req, IResponse res)
        {
            if (req.OperationName != null && IgnoreForOperationTypes.Contains(req.OperationName))
            {
                return;
            }

            var bearerToken = req.GetBearerToken()
                              ?? req.GetCookieValue(Keywords.TokenCookie);

            if (bearerToken != null)
            {
                var parts = bearerToken.Split('.');
                if (parts.Length == 3)
                {
                    if (RequireSecureConnection && !req.IsSecureConnection)
                    {
                        throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection);
                    }

                    var header         = parts[0];
                    var payload        = parts[1];
                    var signatureBytes = parts[2].FromBase64UrlSafe();

                    var headerJson   = header.FromBase64UrlSafe().FromUtf8Bytes();
                    var payloadBytes = payload.FromBase64UrlSafe();

                    var headerData = headerJson.FromJson <Dictionary <string, string> >();

                    var bytesToSign = string.Concat(header, ".", payload).ToUtf8Bytes();

                    var algorithm = headerData["alg"];

                    //Potential Security Risk for relying on user-specified algorithm: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
                    if (RequireHashAlgorithm && algorithm != HashAlgorithm)
                    {
                        throw new NotSupportedException("Invalid algoritm '{0}', expected '{1}'".Fmt(algorithm, HashAlgorithm));
                    }

                    if (!VerifyPayload(algorithm, bytesToSign, signatureBytes))
                    {
                        return;
                    }

                    var payloadJson = payloadBytes.FromUtf8Bytes();
                    var jwtPayload  = JsonObject.Parse(payloadJson);

                    var session = CreateSessionFromPayload(req, jwtPayload);
                    req.Items[Keywords.Session] = session;
                }
                else if (parts.Length == 5) //Encrypted JWE Token
                {
                    if (RequireSecureConnection && !req.IsSecureConnection)
                    {
                        throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection);
                    }

                    if (PrivateKey == null || PublicKey == null)
                    {
                        throw new NotSupportedException("PrivateKey is required to DecryptPayload");
                    }

                    var jweHeaderBase64Url  = parts[0];
                    var jweEncKeyBase64Url  = parts[1];
                    var ivBase64Url         = parts[2];
                    var cipherTextBase64Url = parts[3];
                    var tagBase64Url        = parts[4];

                    var sentTag    = tagBase64Url.FromBase64UrlSafe();
                    var aadBytes   = (jweHeaderBase64Url + "." + jweEncKeyBase64Url).ToUtf8Bytes();
                    var iv         = ivBase64Url.FromBase64UrlSafe();
                    var cipherText = cipherTextBase64Url.FromBase64UrlSafe();

                    var jweEncKey        = jweEncKeyBase64Url.FromBase64UrlSafe();
                    var cryptAuthKeys256 = RsaUtils.Decrypt(jweEncKey, PrivateKey.Value, UseRsaKeyLength);

                    var authKey  = new byte[128 / 8];
                    var cryptKey = new byte[128 / 8];
                    Buffer.BlockCopy(cryptAuthKeys256, 0, authKey, 0, authKey.Length);
                    Buffer.BlockCopy(cryptAuthKeys256, authKey.Length, cryptKey, 0, cryptKey.Length);

                    using (var hmac = new HMACSHA256(authKey))
                        using (var encryptedStream = new MemoryStream())
                        {
                            using (var writer = new BinaryWriter(encryptedStream))
                            {
                                writer.Write(aadBytes);
                                writer.Write(iv);
                                writer.Write(cipherText);
                                writer.Flush();

                                var calcTag = hmac.ComputeHash(encryptedStream.ToArray());

                                if (!calcTag.EquivalentTo(sentTag))
                                {
                                    return;
                                }
                            }
                        }

                    JsonObject jwtPayload;
                    var        aes = Aes.Create();
                    aes.KeySize   = 128;
                    aes.BlockSize = 128;
                    aes.Mode      = CipherMode.CBC;
                    aes.Padding   = PaddingMode.PKCS7;
                    using (aes)
                        using (var decryptor = aes.CreateDecryptor(cryptKey, iv))
                            using (var ms = MemoryStreamFactory.GetStream(cipherText))
                                using (var cryptStream = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                                {
                                    var jwtPayloadBytes = cryptStream.ReadFully();
                                    jwtPayload = JsonObject.Parse(jwtPayloadBytes.FromUtf8Bytes());
                                }

                    var session = CreateSessionFromPayload(req, jwtPayload);
                    req.Items[Keywords.Session] = session;
                }
            }
        }
示例#16
0
        public string SerializeToString(IRequest req, object response)
        {
            var contentType = req.ResponseContentType;

            StreamSerializerDelegate responseStreamWriter;

            if (this.ContentTypeSerializers.TryGetValue(contentType, out responseStreamWriter) ||
                this.ContentTypeSerializers.TryGetValue(ContentFormat.GetRealContentType(contentType), out responseStreamWriter))
            {
                using (var ms = MemoryStreamFactory.GetStream())
                {
                    responseStreamWriter(req, response, ms);

                    ms.Position = 0;
                    var result = new StreamReader(ms, UTF8EncodingWithoutBom).ReadToEnd();
                    return(result);
                }
            }

            ResponseSerializerDelegate responseWriter;

            if (this.ContentTypeResponseSerializers.TryGetValue(contentType, out responseWriter) ||
                this.ContentTypeResponseSerializers.TryGetValue(ContentFormat.GetRealContentType(contentType), out responseWriter))
            {
                using (var ms = MemoryStreamFactory.GetStream())
                {
                    var httpRes = new HttpResponseStreamWrapper(ms, req)
                    {
                        KeepOpen = true, //Don't let view engines close the OutputStream
                    };
                    responseWriter(req, response, httpRes);

                    var bytes  = ms.ToArray();
                    var result = bytes.FromUtf8Bytes();

                    return(result);
                }
            }

            var contentTypeAttr = ContentFormat.GetEndpointAttributes(contentType);

            switch (contentTypeAttr)
            {
            case RequestAttributes.Xml:
                return(XmlSerializer.SerializeToString(response));

            case RequestAttributes.Json:
                return(JsonDataContractSerializer.Instance.SerializeToString(response));

            case RequestAttributes.Jsv:
                return(TypeSerializer.SerializeToString(response));

            case RequestAttributes.Soap11:
                return(SoapHandler.SerializeSoap11ToBytes(req, response).FromUtf8Bytes());

            case RequestAttributes.Soap12:
                return(SoapHandler.SerializeSoap12ToBytes(req, response).FromUtf8Bytes());
            }

            throw new NotSupportedException("ContentType not supported: " + contentType);
        }
示例#17
0
        public async Task githubMarkdown(ScriptScopeContext scope, string markdownPath)
        {
            var file         = Context.ProtectedMethods.ResolveFile(nameof(githubMarkdown), scope, markdownPath);
            var htmlFilePath = file.VirtualPath.LastLeftPart('.') + ".html";
            var cacheKey     = nameof(GitHubMarkdownScripts) + ">" + htmlFilePath;

            var htmlFile = Context.VirtualFiles.GetFile(htmlFilePath);

            if (htmlFile != null && htmlFile.LastModified >= file.LastModified)
            {
                if (UseMemoryCache)
                {
                    byte[] bytes;
                    if (!Context.Cache.TryGetValue(cacheKey, out object oBytes))
                    {
                        using (var stream = htmlFile.OpenRead())
                        {
                            var ms = MemoryStreamFactory.GetStream();
                            using (ms)
                            {
                                await stream.CopyToAsync(ms);

                                ms.Position             = 0;
                                bytes                   = ms.ToArray();
                                Context.Cache[cacheKey] = bytes;
                            }
                        }
                    }
                    else
                    {
                        bytes = (byte[])oBytes;
                    }
                    scope.OutputStream.Write(bytes, 0, bytes.Length);
                }
                else
                {
                    using (var htmlReader = htmlFile.OpenRead())
                    {
                        await htmlReader.CopyToAsync(scope.OutputStream);
                    }
                }
            }
            else
            {
                var ms = MemoryStreamFactory.GetStream();
                using (ms)
                {
                    using (var stream = file.OpenRead())
                    {
                        await stream.CopyToAsync(ms);
                    }

                    ms.Position = 0;
                    var bytes = ms.ToArray();

                    var htmlBytes = RepositoryContext == null
                        ? await ApiBaseUrl.CombineWith("markdown", "raw")
                                    .PostBytesToUrlAsync(bytes, contentType: MimeTypes.PlainText, requestFilter: x => x.UserAgent = "#Script")
                        : await ApiBaseUrl.CombineWith("markdown")
                                    .PostBytesToUrlAsync(new Dictionary <string, string> {
                        { "text", bytes.FromUtf8Bytes() }, { "mode", Mode }, { "context", RepositoryContext }
                    }.ToJson().ToUtf8Bytes(),
                                                         contentType: MimeTypes.Json, requestFilter: x => x.UserAgent = "#Script");


                    var headerBytes = "<div class=\"gfm\">".ToUtf8Bytes();
                    var footerBytes = "</div>".ToUtf8Bytes();

                    var wrappedBytes = new byte[headerBytes.Length + htmlBytes.Length + footerBytes.Length];
                    System.Buffer.BlockCopy(headerBytes, 0, wrappedBytes, 0, headerBytes.Length);
                    System.Buffer.BlockCopy(htmlBytes, 0, wrappedBytes, headerBytes.Length, htmlBytes.Length);
                    System.Buffer.BlockCopy(footerBytes, 0, wrappedBytes, headerBytes.Length + htmlBytes.Length, footerBytes.Length);

                    if (Context.VirtualFiles is IVirtualFiles vfs)
                    {
                        var fs = vfs.GetFileSystemVirtualFiles();
                        fs.DeleteFile(htmlFilePath);
                        fs.WriteFile(htmlFilePath, wrappedBytes);
                    }

                    if (UseMemoryCache)
                    {
                        Context.Cache[cacheKey] = wrappedBytes;
                    }
                    await scope.OutputStream.WriteAsync(wrappedBytes, 0, wrappedBytes.Length);
                }
            }
        }
        public override async Task ProcessRequestAsync(IRequest httpReq, IResponse httpRes, string operationName)
        {
            var args = httpReq.GetTemplateRequestParams();

            if (Args != null)
            {
                foreach (var entry in Args)
                {
                    args[entry.Key] = entry.Value;
                }
            }

            var pageResult = new PageResult(page)
            {
                Args       = args,
                LayoutPage = layoutPage,
                Model      = Model,
            };

            try
            {
                httpRes.ContentType = page.Format.ContentType;
                if (OutputStream != null)
                {
                    await pageResult.WriteToAsync(OutputStream);
                }
                else
                {
                    // Buffering improves perf when running behind a reverse proxy (recommended for .NET Core)
                    using (var ms = MemoryStreamFactory.GetStream())
                    {
                        await pageResult.WriteToAsync(ms);

                        if (pageResult.Args.TryGetValue(TemplateConstants.Return, out var response))
                        {
                            if (response is Task <object> responseTask)
                            {
                                response = await responseTask;
                            }
                            if (response is IRawString raw)
                            {
                                response = raw.ToRawString();
                            }

                            if (response != null)
                            {
                                var httpResult = TemplateApiPagesService.ToHttpResult(pageResult, response);
                                await httpRes.WriteToResponse(httpReq, httpResult);

                                return;
                            }
                        }

                        ms.Position = 0;
                        await ms.WriteToAsync(httpRes.OutputStream);
                    }
                }
            }
            catch (Exception ex)
            {
                await page.Format.OnViewException(pageResult, httpReq, ex);
            }
        }
        public void PreAuthenticate(IRequest req, IResponse res)
        {
            if (req.OperationName != null && IgnoreForOperationTypes.Contains(req.OperationName))
            {
                return;
            }

            var bearerToken = req.GetJwtToken();

            if (bearerToken != null)
            {
                var parts = bearerToken.Split('.');
                if (parts.Length == 3)
                {
                    if (RequireSecureConnection && !req.IsSecureConnection)
                    {
                        throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection);
                    }

                    var jwtPayload = GetVerifiedJwtPayload(parts);
                    if (jwtPayload == null) //not verified
                    {
                        return;
                    }

                    if (ValidateToken != null)
                    {
                        if (!ValidateToken(jwtPayload, req))
                        {
                            throw HttpError.Forbidden(ErrorMessages.TokenInvalid);
                        }
                    }

                    var session = CreateSessionFromPayload(req, jwtPayload);
                    req.Items[Keywords.Session] = session;
                }
                else if (parts.Length == 5) //Encrypted JWE Token
                {
                    if (RequireSecureConnection && !req.IsSecureConnection)
                    {
                        throw HttpError.Forbidden(ErrorMessages.JwtRequiresSecureConnection);
                    }

                    if (PrivateKey == null || PublicKey == null)
                    {
                        throw new NotSupportedException("PrivateKey is required to DecryptPayload");
                    }

                    var jweHeaderBase64Url  = parts[0];
                    var jweEncKeyBase64Url  = parts[1];
                    var ivBase64Url         = parts[2];
                    var cipherTextBase64Url = parts[3];
                    var tagBase64Url        = parts[4];

                    var sentTag    = tagBase64Url.FromBase64UrlSafe();
                    var aadBytes   = (jweHeaderBase64Url + "." + jweEncKeyBase64Url).ToUtf8Bytes();
                    var iv         = ivBase64Url.FromBase64UrlSafe();
                    var cipherText = cipherTextBase64Url.FromBase64UrlSafe();

                    var jweEncKey        = jweEncKeyBase64Url.FromBase64UrlSafe();
                    var cryptAuthKeys256 = RsaUtils.Decrypt(jweEncKey, PrivateKey.Value, UseRsaKeyLength);

                    var authKey  = new byte[128 / 8];
                    var cryptKey = new byte[128 / 8];
                    Buffer.BlockCopy(cryptAuthKeys256, 0, authKey, 0, authKey.Length);
                    Buffer.BlockCopy(cryptAuthKeys256, authKey.Length, cryptKey, 0, cryptKey.Length);

                    using (var hmac = new HMACSHA256(authKey))
                        using (var encryptedStream = new MemoryStream())
                        {
                            using (var writer = new BinaryWriter(encryptedStream))
                            {
                                writer.Write(aadBytes);
                                writer.Write(iv);
                                writer.Write(cipherText);
                                writer.Flush();

                                var calcTag = hmac.ComputeHash(encryptedStream.ToArray());

                                if (!calcTag.EquivalentTo(sentTag))
                                {
                                    return;
                                }
                            }
                        }

                    JsonObject jwtPayload;
                    var        aes = Aes.Create();
                    aes.KeySize   = 128;
                    aes.BlockSize = 128;
                    aes.Mode      = CipherMode.CBC;
                    aes.Padding   = PaddingMode.PKCS7;
                    using (aes)
                        using (var decryptor = aes.CreateDecryptor(cryptKey, iv))
                            using (var ms = MemoryStreamFactory.GetStream(cipherText))
                                using (var cryptStream = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                                {
                                    var jwtPayloadBytes = cryptStream.ReadFully();
                                    jwtPayload = JsonObject.Parse(jwtPayloadBytes.FromUtf8Bytes());
                                }

                    if (ValidateToken != null)
                    {
                        if (!ValidateToken(jwtPayload, req))
                        {
                            throw HttpError.Forbidden(ErrorMessages.TokenInvalid);
                        }
                    }

                    var session = CreateSessionFromPayload(req, jwtPayload);
                    req.Items[Keywords.Session] = session;
                }
            }
        }