Exemplo n.º 1
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);
            //}
        }
Exemplo n.º 2
0
 public HttpResult(byte[] responseBytes, string contentType)
     : this(null, contentType, HttpStatusCode.OK)
 {
     this.AllowsPartialResponse = true;
     this.ResponseStream        = MemoryStreamFactory.GetStream(responseBytes);
 }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
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));

#if !NETSTANDARD1_6
            case RequestAttributes.Soap11:
                return(SoapHandler.SerializeSoap11ToBytes(req, response).FromUtf8Bytes());

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

            throw new NotSupportedException("ContentType not supported: " + contentType);
        }
Exemplo n.º 5
0
        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;
                    using (var aes = new AesManaged
                    {
                        KeySize = 128,
                        BlockSize = 128,
                        Mode = CipherMode.CBC,
                        Padding = PaddingMode.PKCS7
                    })
                        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;
                }
            }
        }
Exemplo n.º 6
0
        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);

            if (webReq != null && Proxy != null)
            {
                webReq.Proxy = Proxy;
            }

            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().ConfigAwait();

                    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().ConfigAwait();

                {
                    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).ConfigAwait()) != 0)
                    {
                        await ms.WriteAsync(bufferRead, 0, read, token).ConfigAwait();

                        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)await stream.ReadToEndAsync().ConfigAwait()));
                                }
                                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,
                                UseTokenCookie = UseTokenCookie,
                            };
                            var uri = this.RefreshTokenUri ?? this.BaseUri.CombineWith(refreshRequest.ToPostUrl());

                            GetAccessTokenResponse tokenResponse;
                            try
                            {
                                tokenResponse = (await uri.PostJsonToUrlAsync(refreshRequest, requestFilter: req => {
                                    if (UseTokenCookie)
                                    {
                                        req.CookieContainer = CookieContainer;
                                    }
                                }).ConfigAwait()).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;
                            var refreshClient = webReq = (HttpWebRequest)WebRequest.Create(requestUri);
                            var tokenCookie   = this.CookieContainer.GetTokenCookie(BaseUri);

                            if (UseTokenCookie)
                            {
                                if (tokenCookie == null)
                                {
                                    throw new RefreshTokenException("Could not retrieve new AccessToken Cooke from: " + uri);
                                }

                                refreshClient.CookieContainer.SetTokenCookie(BaseUri, tokenCookie);
                            }
                            else
                            {
                                if (string.IsNullOrEmpty(accessToken))
                                {
                                    throw new RefreshTokenException("Could not retrieve new AccessToken from: " + uri);
                                }

                                if (tokenCookie != 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).ConfigAwait());
                        }

                        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).ConfigAwait());
                    }
                    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();
                }
            }
        }
Exemplo n.º 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);
                                        }
                            }
            }
        }
        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 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;
                }
            }
        }
Exemplo n.º 9
0
        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 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);
            }
        }
Exemplo n.º 10
0
 internal static MemoryStream CreateBufferedStream(this IResponse response)
 {
     return(MemoryStreamFactory.GetStream());
 }
Exemplo n.º 11
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;
            }
        }