Example #1
0
        public async Task CloudAdapterConnectorFactory()
        {
            // this is just a basic test to verify the wire-up of a ConnectorFactory in the CloudAdapter

            // Arrange

            var headerDictionaryMock = new Mock <IHeaderDictionary>();

            headerDictionaryMock.Setup(h => h[It.Is <string>(v => v == "Authorization")]).Returns <string>(null);

            var httpRequestMock = new Mock <HttpRequest>();

            httpRequestMock.Setup(r => r.Method).Returns(HttpMethods.Post);
            httpRequestMock.Setup(r => r.Body).Returns(CreateMessageActivityStream());
            httpRequestMock.Setup(r => r.Headers).Returns(headerDictionaryMock.Object);

            var httpResponseMock = new Mock <HttpResponse>();

            var claimsIdentity = new ClaimsIdentity();

            var authenticateRequestResult = new AuthenticateRequestResult
            {
                ClaimsIdentity   = claimsIdentity,
                ConnectorFactory = new TestConnectorFactory(),
                Audience         = "audience",
                CallerId         = "callerId"
            };

            var userTokenClient = new TestUserTokenClient("appId");

            var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>();

            cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult));
            cloudEnvironmentMock.Setup(ce => ce.CreateConnectorFactory(It.IsAny <ClaimsIdentity>())).Returns(new TestConnectorFactory());
            cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient));

            var bot = new ConnectorFactoryBot();

            // Act
            var adapter = new CloudAdapter(cloudEnvironmentMock.Object);
            await adapter.ProcessAsync(httpRequestMock.Object, httpResponseMock.Object, bot);

            // Assert
            Assert.Equal("audience", bot.Authorization.Parameter);
            Assert.Equal(claimsIdentity, bot.Identity);
            Assert.Equal(userTokenClient, bot.UserTokenClient);
            Assert.True(bot.ConnectorClient != null);
            Assert.True(bot.BotCallbackHandler != null);
        }
Example #2
0
        public async Task InjectCloudEnvironment()
        {
            // Arrange
            var headerDictionaryMock = new Mock <IHeaderDictionary>();

            headerDictionaryMock.Setup(h => h[It.Is <string>(v => v == "Authorization")]).Returns <string>(null);

            var httpRequestMock = new Mock <HttpRequest>();

            httpRequestMock.Setup(r => r.Method).Returns(HttpMethods.Post);
            httpRequestMock.Setup(r => r.Body).Returns(CreateMessageActivityStream());
            httpRequestMock.Setup(r => r.Headers).Returns(headerDictionaryMock.Object);

            var httpResponseMock = new Mock <HttpResponse>();

            var botMock = new Mock <IBot>();

            botMock.Setup(b => b.OnTurnAsync(It.IsAny <TurnContext>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask);

            var authenticateRequestResult = new AuthenticateRequestResult
            {
                ClaimsIdentity   = new ClaimsIdentity(),
                ConnectorFactory = new TestConnectorFactory(),
                Audience         = "audience",
                CallerId         = "callerId"
            };

            var userTokenClient = new TestUserTokenClient("appId");

            var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>();

            cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult));
            cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient));

            var httpClient = new Mock <HttpClient>();

            // Act
            var adapter = new CloudAdapter(cloudEnvironmentMock.Object);
            await adapter.ProcessAsync(httpRequestMock.Object, httpResponseMock.Object, botMock.Object);

            // Assert
            botMock.Verify(m => m.OnTurnAsync(It.Is <TurnContext>(tc => true), It.Is <CancellationToken>(ct => true)), Times.Once());
            cloudEnvironmentMock.Verify(ce => ce.AuthenticateRequestAsync(It.Is <Activity>(tc => true), It.Is <string>(tc => true), It.Is <CancellationToken>(ct => true)), Times.Once());
        }
Example #3
0
        public async Task CloudAdapterContinueConversation()
        {
            // Arrange
            var claimsIdentity = new ClaimsIdentity();

            var authenticateRequestResult = new AuthenticateRequestResult
            {
                ClaimsIdentity   = claimsIdentity,
                ConnectorFactory = new TestConnectorFactory(),
                Scope            = "scope",
                CallerId         = "callerId"
            };

            var userTokenClient = new TestUserTokenClient("appId");

            var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>();

            cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult));
            cloudEnvironmentMock.Setup(ce => ce.CreateConnectorFactory(It.IsAny <ClaimsIdentity>())).Returns(new TestConnectorFactory());
            cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient));

            var bot = new ConnectorFactoryBot();

            var expectedServiceUrl = "http://serviceUrl";

            var conversationAccount = new ConversationAccount {
                Id = "conversation Id"
            };
            var continuationActivity = new Activity {
                Type = ActivityTypes.Event, ServiceUrl = expectedServiceUrl, Conversation = conversationAccount
            };
            var conversationReference = new ConversationReference {
                ServiceUrl = expectedServiceUrl, Conversation = conversationAccount
            };

            var actualServiceUrl1 = string.Empty;
            var actualServiceUrl2 = string.Empty;
            var actualServiceUrl3 = string.Empty;
            var actualServiceUrl4 = string.Empty;
            var actualServiceUrl5 = string.Empty;
            var actualServiceUrl6 = string.Empty;

            BotCallbackHandler callback1 = (t, c) =>
            {
                actualServiceUrl1 = t.Activity.ServiceUrl;
                return(Task.CompletedTask);
            };
            BotCallbackHandler callback2 = (t, c) =>
            {
                actualServiceUrl2 = t.Activity.ServiceUrl;
                return(Task.CompletedTask);
            };
            BotCallbackHandler callback3 = (t, c) =>
            {
                actualServiceUrl3 = t.Activity.ServiceUrl;
                return(Task.CompletedTask);
            };
            BotCallbackHandler callback4 = (t, c) =>
            {
                actualServiceUrl4 = t.Activity.ServiceUrl;
                return(Task.CompletedTask);
            };
            BotCallbackHandler callback5 = (t, c) =>
            {
                actualServiceUrl5 = t.Activity.ServiceUrl;
                return(Task.CompletedTask);
            };
            BotCallbackHandler callback6 = (t, c) =>
            {
                actualServiceUrl6 = t.Activity.ServiceUrl;
                return(Task.CompletedTask);
            };

            // Act
            var adapter = new CloudAdapter(cloudEnvironmentMock.Object);
            await adapter.ContinueConversationAsync("botAppId", continuationActivity, callback1, CancellationToken.None);

            await adapter.ContinueConversationAsync(claimsIdentity, continuationActivity, callback2, CancellationToken.None);

            await adapter.ContinueConversationAsync(claimsIdentity, continuationActivity, "audience", callback3, CancellationToken.None);

            await adapter.ContinueConversationAsync("botAppId", conversationReference, callback4, CancellationToken.None);

            await adapter.ContinueConversationAsync(claimsIdentity, conversationReference, callback5, CancellationToken.None);

            await adapter.ContinueConversationAsync(claimsIdentity, conversationReference, "audience", callback6, CancellationToken.None);

            // Assert
            Assert.Equal(expectedServiceUrl, actualServiceUrl1);
            Assert.Equal(expectedServiceUrl, actualServiceUrl2);
            Assert.Equal(expectedServiceUrl, actualServiceUrl3);
            Assert.Equal(expectedServiceUrl, actualServiceUrl4);
            Assert.Equal(expectedServiceUrl, actualServiceUrl5);
            Assert.Equal(expectedServiceUrl, actualServiceUrl6);
        }
Example #4
0
        public async Task CloudAdapterProvidesUserTokenClient()
        {
            // this is just a basic test to verify the wire-up of a UserTokenClient in the CloudAdapter
            // there is also some coverage for the internal code that creates the TokenExchangeState string

            // Arrange
            string appId               = "appId";
            string userId              = "userId";
            string channelId           = "channelId";
            string conversationId      = "conversationId";
            string recipientId         = "botId";
            string relatesToActivityId = "relatesToActivityId";
            string connectionName      = "connectionName";

            var headerDictionaryMock = new Mock <IHeaderDictionary>();

            headerDictionaryMock.Setup(h => h[It.Is <string>(v => v == "Authorization")]).Returns <string>(null);

            var httpRequestMock = new Mock <HttpRequest>();

            httpRequestMock.Setup(r => r.Body).Returns(CreateMessageActivityStream(userId, channelId, conversationId, recipientId, relatesToActivityId));
            httpRequestMock.Setup(r => r.Headers).Returns(headerDictionaryMock.Object);

            var httpResponseMock = new Mock <HttpResponse>();

            var authenticateRequestResult = new AuthenticateRequestResult
            {
                ClaimsIdentity   = new ClaimsIdentity(),
                ConnectorFactory = new TestConnectorFactory(),
                Scope            = "scope",
                CallerId         = "callerId"
            };

            var userTokenClient = new TestUserTokenClient(appId);

            var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>();

            cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult));
            cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient));

            var bot = new UserTokenClientBot(connectionName);

            // Act
            var adapter = new CloudAdapter(cloudEnvironmentMock.Object);
            await adapter.ProcessAsync(httpRequestMock.Object, httpResponseMock.Object, bot);

            // Assert
            var args_ExchangeTokenAsync = userTokenClient.Record["ExchangeTokenAsync"];

            Assert.Equal(userId, (string)args_ExchangeTokenAsync[0]);
            Assert.Equal(connectionName, (string)args_ExchangeTokenAsync[1]);
            Assert.Equal(channelId, (string)args_ExchangeTokenAsync[2]);
            Assert.Equal("TokenExchangeRequest", args_ExchangeTokenAsync[3].GetType().Name);

            var args_GetAadTokensAsync = userTokenClient.Record["GetAadTokensAsync"];

            Assert.Equal(userId, (string)args_GetAadTokensAsync[0]);
            Assert.Equal(connectionName, (string)args_GetAadTokensAsync[1]);
            Assert.Equal("x", ((string[])args_GetAadTokensAsync[2])[0]);
            Assert.Equal("y", ((string[])args_GetAadTokensAsync[2])[1]);

            Assert.Equal(channelId, (string)args_GetAadTokensAsync[3]);

            var args_GetSignInResourceAsync = userTokenClient.Record["GetSignInResourceAsync"];

            // this code is testing the internal CreateTokenExchangeState function by doing the work in reverse
            var state = (string)args_GetSignInResourceAsync[0];
            var json  = Encoding.UTF8.GetString(Convert.FromBase64String(state));
            var tokenExchangeState = JsonConvert.DeserializeObject <TokenExchangeState>(json);

            Assert.Equal(connectionName, tokenExchangeState.ConnectionName);
            Assert.Equal(appId, tokenExchangeState.MsAppId);
            Assert.Equal(conversationId, tokenExchangeState.Conversation.Conversation.Id);
            Assert.Equal(recipientId, tokenExchangeState.Conversation.Bot.Id);
            Assert.Equal(relatesToActivityId, tokenExchangeState.RelatesTo.ActivityId);

            Assert.Equal("finalRedirect", (string)args_GetSignInResourceAsync[1]);

            var args_GetTokenStatusAsync = userTokenClient.Record["GetTokenStatusAsync"];

            Assert.Equal(userId, (string)args_GetTokenStatusAsync[0]);
            Assert.Equal(channelId, (string)args_GetTokenStatusAsync[1]);
            Assert.Equal("includeFilter", (string)args_GetTokenStatusAsync[2]);

            var args_GetUserTokenAsync = userTokenClient.Record["GetUserTokenAsync"];

            Assert.Equal(userId, (string)args_GetUserTokenAsync[0]);
            Assert.Equal(connectionName, (string)args_GetUserTokenAsync[1]);
            Assert.Equal(channelId, (string)args_GetUserTokenAsync[2]);
            Assert.Equal("magicCode", (string)args_GetUserTokenAsync[3]);

            var args_SignOutUserAsync = userTokenClient.Record["SignOutUserAsync"];

            Assert.Equal(userId, (string)args_SignOutUserAsync[0]);
            Assert.Equal(connectionName, (string)args_SignOutUserAsync[1]);
            Assert.Equal(channelId, (string)args_SignOutUserAsync[2]);
        }
Example #5
0
        public async Task CloudAdapterCreateConversation()
        {
            // Arrange
            var claimsIdentity = new ClaimsIdentity();

            var authenticateRequestResult = new AuthenticateRequestResult
            {
                ClaimsIdentity   = claimsIdentity,
                ConnectorFactory = new TestConnectorFactory(),
                Audience         = "audience",
                CallerId         = "callerId"
            };

            var userTokenClient = new TestUserTokenClient("appId");

            var conversationResourceResponse = new ConversationResourceResponse();
            var createResponse = new HttpOperationResponse <ConversationResourceResponse> {
                Body = conversationResourceResponse
            };

            // note Moq doesn't support extension methods used in the implementation so we are actually mocking the underlying CreateConversationWithHttpMessagesAsync method
            var conversationsMock = new Mock <IConversations>();

            conversationsMock.Setup(cm => cm.CreateConversationWithHttpMessagesAsync(It.IsAny <ConversationParameters>(), It.IsAny <Dictionary <string, List <string> > >(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(createResponse));

            var connectorMock = new Mock <IConnectorClient>();

            connectorMock.SetupGet(m => m.Conversations).Returns(conversationsMock.Object);

            var expectedServiceUrl = "http://serviceUrl";
            var expectedAudience   = "audience";

            var connectorFactoryMock = new Mock <ConnectorFactory>();

            connectorFactoryMock.Setup(cf => cf.CreateAsync(It.Is <string>(serviceUrl => serviceUrl == expectedServiceUrl), It.Is <string>(audience => audience == expectedAudience), It.IsAny <CancellationToken>())).Returns(Task.FromResult(connectorMock.Object));

            var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>();

            cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult));
            cloudEnvironmentMock.Setup(ce => ce.CreateConnectorFactory(It.IsAny <ClaimsIdentity>())).Returns(connectorFactoryMock.Object);
            cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient));

            var expectedChannelId = "expected-channel-id";
            var actualChannelId   = string.Empty;

            BotCallbackHandler callback1 = (t, c) =>
            {
                actualChannelId = t.Activity.ChannelId;

                return(Task.CompletedTask);
            };

            var conversationParameters = new ConversationParameters
            {
                IsGroup  = false,
                Bot      = new ChannelAccount {
                },
                Members  = new ChannelAccount[] { },
                TenantId = "tenantId",
            };

            // Act
            var adapter = new CloudAdapter(cloudEnvironmentMock.Object);
            await adapter.CreateConversationAsync("botAppId", expectedChannelId, expectedServiceUrl, expectedAudience, conversationParameters, callback1, CancellationToken.None);

            // Assert
            Assert.Equal(expectedChannelId, actualChannelId);
        }
Example #6
0
        public void CanContinueConversationOverWebSocket()
        {
            // Arrange
            var continueConversationWaiter = new AutoResetEvent(false);
            var verifiedValidContinuation  = false;

            var appId     = "testAppId";
            var tenantId  = "testTenantId";
            var token     = "Bearer testjwt";
            var channelId = "testChannel";
            var audience  = "testAudience";
            var callerId  = "testCallerId";

            var authResult = new AuthenticateRequestResult
            {
                Audience       = audience,
                CallerId       = callerId,
                ClaimsIdentity = new ClaimsIdentity(new List <Claim>
                {
                    new Claim("aud", audience),
                    new Claim("iss", $"https://login.microsoftonline.com/{tenantId}/"),
                    new Claim("azp", appId),
                    new Claim("tid", tenantId),
                    new Claim("ver", "2.0")
                })
            };

            var userTokenClient = new TestUserTokenClient(appId);

            var validActivity = new Activity
            {
                Id   = Guid.NewGuid().ToString("N"),
                Type = ActivityTypes.Message,
                From = new ChannelAccount {
                    Id = "testUser"
                },
                Conversation = new ConversationAccount {
                    Id = Guid.NewGuid().ToString("N")
                },
                Recipient = new ChannelAccount {
                    Id = "testBot"
                },
                ServiceUrl = "wss://InvalidServiceUrl/api/messages",
                ChannelId  = channelId,
                Text       = "hi",
            };
            var validContent = new StringContent(JsonConvert.SerializeObject(validActivity), Encoding.UTF8, "application/json");

            var invalidActivity = new Activity
            {
                Id   = Guid.NewGuid().ToString("N"),
                Type = ActivityTypes.Message,
                From = new ChannelAccount {
                    Id = "testUser"
                },
                Conversation = new ConversationAccount {
                    Id = Guid.NewGuid().ToString("N")
                },
                Recipient = new ChannelAccount {
                    Id = "testBot"
                },
                ServiceUrl = "wss://InvalidServiceUrl/api/messages",
                ChannelId  = channelId,
                Text       = "hi",
            };

            var streamingConnection = new Mock <StreamingConnection>();

            streamingConnection
            .Setup(c => c.ListenAsync(It.IsAny <RequestHandler>(), It.IsAny <CancellationToken>()))
            .Returns <RequestHandler, CancellationToken>((handler, cancellationToken) => handler.ProcessRequestAsync(
                                                             new ReceiveRequest
            {
                Verb    = "POST",
                Path    = "/api/messages",
                Streams = new List <IContentStream>
                {
                    new TestContentStream
                    {
                        Id          = Guid.NewGuid(),
                        ContentType = "application/json",
                        Length      = (int?)validContent.Headers.ContentLength,
                        Stream      = validContent.ReadAsStreamAsync().GetAwaiter().GetResult()
                    }
                }
            },
                                                             null,
                                                             cancellationToken: cancellationToken));

            var auth = new Mock <BotFrameworkAuthentication>();

            auth.Setup(a => a.AuthenticateStreamingRequestAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult(authResult));
            auth.Setup(a => a.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>()))
            .Returns(Task.FromResult <UserTokenClient>(userTokenClient));

            var webSocketManager = new Mock <WebSocketManager>();

            webSocketManager.Setup(m => m.IsWebSocketRequest).Returns(true);
            var httpContext = new Mock <HttpContext>();

            httpContext.Setup(c => c.WebSockets).Returns(webSocketManager.Object);
            var httpRequest = new Mock <HttpRequest>();

            httpRequest.Setup(r => r.Method).Returns("GET");
            httpRequest.Setup(r => r.HttpContext).Returns(httpContext.Object);
            httpRequest.Setup(r => r.Headers).Returns(new HeaderDictionary
            {
                { "Authorization", new StringValues(token) },
                { "channelid", new StringValues(channelId) }
            });

            var httpResponse = new Mock <HttpResponse>();

            var bot = new Mock <IBot>();

            bot.Setup(b => b.OnTurnAsync(It.IsAny <ITurnContext>(), It.IsAny <CancellationToken>()))
            .Returns(Task.Factory.StartNew(() => { continueConversationWaiter.WaitOne(); }));     // Simulate listening on web socket

            // Act
            var adapter        = new StreamingTestCloudAdapter(auth.Object, streamingConnection.Object);
            var processRequest = adapter.ProcessAsync(httpRequest.Object, httpResponse.Object, bot.Object, CancellationToken.None);

            var validContinuation = adapter.ContinueConversationAsync(
                authResult.ClaimsIdentity,
                validActivity,
                (turn, cancellationToken) =>
            {
                var connectorFactory = turn.TurnState.Get <ConnectorFactory>();
                Assert.NotNull(connectorFactory);
                var connectorFactoryTypeName = connectorFactory.GetType().FullName ?? string.Empty;
                Assert.EndsWith("StreamingConnectorFactory", connectorFactoryTypeName);
                verifiedValidContinuation = true;

                return(Task.CompletedTask);
            },
                CancellationToken.None);

            var invalidContinuation = adapter.ContinueConversationAsync(
                authResult.ClaimsIdentity, invalidActivity, (turn, cancellationToken) => Task.CompletedTask, CancellationToken.None);

            continueConversationWaiter.Set();
            processRequest.Wait();

            // Assert
            Assert.True(processRequest.IsCompletedSuccessfully);
            Assert.True(verifiedValidContinuation);
            Assert.True(validContinuation.IsCompletedSuccessfully);
            Assert.Null(validContinuation.Exception);
            Assert.True(invalidContinuation.IsFaulted);
            Assert.NotEmpty(invalidContinuation.Exception.InnerExceptions);
            Assert.True(invalidContinuation.Exception.InnerExceptions[0] is ApplicationException);
        }