public async Task ExecuteAsync(HttpContext context)
        {
            Init(context);

            var validatedRequest = _result.IsError ? null : _result.ValidatedRequest;

            string id = null;

            if (validatedRequest != null)
            {
                var msg = new MessageWithId <LogoutMessage>(new LogoutMessage(validatedRequest));
                id = msg.Id;

                await _logoutMessageStore.WriteAsync(id, msg);

                await _clientSessionService.EnsureClientListCookieAsync(validatedRequest.SessionId);
            }

            var redirect = _options.UserInteraction.LogoutUrl;

            if (redirect.IsLocalUrl())
            {
                redirect = context.GetIdentityServerRelativeUrl(redirect);
            }

            if (id != null)
            {
                redirect = redirect.AddQueryString(_options.UserInteraction.LogoutIdParameter, id);
            }

            context.Response.Redirect(redirect);
        }
示例#2
0
        static bool HasMore(MessageWithId msg)
        {
            var hasMore = ((MessageFlags)msg.Attributes & MessageFlags.ToBeContinued) ==
                          MessageFlags.ToBeContinued;

            return(hasMore);
        }
示例#3
0
 private void TaskCompletionSourceInvoke(MessageWithId message, string method, object parameter, Type[] types = null)
 {
     if (message.HasRequestId && WaitingTasks.TryRemove(message.RequestId, out object tcs))
     {
         var tcsType = tcs.GetType();
         (types == null ? tcsType.GetMethod(method) : tcsType.GetMethod(method, types)).Invoke(tcs, new object[] { parameter });
     }
 }
示例#4
0
        private MessageWithId <ServerMessage> SendReceive(MessageWithId <ClientMessage> msg)
        {
            _nitraClient.Send(msg.Message);

            return(new MessageWithId <ServerMessage> {
                Id = msg.Id,
                Message = _nitraClient.Receive <ServerMessage>()
            });
        }
示例#5
0
 static bool TryRead(BinaryReader reader, out MessageWithId msg)
 {
     try {
         msg = StorageFormat.Read(reader);
         return(true);
     }
     catch (EndOfStreamException) {
         msg = null;
         return(false);
     }
 }
示例#6
0
        private void TaskCompletionSourceInvoke(MessageWithId message, string method, object parameter, Type[] types = null)
        {
            if (!message.HasRequestId || !_sender.WaitingTasks.TryRemove(message.RequestId, out object tcs))
            {
                return;
            }
            var tcsType        = tcs.GetType();
            var methodToInvoke = types == null?tcsType.GetMethod(method) : tcsType.GetMethod(method, types);

            var  methodParameters = methodToInvoke.GetParameters();
            bool isAsignable      = methodParameters.First().ParameterType.IsAssignableFrom(parameter.GetType());

            methodToInvoke.Invoke(tcs, isAsignable ? new[] { parameter } : new object[] { null });
        }
示例#7
0
        public static void Write(BinaryWriter writer, MessageWithId item)
        {
            writer.Write(HeaderSignature);

            writer.Write(item.Id.GetBytes());
            // we know for 100% that key length will be byte

            writer.Write((byte)item.Key.Length);
            writer.Write(item.Key);
            // we know for 100% that value length will be ushort
            writer.Write(item.Value.Length);
            writer.Write(item.Value);
            writer.Write(FooterSignature);
        }
        private async Task <IEndpointResult> CreateLogoutPageRedirectAsync(EndSessionValidationResult result)
        {
            var validatedRequest = result.IsError ? null : result.ValidatedRequest;

            if (validatedRequest != null &&
                (validatedRequest.Client != null || validatedRequest.PostLogOutUri != null))
            {
                var msg = new MessageWithId <LogoutMessage>(new LogoutMessage(validatedRequest));
                await _logoutMessageStore.WriteAsync(msg.Id, msg);

                return(new LogoutPageResult(_context.Options.UserInteractionOptions, msg.Id));
            }

            return(new LogoutPageResult(_context.Options.UserInteractionOptions));
        }
        async Task RedirectToErrorPageAsync(HttpContext context)
        {
            var errorModel = new ErrorMessage
            {
                RequestId = context.TraceIdentifier,
                Error     = Response.Error
            };

            var message = new MessageWithId <ErrorMessage>(errorModel);
            await _errorMessageStore.WriteAsync(message.Id, message);

            var errorUrl = _options.UserInteraction.ErrorUrl;

            var url = errorUrl.AddQueryString(_options.UserInteraction.ErrorIdParameter, message.Id);

            context.Response.RedirectToAbsoluteUrl(url);
        }
示例#10
0
 private async void TaskCompletionSourceInvoke(MessageWithId message, string method, object parameter, Type[] types = null)
 {
     if (message.HasRequestId && WaitingTasks.TryRemove(message.RequestId, out object tcs))
     {
         var tcsType = tcs.GetType();
         (types == null ? tcsType.GetMethod(method) : tcsType.GetMethod(method, types)).Invoke(tcs, new object[] { parameter });
     }
     else
     {
         //This is just to handle media status messages. Where we want to update the status of media but we are not expecting an update
         if (message.Type == "MEDIA_STATUS")
         {
             var statusMessage = parameter as MediaStatusMessage;
             await GetChannel <MediaChannel>().OnMessageReceivedAsync(statusMessage);
         }
     }
 }
示例#11
0
        public async Task <string> CreateLogoutContextAsync()
        {
            var sid = await _sessionIdService.GetCurrentSessionIdAsync();

            if (sid != null)
            {
                await _clientSessionService.EnsureClientListCookieAsync(sid);

                var msg = new MessageWithId <LogoutMessage>(new LogoutMessage {
                    SessionId = sid
                });

                var id = msg.Id;
                await _logoutMessageStore.WriteAsync(id, msg);

                return(id);
            }

            return(null);
        }
示例#12
0
        public async Task ExecuteAsync(HttpContext context)
        {
            Init(context);

            var validatedRequest = _result.IsError ? null : _result.ValidatedRequest;

            string id = null;

            if (validatedRequest != null)
            {
                var msg = new MessageWithId <LogoutMessage>(new LogoutMessage(validatedRequest));
                id = msg.Id;

                await _logoutMessageStore.WriteAsync(id, msg);

                await _clientSessionService.EnsureClientListCookieAsync(validatedRequest.SessionId);
            }

            var redirect = _options.UserInteractionOptions.LogoutUrl;

            if (redirect.IsLocalUrl())
            {
                // TODO: look at GetIdentityServerRelativeUrl instead and logic if the above if check; compare to login result
                if (redirect.StartsWith("~/"))
                {
                    redirect = redirect.Substring(1);
                }
                redirect = context.GetIdentityServerBaseUrl().EnsureTrailingSlash() + redirect.RemoveLeadingSlash();
            }

            if (id != null)
            {
                redirect = redirect.AddQueryString(_options.UserInteractionOptions.LogoutIdParameter, id);
            }

            context.Response.Redirect(redirect);
        }
示例#13
0
 void WriteMessage(MessageWithId msg)
 {
     EnsureSizeToAvoidFragmentation();
     CacheStorage.Write(_writer, msg);
 }
示例#14
0
        public async Task <FetchResult> DownloadNextAsync(CancellationToken token)
        {
            var pos = _cacheChk.ReadPositionVolatile();

            var convertedLocalPos     = pos[0];
            var currentRemotePosition = pos[1];


            var maxRemotePos = await _remotePos.ReadAsync(token)
                               .ConfigureAwait(false);

            var result = new FetchResult()
            {
                MaxRemotePosition     = maxRemotePos,
                CurrentRemotePosition = currentRemotePosition,
                CurrentCachePosition  = convertedLocalPos,
                DownloadedBytes       = 0,
                UsedBytes             = 0,
                SavedBytes            = 0
            };

            if (maxRemotePos <= currentRemotePosition)
            {
                // we don't have anything to write
                return(result);
            }

            var availableAmount = maxRemotePos - currentRemotePosition;
            var amountToLoad    = Math.Min(availableAmount, AmountToLoadMax);

            long usedBytes         = 0;
            long downloadedRecords = 0;

            using (var mem = _streamManager.GetStream("fetcher")) {
                await _remote.DownloadRangeToStreamAsync(mem, currentRemotePosition, (int)amountToLoad)
                .ConfigureAwait(false);

                // cool, we've got some data back

                result.DownloadedBytes = mem.Position;
                mem.Seek(0, SeekOrigin.Begin);


                _cacheWriter.Seek(convertedLocalPos, SeekOrigin.Begin);

                var pages = new List <MessageWithId>();
                using (var bin = new BinaryReader(mem)) {
                    MessageWithId msg;
                    while (TryRead(bin, out msg))
                    {
                        var hasMorePagesToRead = HasMore(msg);

                        if (false == hasMorePagesToRead && pages.Count == 0)
                        {
                            // fast path, we can save message directly without merging
                            WriteMessage(msg);
                            downloadedRecords += 1;
                            usedBytes          = mem.Position;
                            continue;
                        }

                        pages.Add(msg);
                        if (hasMorePagesToRead)
                        {
                            continue;
                        }

                        var total = pages.Sum(m => m.Value.Length);
                        using (var sub = _streamManager.GetStream("chase-1", total))
                        {
                            foreach (var page in pages)
                            {
                                sub.Write(page.Value, 0, page.Value.Length);
                            }
                            sub.Seek(0, SeekOrigin.Begin);
                            var last  = pages.Last();
                            var final = new MessageWithId(last.Id, last.Attributes, last.Key, sub.ToArray(), 0);
                            WriteMessage(final);
                            usedBytes          = mem.Position;
                            downloadedRecords += 1;
                        }
                        pages.Clear();
                    }
                }
                if (usedBytes == 0)
                {
                    return(result);
                }
                _writer.Flush();
                _cacheWriter.Flush(true);
                _cacheChk.Update(new[] {
                    _cacheWriter.Position,
                    currentRemotePosition + usedBytes,
                    maxRemotePos
                });

                result.UsedBytes         = usedBytes;
                result.SavedBytes        = _cacheWriter.Position - result.CurrentCachePosition;
                result.DownloadedRecords = downloadedRecords;
                return(result);
            }
        }
示例#15
0
        public async Task <DirectReadResult> ReadAll(CancellationToken token, long startingFrom, int maxCount, MessageHandler handler)
        {
            //var convertedLocalPos = pos[0];
            //var currentRemotePosition = pos[1];

            var watch  = Stopwatch.StartNew();
            var maxPos = await _remotePos.ReadAsync(token)
                         .ConfigureAwait(false);

            var result = new DirectReadResult
            {
                StartingPosition = startingFrom,
                CurrentPosition  = startingFrom,
                MaxPosition      = maxPos,
            };

            if (maxPos <= startingFrom)
            {
                // we don't have anything to write
                return(result);
            }

            var availableAmount = maxPos - startingFrom;

            if (availableAmount <= 0)
            {
                // we don't have anything to write
                return(result);
            }

            var amountToLoad = Math.Min(availableAmount, AmountToLoadMax);

            using (var mem = _streamManager.GetStream("fetcher"))
            {
                await _remote.DownloadRangeToStreamAsync(mem, startingFrom, (int)amountToLoad)
                .ConfigureAwait(false);

                // cool, we've got some data back

                mem.Seek(0, SeekOrigin.Begin);

                var usedBytes = 0L;

                var pages = new List <MessageWithId>();
                using (var bin = new BinaryReader(mem))
                {
                    MessageWithId msg;
                    while (TryRead(bin, out msg))
                    {
                        var hasMorePagesToRead = HasMore(msg);

                        if (false == hasMorePagesToRead && pages.Count == 0)
                        {
                            // fast path, we can save message directly without merging
                            handler(msg, msg.Id.GetOffset(), maxPos);

                            //WriteMessage(msg);
                            usedBytes           = mem.Position;
                            result.ReadRecords += 1;

                            continue;
                        }

                        pages.Add(msg);
                        if (hasMorePagesToRead)
                        {
                            continue;
                        }

                        var total = pages.Sum(m => m.Value.Length);
                        using (var sub = _streamManager.GetStream("chase-1", total))
                        {
                            foreach (var page in pages)
                            {
                                sub.Write(page.Value, 0, page.Value.Length);
                            }
                            sub.Seek(0, SeekOrigin.Begin);
                            var last  = pages.Last();
                            var final = new MessageWithId(last.Id, last.Attributes, last.Key, sub.ToArray(), 0);
                            handler(final, last.Id.GetOffset(), maxPos);
                            usedBytes           = mem.Position;
                            result.ReadRecords += 1;
                        }
                        pages.Clear();
                    }
                }
                result.CurrentPosition = result.StartingPosition + usedBytes;
                result.Elapsed         = watch.Elapsed;
                return(result);
            }
        }
示例#16
0
        public async Task <IEndpointResult> CreateErrorResultAsync(ErrorTypes errorType, string error, ValidatedAuthorizeRequest request)
        {
            if (errorType == ErrorTypes.Client && request == null)
            {
                throw new ArgumentNullException(nameof(request), "Request must be passed when error type is Client.");
            }

            AuthorizeResponse response = null;

            if (errorType == ErrorTypes.Client)
            {
                response = new AuthorizeResponse
                {
                    Request     = request,
                    IsError     = true,
                    Error       = error,
                    State       = request.State,
                    RedirectUri = request.RedirectUri
                };

                // do some early checks to see if we will end up not generating an error page
                if (error == OidcConstants.AuthorizeErrors.AccessDenied)
                {
                    return(await CreateAuthorizeResultAsync(response));
                }

                if (request.PromptMode == OidcConstants.PromptModes.None &&
                    request.Client.AllowPromptNone == true &&
                    (error == OidcConstants.AuthorizeErrors.LoginRequired ||
                     error == OidcConstants.AuthorizeErrors.ConsentRequired ||
                     error == OidcConstants.AuthorizeErrors.InteractionRequired)
                    )
                {
                    // todo: verify these are the right conditions to allow
                    // redirecting back to client
                    // https://tools.ietf.org/html/draft-bradley-oauth-open-redirector-00
                    return(await CreateAuthorizeResultAsync(response));
                }
                else
                {
                    //_logger.LogWarning("Rendering error page due to prompt=none, client does not allow prompt mode none, response is query, and ");
                }
            }

            // we now know we must show error page
            var msg = _localizationService.GetMessage(error);

            if (msg.IsMissing())
            {
                msg = error;
            }

            var errorModel = new ErrorMessage
            {
                RequestId        = _context.HttpContext.TraceIdentifier,
                ErrorCode        = error,
                ErrorDescription = msg
            };

            if (errorType == ErrorTypes.Client)
            {
                // if this is a client error, we need to build up the
                // response back to the client, and provide it in the
                // error view model so the UI can build the link/form
                errorModel.ReturnInfo = new ClientReturnInfo
                {
                    ClientId = request.ClientId,
                };

                if (request.ResponseMode == OidcConstants.ResponseModes.Query ||
                    request.ResponseMode == OidcConstants.ResponseModes.Fragment)
                {
                    errorModel.ReturnInfo.Uri = request.RedirectUri = AuthorizeRedirectResult.BuildUri(response);
                }
                else if (request.ResponseMode == OidcConstants.ResponseModes.FormPost)
                {
                    errorModel.ReturnInfo.Uri      = request.RedirectUri;
                    errorModel.ReturnInfo.PostBody = AuthorizeFormPostResult.BuildFormBody(response);
                }
                else
                {
                    _logger.LogError("Unsupported response mode.");
                    throw new InvalidOperationException("Unsupported response mode");
                }
            }

            var message = new MessageWithId <ErrorMessage>(errorModel);
            await _errorMessageStore.WriteAsync(message.Id, message);

            return(new ErrorPageResult(_context.Options.UserInteractionOptions, message.Id));
        }