示例#1
0
        private ActionResult List(string categorySlug, string query, UrlToken <SortOrder> order, UrlToken <SortDirection> direction, int?page, int?size)
        {
            CategoryModel category = null;

            if (!string.IsNullOrEmpty(categorySlug))
            {
                category = _categoryRepository.GetBySlug(categorySlug);

                if (category == null)
                {
                    throw new HttpException((int)HttpStatusCode.NotFound, Resources.Error_NotFound_Category);
                }
            }

            int totalItemsCount;
            var collection = _productRepository.GetProducts(category, query, order, direction, ref page, ref size, out totalItemsCount);

            var viewModel = new ProductListViewModel(collection)
            {
                Category        = category,
                Query           = query,
                Page            = page.GetValueOrDefault(),
                Size            = size.GetValueOrDefault(),
                Order           = order,
                Direction       = direction,
                TotalItemsCount = totalItemsCount
            };

            return(ViewAsync(Views.List, Views._List, viewModel));
        }
        public async Task StartAsync(IDialogContext context)
        {
            Logger.Info("StartAsync...");
            var incoming = context.Activity as Activity;
            var jsonText = JsonConvert.SerializeObject(incoming.ChannelData);

            Logger.Info($"JsonText={jsonText}");
            var channelData = JsonConvert.DeserializeObject <OCSBot.Shared.Models.DirectLineChannelData>(jsonText);

            Logger.Info($"ChannelData.DirectLineBotID={channelData.DirectLineBotID}");
            var storage           = new AgentStatusStorage(ConfigurationHelper.GetString("BotStatusDBConnectionString"));
            var localConversation = (await storage.FindMyConversationActivityAsync(channelData.UserID)).FirstOrDefault();

            Logger.Info($"localConversation={localConversation}");

            var resumptionCookie = UrlToken.Decode <ResumptionCookie>(localConversation.LocalActivity);
            var localActivity    = resumptionCookie.GetMessage();
            var message          = ((Activity)context.Activity).Text.Replace("reply:", "");

            message = $"[{incoming.From.Name}]{message}";
            var reply = localActivity.CreateReply(message);

            Logger.Info($"reply={JsonConvert.SerializeObject(reply)}");
            var localConnector = new ConnectorClient(new Uri(localActivity.ServiceUrl),
                                                     new MicrosoftAppCredentials(
                                                         ConfigurationHelper.GetString("MicrosoftAppId"),
                                                         ConfigurationHelper.GetString("MicrosoftAppPassword")),
                                                     true);

            Microsoft.Bot.Connector.Conversations localConversations = new Microsoft.Bot.Connector.Conversations(localConnector);
            localConversations.ReplyToActivity(reply);
            Logger.Info("Done");
        }
示例#3
0
 public UrlBuilder(Provider <UrlToken> urlToken, IUrlHelper urlHelper)
 {
     Ensure.NotNull(urlToken, "urlToken");
     Ensure.NotNull(urlHelper, "urlHelper");
     this.urlToken  = urlToken.Optional;
     this.urlHelper = urlHelper;
 }
示例#4
0
        /// <summary>
        /// Generates the state to be utilized with the authentication request.
        /// </summary>
        /// <param name="context">Context for the dialog.</param>
        /// <returns>A string that represents the current state for the user.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="context"/> is null.
        /// </exception>
        private string GenerateState(IDialogContext context)
        {
            Dictionary <string, string> state;
            Guid uniqueId = Guid.NewGuid();

            context.AssertNotNull(nameof(context));

            try
            {
                state = new Dictionary <string, string>
                {
                    { BotConstants.BotIdKey, conversationReference.Bot.Id },
                    { BotConstants.ChannelIdKey, conversationReference.ChannelId },
                    { BotConstants.ConversationIdKey, conversationReference.Conversation.Id },
                    { BotConstants.UniqueIdentifierKey, uniqueId.ToString() },
                    { BotConstants.ServiceUrlKey, conversationReference.ServiceUrl },
                    { BotConstants.UserIdKey, conversationReference.User.Id }
                };

                // Save the unique identifier in the user's private conversation store. This value will be
                // utilized to verify the authentication request.
                context.PrivateConversationData.SetValue(BotConstants.UniqueIdentifierKey, uniqueId);

                return(UrlToken.Encode(state));
            }
            finally
            {
                state = null;
            }
        }
        private void RequestLogin(Microsoft.Bot.Connector.Activity message)
        {
            var resumptionCookie        = new ResumptionCookie(message);
            var encodedResumptionCookie = UrlToken.Encode <ResumptionCookie>(resumptionCookie);

            Microsoft.Bot.Connector.Activity oriMessage = resumptionCookie.GetMessage();


            var reply = oriMessage.CreateReply(Messages.BOT_PLEASE_LOGIN);

            reply.Recipient   = oriMessage.From;
            reply.Type        = Microsoft.Bot.Connector.ActivityTypes.Message;
            reply.Attachments = new List <Microsoft.Bot.Connector.Attachment>();
            List <Microsoft.Bot.Connector.CardAction> cardButtons = new List <Microsoft.Bot.Connector.CardAction>();
            var encodedCookie = UrlToken.Encode(resumptionCookie);

            Microsoft.Bot.Connector.CardAction button = new Microsoft.Bot.Connector.CardAction()
            {
                Value = $"{ConfigurationHelper.GetString("AgentLogin_URL")}?cookie={encodedCookie}",
                Type  = "signin",
                Title = Messages.BOT_SIGNIN_BUTTON_TEXT,
                Image = "https://michistorageea.blob.core.windows.net/cdn/login.png"
            };
            cardButtons.Add(button);
            Microsoft.Bot.Connector.SigninCard plCard = new Microsoft.Bot.Connector.SigninCard(
                text: $"{Messages.BOT_PLEASE_LOGIN}",
                buttons: cardButtons);
            Microsoft.Bot.Connector.Attachment plAttachment = plCard.ToAttachment();
            reply.Attachments.Add(plAttachment);
            ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
            var             response  = connector.Conversations.SendToConversation(reply);
        }
        public async Task <HttpResponseMessage> Get(string code, string state, CancellationToken cancellationToken)
        {
            // 從 state 參數轉換為原本的 ConversationReference
            ConversationReference conversationReference = UrlToken.Decode <ConversationReference>(state);

            // 請求拿到 Google OAuth 的 Access Token
            var accessToken = await GoogleOAuthHelper.ExchangeCodeForGoogleAccessToken(code, BotUtility.OAuthCallbackURL);

            var msg = conversationReference.GetPostToBotMessage();

            // 取得目前談話對象的容器,並且把 UserData 加入 Access Token
            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, msg))
            {
                IStateClient sc       = scope.Resolve <IStateClient>();
                BotData      userData = sc.BotState.GetUserData(msg.ChannelId, msg.From.Id);
                userData.SetProperty(BotUtility.AccessToken, accessToken.AccessToken);
                sc.BotState.SetUserData(msg.ChannelId, msg.From.Id, userData);
            }

            // 設定 ResumeAsync 回到 MessagesController 的識別值 (例如: 使用 token 關鍵字, 真實案例不適合這樣用)
            msg.Text = "token:" + accessToken.AccessToken;

            // 要記得使用 RsumeAsync 才能夠接回原本的 converstaion
            await Conversation.ResumeAsync(conversationReference, msg);

            return(Request.CreateResponse("ok"));
        }
示例#7
0
        public void UrlToken_Can_Serialize_Address()
        {
            var expected = MakeAddress();
            var encoded  = UrlToken.Encode(expected);
            var actual   = UrlToken.Decode <Address>(encoded);

            Assert.AreEqual(expected, actual);
        }
 public void SetUp()
 {
     this.deserializedObject = new UrlToken()
     {
         Path = "blah"
     };
     this.uriProvider = new PreAuthenticatedUriProvider(new MockedCryptoSerializer(this));
 }
示例#9
0
        public void UrlToken_Can_Serialize_ConversationReference()
        {
            // https://github.com/Microsoft/BotBuilder/pull/1279
            var expected = MakeCookie();
            var encoded  = UrlToken.Encode(expected);
            var actual   = UrlToken.Decode <ConversationReference>(encoded);

            Assert.AreEqual(expected, actual);
        }
示例#10
0
        private string getStateParam(ConversationReference conversationRef)
        {
            var queryString = HttpUtility.ParseQueryString(string.Empty);

            queryString["conversationRef"]  = UrlToken.Encode(conversationRef);
            queryString["providerassembly"] = this.authProvider.GetType().Assembly.FullName;
            queryString["providertype"]     = this.authProvider.GetType().FullName;
            queryString["providername"]     = this.authProvider.Name;
            return(HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(queryString.ToString())));
        }
示例#11
0
        private string getStateParam(ResumptionCookie resumptionCookie)
        {
            var queryString = HttpUtility.ParseQueryString(string.Empty);

            queryString["resumption"]       = UrlToken.Encode(resumptionCookie);
            queryString["providerassembly"] = this.authProvider.GetType().Assembly.FullName;
            queryString["providertype"]     = this.authProvider.GetType().FullName;
            queryString["providername"]     = this.authProvider.Name;
            return(HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(queryString.ToString())));
        }
        private static CallbackModel GetCallbackModel(string state)
        {
            var model = new CallbackModel
            {
                Query = GetQuery(state)
            };

            model.ConversationReference = UrlToken.Decode <ConversationReference>(model.Query["conversationRef"]);
            model.Message = model.ConversationReference.GetPostToBotMessage();

            return(model);
        }
示例#13
0
        public async Task SayMyName(IDialogContext context)
        {
            try
            {
                // make a simple request to Microsoft Graph API using the Active Directory access token.
                var me = await client.Me.Request().GetAsync();

                await context.PostAsync($"Your name is {me.DisplayName}");
            }
            catch (AdalSilentTokenAcquisitionException)
            {
                await context.PostAsync(loginUri.AbsoluteUri + UrlToken.Encode(cookie));
            }
        }
        private static string BuildExtraParameters(ResumptionCookie resumptionCookie)
        {
            var encodedCookie = UrlToken.Encode(resumptionCookie);

            //var queryString = HttpUtility.ParseQueryString(string.Empty);
            //queryString["userId"] = resumptionCookie.Address.UserId;
            //queryString["botId"] = resumptionCookie.Address.BotId;
            //queryString["conversationId"] = resumptionCookie.Address.ConversationId;
            //queryString["serviceUrl"] = resumptionCookie.Address.ServiceUrl;
            //queryString["channelId"] = resumptionCookie.Address.ChannelId;
            //queryString["locale"] = resumptionCookie.Locale ?? "en";

            //return TokenEncoder(queryString.ToString());
            return(encodedCookie);
        }
        public void VerifyPreAuthenticatedUrl(string url, string urlTokenPath, string expiration, bool expectedResult)
        {
            Console.WriteLine(DateTime.UtcNow.ToString("u"));
            // "http://bahaha/filofax?$token=XYZ"
            this.deserializedObject = new UrlToken()
            {
                Path       = urlTokenPath,
                Expiration =
                    expiration != null ? (DateTime?)DateTime.Parse(expiration, CultureInfo.InvariantCulture) : null
            };
            var result = this.uriProvider.VerifyPreAuthenticatedUrl(url,
                                                                    new DateTime(2050, 1, 1, 1, 1, 1, DateTimeKind.Utc));

            Assert.That(result, Is.EqualTo(expectedResult));
        }
示例#16
0
        public static string GetGoogleLoginURL(ConversationReference conversationReference, string oauthCallback)
        {
            // 把 conversationreference 的内容放到 state 的參數裏面
            string stateToken = UrlToken.Encode(conversationReference);

            var uri = BotUtility.GetUri("https://accounts.google.com/o/oauth2/v2/auth",
                                        Tuple.Create("client_id", Google_clientId),
                                        Tuple.Create("redirect_uri", oauthCallback),
                                        Tuple.Create("response_type", "code"),
                                        Tuple.Create("access_type", "online"),
                                        Tuple.Create("scope", Uri.EscapeDataString("profile")),
                                        Tuple.Create("state", stateToken)
                                        );

            return(uri.ToString());
        }
示例#17
0
        private UploadSettings FindSettings(RouteData routeData)
        {
            UrlToken urlToken = FindUrlToken(routeData);

            if (urlToken != null)
            {
                if (configuration.Value.Profiles.TryGetValue(urlToken.Value, out var settings))
                {
                    return(settings);
                }

                return(null);
            }

            return(configuration.Value.Default);
        }
示例#18
0
        public static async Task <HttpResponseMessage> Resolve(HttpRequestMessage request, int maxWriteAttempts)
        {
            NameValueCollection parameters = null;

            if (request.Method == HttpMethod.Get)
            {
                parameters = request.RequestUri.ParseQueryString();
            }
            else if (request.Method == HttpMethod.Post)
            {
                parameters = await request.Content.ReadAsFormDataAsync();
            }

            // Create the message that is send to conversation to resume the login flow
            string state            = parameters["state"];
            var    resumptionCookie = UrlToken.Decode <ResumptionCookie>(state);
            var    message          = resumptionCookie.GetMessage();

            string dialogId;

            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
            {
                IStateClient sc       = scope.Resolve <IStateClient>();
                BotData      userData = sc.BotState.GetUserData(message.ChannelId, message.From.Id);

                dialogId = userData.GetProperty <string>(AuthenticationConstants.AuthHandlerKey);
            }

            AuthCallbackHandler handler;

            switch (dialogId)
            {
            case AuthenticationConstants.AuthDialogId_AzureAD:
                handler = new mStack.API.Bots.AzureAD.AuthCallbackHandler(maxWriteAttempts);
                break;

            case AuthenticationConstants.AuthDialogId_ExactOnline:
                handler = new mStack.API.Bots.ExactOnline.AuthCallbackHandler(maxWriteAttempts);
                break;

            default:
                throw new ArgumentException("Unknown auth handler type.");
            }

            return(await handler.ProcessOAuthCallback(parameters));
        }
        public async Task <HttpResponseMessage> LogOut([FromUri] string conversationRef)
        {
            // Get the conversation reference from the URL (this was specified when triggering logout in the first place). Send a message
            // to the user confirming logout is complete.
            var conversationRefDecoded = UrlToken.Decode <ConversationReference>(conversationRef);
            var message = conversationRefDecoded.GetPostToBotMessage();
            var client  = new ConnectorClient(new Uri(message.ServiceUrl));

            var replyMessage = message.CreateReply("You are now logged out.");
            await client.Conversations.SendToConversationAsync((Activity)replyMessage);

            // Show a message in the browser indicating logout is complete.
            var resp = new HttpResponseMessage(HttpStatusCode.OK);

            resp.Content = new StringContent($"<html><head><script type='text/javascript'>window.close();</script></head><body>You are now logged out of SharePoint. You can close this tab.</body></html>", System.Text.Encoding.UTF8, @"text/html");
            return(resp);
        }
示例#20
0
        public async Task <ITokenInfo> GetTokenInfoAsync(UrlToken urlToken, bool skipValidation = false)
        {
            const string InvalidTokenMessage = "Autorization token is invalid";

            try
            {
                if (urlToken is ValidUrlToken validUrlToken)
                {
                    return(skipValidation
                        ? _noValidationBuilder.Build(validUrlToken.RawToken)
                        : await _validationBuilder.ValidateAndBuildAsync(validUrlToken.RawToken));
                }

                throw new ApplicationException(InvalidTokenMessage);
            }
            catch (Exception ex)
            {
                throw new ApplicationException(InvalidTokenMessage, ex);
            }
        }
示例#21
0
        public async Task <string> Get(string cookie, CancellationToken token)
        {
            // get the TokenCache stored per-user from within OpenIdConnectOptions.Events.OnAuthorizationCodeReceived
            var authenticateContext = new AuthenticateContext(CookieAuthenticationDefaults.AuthenticationScheme);

            await this.HttpContext.Authentication.AuthenticateAsync(authenticateContext);

            string tokenBase64;

            if (authenticateContext.Properties.TryGetValue(Keys.TokenCache, out tokenBase64))
            {
                byte[] tokenBlob = Convert.FromBase64String(tokenBase64);

                // decode the resumption cookie from the url
                var resume       = UrlToken.Decode <ResumptionCookie>(cookie);
                var continuation = resume.GetMessage();
                using (var scope = DialogModule.BeginLifetimeScope(Container.Instance, continuation))
                {
                    var botData = scope.Resolve <IBotData>();
                    await botData.LoadAsync(token);

                    var data = botData.UserData;

                    var tenantID         = this.User.FindFirst(Keys.TenantID);
                    var objectIdentifier = this.User.FindFirst(Keys.ObjectID);

                    data.SetValue(Keys.ObjectID, objectIdentifier.Value);
                    data.SetValue(Keys.TenantID, tenantID.Value);
                    data.SetValue(Keys.TokenCache, tokenBlob);

                    await botData.FlushAsync(token);
                }

                return("You're now logged-in - continue talking to the bot!");
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
示例#22
0
        public static async Task <object> HandleOAuthCallback(HttpRequestMessage req, uint maxWriteAttempts)
        {
            try
            {
                var queryParams = req.RequestUri.ParseQueryString();

                if (req.Method != HttpMethod.Post)
                {
                    throw new ArgumentException("The OAuth postback handler only supports POST requests.");
                }

                var formData = await req.Content.ReadAsFormDataAsync();

                string stateStr = formData["state"];
                string code     = formData["code"];

                var resumptionCookie = UrlToken.Decode <ResumptionCookie>(stateStr);
                var message          = resumptionCookie.GetMessage();

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    AuthenticationSettings authSettings = AuthenticationSettings.GetFromAppSettings();

                    var client = scope.Resolve <IConnectorClient>();
                    AuthenticationResult authenticationResult = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, authSettings);

                    IStateClient sc = scope.Resolve <IStateClient>();

                    //IMPORTANT: DO NOT REMOVE THE MAGIC NUMBER CHECK THAT WE DO HERE. THIS IS AN ABSOLUTE SECURITY REQUIREMENT
                    //REMOVING THIS WILL REMOVE YOUR BOT AND YOUR USERS TO SECURITY VULNERABILITIES.
                    //MAKE SURE YOU UNDERSTAND THE ATTACK VECTORS AND WHY THIS IS IN PLACE.
                    int  magicNumber     = GenerateRandomNumber();
                    bool writeSuccessful = false;
                    uint writeAttempts   = 0;
                    while (!writeSuccessful && writeAttempts++ < maxWriteAttempts)
                    {
                        try
                        {
                            BotData userData = sc.BotState.GetUserData(message.ChannelId, message.From.Id);
                            userData.SetProperty(AuthenticationConstants.AuthResultKey, authenticationResult);
                            userData.SetProperty(AuthenticationConstants.MagicNumberKey, magicNumber);
                            userData.SetProperty(AuthenticationConstants.MagicNumberValidated, "false");
                            sc.BotState.SetUserData(message.ChannelId, message.From.Id, userData);
                            writeSuccessful = true;
                        }
                        catch (HttpOperationException)
                        {
                            writeSuccessful = false;
                        }
                    }
                    var resp = new HttpResponseMessage(HttpStatusCode.OK);
                    if (!writeSuccessful)
                    {
                        message.Text = String.Empty; // fail the login process if we can't write UserData
                        await Conversation.ResumeAsync(resumptionCookie, message);

                        resp.Content = new StringContent("<html><body>Could not log you in at this time, please try again later</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    else
                    {
                        await Conversation.ResumeAsync(resumptionCookie, message);

                        resp.Content = new StringContent($"<html><body>Almost done! Please copy this number and paste it back to your chat so your authentication can complete:<br/> <h1>{magicNumber}</h1>.</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    return(resp);
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.
                return(req.CreateErrorResponse(HttpStatusCode.BadRequest, ex));
            }
        }
示例#23
0
        public async Task <HttpResponseMessage> OAuthCallback(
            [FromUri] string code,
            [FromUri] string state,
            CancellationToken cancellationToken)
        {
            try
            {
                var    queryParams = state;
                object tokenCache  = null;
                if (string.Equals(AuthSettings.Mode, "v1", StringComparison.OrdinalIgnoreCase))
                {
                    tokenCache = new Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache();
                }
                else if (string.Equals(AuthSettings.Mode, "v2", StringComparison.OrdinalIgnoreCase))
                {
                    tokenCache = new Microsoft.Identity.Client.TokenCache();
                }
                else if (string.Equals(AuthSettings.Mode, "b2c", StringComparison.OrdinalIgnoreCase))
                {
                }

                var resumptionCookie = UrlToken.Decode <ResumptionCookie>(queryParams);
                // Create the message that is send to conversation to resume the login flow
                var message = resumptionCookie.GetMessage();

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var        client     = scope.Resolve <IConnectorClient>();
                    AuthResult authResult = null;
                    if (string.Equals(AuthSettings.Mode, "v1", StringComparison.OrdinalIgnoreCase))
                    {
                        // Exchange the Auth code with Access token
                        var token = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, (Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache) tokenCache);

                        authResult = token;
                    }
                    else if (string.Equals(AuthSettings.Mode, "v2", StringComparison.OrdinalIgnoreCase))
                    {
                        // Exchange the Auth code with Access token
                        var token = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, (Microsoft.Identity.Client.TokenCache) tokenCache, Models.AuthSettings.Scopes);

                        authResult = token;
                    }
                    else if (string.Equals(AuthSettings.Mode, "b2c", StringComparison.OrdinalIgnoreCase))
                    {
                    }

                    IStateClient sc = scope.Resolve <IStateClient>();

                    //IMPORTANT: DO NOT REMOVE THE MAGIC NUMBER CHECK THAT WE DO HERE. THIS IS AN ABSOLUTE SECURITY REQUIREMENT
                    //REMOVING THIS WILL REMOVE YOUR BOT AND YOUR USERS TO SECURITY VULNERABILITIES.
                    //MAKE SURE YOU UNDERSTAND THE ATTACK VECTORS AND WHY THIS IS IN PLACE.
                    int  magicNumber     = GenerateRandomNumber();
                    bool writeSuccessful = false;
                    uint writeAttempts   = 0;
                    while (!writeSuccessful && writeAttempts++ < MaxWriteAttempts)
                    {
                        try
                        {
                            BotData userData = sc.BotState.GetUserData(message.ChannelId, message.From.Id);
                            userData.SetProperty(ContextConstants.AuthResultKey, authResult);
                            userData.SetProperty(ContextConstants.MagicNumberKey, magicNumber);
                            userData.SetProperty(ContextConstants.MagicNumberValidated, "false");
                            sc.BotState.SetUserData(message.ChannelId, message.From.Id, userData);
                            writeSuccessful = true;
                        }
                        catch (HttpOperationException)
                        {
                            writeSuccessful = false;
                        }
                    }
                    var resp = new HttpResponseMessage(HttpStatusCode.OK);
                    if (!writeSuccessful)
                    {
                        message.Text = String.Empty; // fail the login process if we can't write UserData
                        await Conversation.ResumeAsync(resumptionCookie, message);

                        resp.Content = new StringContent("<html><body>Could not log you in at this time, please try again later</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    else
                    {
                        await Conversation.ResumeAsync(resumptionCookie, message);

                        resp.Content = new StringContent($"<html><body>Almost done! Please copy this number and paste it back to your chat so your authentication can complete:<br/> <h1>{magicNumber}</h1>.</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    return(resp);
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.
                return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex));
            }
        }
        public async Task DispatchAsync(IDialogContext context, IAwaitable <Microsoft.Bot.Connector.IMessageActivity> item)
        {
            Microsoft.Bot.Connector.Activity activity = (Microsoft.Bot.Connector.Activity) await item;
            Logger.Info($"message received from {activity.From.Name}/{activity.From.Id} : {JsonConvert.SerializeObject(activity)}");
            Logger.Info($"message received to {activity.Recipient.Name}/{activity.Recipient.Id}");

            var storage = new AgentStatusStorage(
                ConfigurationHelper.GetString("BotStatusDBConnectionString"));

            if (activity.From.Name.EndsWith("@ocsuser"))
            {
                //Messages from OCS User, when message from OCS User sent to this method, it has to be coming from DirectLine
                AgentStatus agent = null;
                //retrieve ChannelData which includes channelId for our conversation
                //TODO:figure out a way that simplier
                JObject o  = (JObject)activity.ChannelData;
                var     os = JsonConvert.SerializeObject(o);
                DirectLineChannelData channelData = JsonConvert.DeserializeObject <DirectLineChannelData>(os);

                Logger.Info($"ChannelData = {channelData}");
                //ConversationStatus conversation = null;
                Logger.Info($"RoundTrip = {channelData.RoundTrip}");
                //first message send to agent, find an available agent
                //TODO:the agent has been selected in OCS Bot, need to make it sync
                //      Instead of selecting another one here...
                agent = (await storage.FindAvailableAgentsAsync()).FirstOrDefault();
                var convRecord = (await storage.FindConversationActivityAsync(a => a.UserID == agent.Id)).FirstOrDefault();
                convRecord.RemoteConversationID = channelData.ConversationId;
                convRecord.RemoteBotId          = activity.From.Id;//remote user id actually...
                convRecord.RemoteActivity       = UrlToken.Encode <ResumptionCookie>(
                    new ResumptionCookie((Microsoft.Bot.Connector.Activity)activity));
                convRecord.RemoteUserId   = channelData.UserID;
                convRecord.RemoteUserName = channelData.UserName;
                await storage.UpdateConversationActivityAsync(convRecord);

                Logger.Info($"agent:{agent}");
                if (!agent.IsLoggedIn)
                {
                    //Agent somehow is occupied (logout?)
                    Logger.Info("Agent is occupied");
                    var             reply     = activity.CreateReply($"Agent is occupied");
                    ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
                    await connector.Conversations.ReplyToActivityAsync(reply);
                }
                else
                {
                    //Agnet is available to answer questions, send message to agent
                    Logger.Info("Sending to conversation...");

                    //TODO:Need to check if current agent is this user
                    //agent.IsOccupied = true;
                    //await storage.UpdateAgentStatusAsync(agent);

                    //First retrieve last conversaion if exists
                    //resumptionCookie = UrlToken.Decode<ResumptionCookie>(conversation.AgentResumptionCookie);
                    var localResumptionCookie = UrlToken.Decode <ResumptionCookie>(convRecord.LocalActivity);
                    Logger.Info($"AgentBot::LocalResumptionCookie:{localResumptionCookie}");
                    var localActivity  = localResumptionCookie.GetMessage();
                    var localReply     = localActivity.CreateReply($"[{activity.From.Name}]{activity.Text}");
                    var localConnector = new ConnectorClient(new Uri(localActivity.ServiceUrl),
                                                             new MicrosoftAppCredentials(
                                                                 ConfigurationHelper.GetString("MicrosoftAppId"),
                                                                 ConfigurationHelper.GetString("MicrosoftAppPassword")),
                                                             true);

                    Microsoft.Bot.Connector.Conversations localConversation = new Microsoft.Bot.Connector.Conversations(localConnector);
                    localConversation.ReplyToActivity(localReply);
                    Logger.Info("done");


                    return;
                }
            }
            else
            {
                resumptionCookie = new ResumptionCookie(await item);
                await MessageReceivedAsync(context, item);
            }
        }
示例#25
0
        public async Task <ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (!ModelState.IsValid)
            {
                return(View(model));
            }
#if true
            //Send message to Agent
            string           resumption       = Request.UrlReferrer.Query.Split('=')[1];
            ResumptionCookie resumptionCookie = null;
            //string resumption = Request.QueryString["cookie"];
            resumptionCookie = UrlToken.Decode <ResumptionCookie>(resumption);
            var appId              = Configuration.ConfigurationHelper.GetString("MicrosoftAgentBotAppId");
            var appPassword        = Configuration.ConfigurationHelper.GetString("MicrosoftAgentBotAppPassword");
            var agentBotCredentail = new MicrosoftAppCredentials(
                appId: appId,
                password: appPassword);
            Activity activity = (Activity)resumptionCookie.GetMessage();
            var      userId   = activity.From.Id;
            //Michael - demo - do not check id/password
            FormsAuthentication.SetAuthCookie(userId, true);

            StateClient sc   = activity.GetStateClient(agentBotCredentail);
            BotData     data = await sc.BotState.GetUserDataAsync(activity.ChannelId, activity.From.Id);

            data.SetProperty("Agent:Authenticated", true);
            data.SetProperty("Agent:IsAgent", true);
            await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, data);

            // Let the user know back in the conversation
            //var client = new ConnectorClient(new Uri(activity.ServiceUrl),
            //                        "34ee43c1-8b3c-467d-a719-e1c88694b390",
            //                        "2Pg2M0gfS6uhgUHRX1wZYi9");
            ////var client = new ConnectorClient(new Uri(activity.ServiceUrl));
            //Activity replyActivity = activity.CreateReply("You've been succesfully authenticated!");
            //await client.Conversations.ReplyToActivityAsync(replyActivity);
            //Activity replyActivity = activity.CreateReply("You've been succesfully authenticated!");
            OCSBot.Shared.AgentStatusStorage storage = new OCSBot.Shared.AgentStatusStorage(
                Configuration.ConfigurationHelper.GetString("BotStatusDBConnectionString"));
            await storage.UpdateConversationActivityAsync(new OCSBot.Shared.Models.ConversationRecord
            {
                UserID              = userId,
                LocalActivity       = resumption,
                LocalChannelID      = activity.ChannelId,
                LocalConversationID = activity.Conversation.Id,
                LocalBotId          = activity.Recipient.Id,
                LocalUserName       = activity.From.Name
            });

            //await storage.UpdateConversationStatusAsync(new OCSBot.Shared.Models.ConversationStatus
            //{
            //    AgentID = userId,
            //    ConversationId = activity.Conversation.Id,
            //    AgentResumptionCookie = resumption
            //});
            await storage.UpdateAgentStatusAsync(new OCSBot.Shared.Models.AgentStatus()
            {
                Id         = userId,
                IsLoggedIn = true,
                Office     = "POST",
                Name       = "Michael SH Chi",
                IsOccupied = false,
                LastConversationEndTime   = null,
                LastConversationStartTime = null,
                LoginTime          = DateTime.UtcNow,
                ConversationId     = activity.Conversation.Id,
                AgentIdInChannel   = activity.From.Id,
                AgentNameInChannel = activity.From.Name,
                ChannelId          = activity.ChannelId,
                BotIdInChannel     = activity.Recipient.Id,
                BotNameInChannel   = activity.Recipient.Name,
                ServiceURL         = activity.ServiceUrl
            });

            //Conversation.ResumeAsync(resumptionCookie, activity).Wait(5000, System.Threading.CancellationToken.None);
            //replyActivity.From = new ChannelAccount(activity.Recipient.Id,activity.Recipient.Name);
            //replyActivity.Recipient = new ChannelAccount(activity.From.Id, activity.From.Name);
            //client.Conversations.ReplyToActivityAsync(replyActivity.Conversation.Id, activity.Id, replyActivity).Wait(5000, System.Threading.CancellationToken.None);

            return(RedirectToLocal("/authenticated.html"));
#endif
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, change to shouldLockout: true
            var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout : false);

            switch (result)
            {
            case SignInStatus.Success:
                //TODO:send message to Bot
#if false
                //Send message to Agent
                string           resumption       = Request.UrlReferrer.Query.Split('=')[1];
                ResumptionCookie resumptionCookie = null;
                //string resumption = Request.QueryString["cookie"];
                resumptionCookie = UrlToken.Decode <ResumptionCookie>(resumption);

                var agentBotCredentail = new MicrosoftAppCredentials(
                    appId: "a6bae9f3-0817-443b-9247-ffdd02dabccd",
                    password: "******");
                Activity    activity = (Activity)resumptionCookie.GetMessage();
                StateClient sc       = activity.GetStateClient(agentBotCredentail);
                BotData     data     = await sc.BotState.GetUserDataAsync(activity.ChannelId, activity.From.Id);

                data.SetProperty("Authenticated", true);
                await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, data);

                // Let the user know back in the conversation
                var client = new ConnectorClient(new Uri(activity.ServiceUrl),
                                                 "a6bae9f3-0817-443b-9247-ffdd02dabccd",
                                                 "bsi2LBN820jcYRfgYxXqtnN");
                Activity replyActivity = activity.CreateReply("You've been succesfully authenticated!");
                await client.Conversations.ReplyToActivityAsync(replyActivity.Conversation.Id, activity.Id, replyActivity);
#endif
                return(RedirectToLocal(returnUrl));

            case SignInStatus.LockedOut:
                return(View("Lockout"));

            case SignInStatus.RequiresVerification:
                return(RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }));

            case SignInStatus.Failure:
            default:
                ModelState.AddModelError("", "Invalid login attempt.");
                return(View(model));
            }
        }
示例#26
0
        public void EncodeTest(string Value, string Expected)
        {
            string Actual = new UrlToken(Value).Encode();

            Assert.Equal(Expected, Actual);
        }
示例#27
0
        public async Task LogOut(IDialogContext context)
        {
            // We will store the conversation reference in the callback URL. When Office 365 logs out it will hit the LogOut endpoint and pass
            // that reference. That event signifies that log out has completed, and will prompt a message from the bot to the user to indicate that fact.
            var conversationRef = context.Activity.ToConversationReference();

            var options = GetDefaultOffice365Options();

            options.RedirectUrl = $"{ConfigurationManager.AppSettings["PostLogoutUrl"]}?conversationRef={UrlToken.Encode(conversationRef)}";

            // We need to know the resource ID. This *should be* stored in bot state from when user logged in.
            string lastSiteCollectionUrl = null;

            context.UserData.TryGetValue <string>(Constants.StateKeys.LastLoggedInSiteCollectionUrl, out lastSiteCollectionUrl);
            options.ResourceId = lastSiteCollectionUrl;


            await new ADALAuthProvider().Logout(options, context);
        }
示例#28
0
        public async Task <HttpResponseMessage> ProcessOAuthCallback(NameValueCollection parameters)
        {
            try
            {
                var queryParams = parameters["state"];

                var resumptionCookie = UrlToken.Decode <ResumptionCookie>(queryParams);
                // Create the message that is send to conversation to resume the login flow
                var message = resumptionCookie.GetMessage();

                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    var client = scope.Resolve <IConnectorClient>();
                    AuthenticationResult authResult = null;

                    // Exchange the Auth code with Access token
                    authResult = await GetTokenByAuthCodeAsync(parameters);

                    IStateClient sc = scope.Resolve <IStateClient>();

                    //IMPORTANT: DO NOT REMOVE THE MAGIC NUMBER CHECK THAT WE DO HERE. THIS IS AN ABSOLUTE SECURITY REQUIREMENT
                    //REMOVING THIS WILL REMOVE YOUR BOT AND YOUR USERS TO SECURITY VULNERABILITIES.
                    //MAKE SURE YOU UNDERSTAND THE ATTACK VECTORS AND WHY THIS IS IN PLACE.
                    int  magicNumber     = GenerateRandomNumber();
                    bool writeSuccessful = false;
                    uint writeAttempts   = 0;
                    while (!writeSuccessful && writeAttempts++ < _maxWriteAttempts)
                    {
                        try
                        {
                            BotData userData = sc.BotState.GetUserData(message.ChannelId, message.From.Id);
                            userData.SetProperty(dialogId + '_' + AuthenticationConstants.AuthResultKey, authResult);
                            userData.SetProperty(dialogId + '_' + AuthenticationConstants.MagicNumberKey, magicNumber);
                            userData.SetProperty(dialogId + '_' + AuthenticationConstants.MagicNumberValidated, "false");
                            sc.BotState.SetUserData(message.ChannelId, message.From.Id, userData);
                            writeSuccessful = true;
                        }
                        catch (HttpOperationException)
                        {
                            writeSuccessful = false;
                        }
                    }
                    var resp = new HttpResponseMessage(HttpStatusCode.OK);
                    if (!writeSuccessful)
                    {
                        message.Text = String.Empty; // fail the login process if we can't write UserData
                        await Conversation.ResumeAsync(resumptionCookie, message);

                        resp.Content = new StringContent("<html><body>Could not log you in at this time, please try again later</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    else
                    {
                        await Conversation.ResumeAsync(resumptionCookie, message);

                        resp.Content = new StringContent($"<html><body>Almost done! Please copy this number and paste it back to your chat so your authentication can complete:<br/> <h1>{magicNumber}</h1>.</body></html>", System.Text.Encoding.UTF8, @"text/html");
                    }
                    return(resp);
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.
                var resp = new HttpResponseMessage(HttpStatusCode.InternalServerError);
                return(resp);
            }
        }
示例#29
0
        public async Task <HttpResponseMessage> Callback([FromUri] string code, [FromUri] string state, CancellationToken cancellationToken)
        {
            try
            {
                // Use the state parameter to get correct IAuthProvider and ResumptionCookie
                var           decoded      = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(state));
                var           queryString  = HttpUtility.ParseQueryString(decoded);
                var           assembly     = Assembly.Load(queryString["providerassembly"]);
                var           type         = assembly.GetType(queryString["providertype"]);
                var           providername = queryString["providername"];
                IAuthProvider authProvider;
                if (type.GetConstructor(new Type[] { typeof(string) }) != null)
                {
                    authProvider = (IAuthProvider)Activator.CreateInstance(type, providername);
                }
                else
                {
                    authProvider = (IAuthProvider)Activator.CreateInstance(type);
                }

                // Get the conversation reference
                var conversationRef = UrlToken.Decode <ConversationReference>(queryString["conversationRef"]);

                Activity message = conversationRef.GetPostToBotMessage();
                using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message))
                {
                    // Get the UserData from the original conversation
                    IBotDataStore <BotData> stateStore = scope.Resolve <IBotDataStore <BotData> >();
                    var key      = Address.FromActivity(message);
                    var userData = await stateStore.LoadAsync(key, BotStoreType.BotUserData, CancellationToken.None);

                    // Get Access Token using authorization code
                    var authOptions = userData.GetProperty <AuthenticationOptions>($"{authProvider.Name}{ContextConstants.AuthOptions}");
                    var token       = await authProvider.GetTokenByAuthCodeAsync(authOptions, code);

                    // Generate magic number and attempt to write to userdata
                    int  magicNumber     = GenerateRandomNumber();
                    bool writeSuccessful = false;
                    uint writeAttempts   = 0;
                    while (!writeSuccessful && writeAttempts++ < MaxWriteAttempts)
                    {
                        try
                        {
                            userData.SetProperty($"{authProvider.Name}{ContextConstants.AuthResultKey}", token);
                            if (authOptions.UseMagicNumber)
                            {
                                userData.SetProperty($"{authProvider.Name}{ContextConstants.MagicNumberKey}", magicNumber);
                                userData.SetProperty($"{authProvider.Name}{ContextConstants.MagicNumberValidated}", "false");
                            }
                            await stateStore.SaveAsync(key, BotStoreType.BotUserData, userData, CancellationToken.None);

                            await stateStore.FlushAsync(key, CancellationToken.None);

                            writeSuccessful = true;
                        }
                        catch (Exception)
                        {
                            writeSuccessful = false;
                        }
                    }
                    var resp = new HttpResponseMessage(HttpStatusCode.OK);
                    if (!writeSuccessful)
                    {
                        message.Text = String.Empty; // fail the login process if we can't write UserData
                        await Conversation.ResumeAsync(conversationRef, message);

                        if (ConfigurationManager.AppSettings.AllKeys.Contains("BotAuth:ErrorHtml"))
                        {
                            resp.Content = new StringContent(ConfigurationManager.AppSettings["BotAuth:ErrorHtml"], System.Text.Encoding.UTF8, @"text/html");
                        }
                        else
                        {
                            resp.Content = new StringContent("<html><body>Could not log you in at this time, please try again later</body></html>", System.Text.Encoding.UTF8, @"text/html");
                        }
                    }
                    else
                    {
                        await Conversation.ResumeAsync(conversationRef, message);

                        if (ConfigurationManager.AppSettings.AllKeys.Contains("BotAuth:SucceedHtml"))
                        {
                            resp.Content = new StringContent(string.Format(ConfigurationManager.AppSettings["BotAuth:SucceedHtml"], magicNumber), System.Text.Encoding.UTF8, @"text/html");
                        }
                        else
                        {
                            resp.Content = new StringContent($"<html><body>Almost done! Please copy this number and paste it back to your chat so your authentication can complete:<br/> <h1>{magicNumber}</h1>.</body></html>", System.Text.Encoding.UTF8, @"text/html");
                        }
                    }
                    return(resp);
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.
                return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex));
            }
        }
示例#30
0
        public static string EncodeResumptionCookie(ResumptionCookie resumptionCookie)
        {
            var encodedCookie = UrlToken.Encode(resumptionCookie);

            return(encodedCookie);
        }