public async Task <HttpResponseMessage> OAuthCallback([FromUri] string code, [FromUri] string session_state, string state, CancellationToken token)
        {
            var     dict           = HttpUtility.ParseQueryString(state);
            string  json           = JsonConvert.SerializeObject(dict.Cast <string>().ToDictionary(k => k, v => dict[v]));
            Address encodedAddress = JsonConvert.DeserializeObject <Address>(json);
            Address address        = new Address(
                botId: SharepointHelpers.TokenDecoder(encodedAddress.BotId),
                channelId: SharepointHelpers.TokenDecoder(encodedAddress.ChannelId),
                conversationId: SharepointHelpers.TokenDecoder(encodedAddress.ConversationId),
                serviceUrl: SharepointHelpers.TokenDecoder(encodedAddress.ServiceUrl),
                userId: SharepointHelpers.TokenDecoder(encodedAddress.UserId)
                );

            var conversationReference = address.ToConversationReference();

            // Exchange the Sharepoint Auth code with Access token
            var accessToken = await SharepointHelpers.ExchangeCodeForAccessToken(conversationReference, code, Constants.SharepointOauthCallback.ToString());

            // Create the message that is send to conversation to resume the login flow
            var msg = conversationReference.GetPostToBotMessage();

            msg.Text = $"token:{accessToken}";

            // Resume the conversation to AuthDialog

            await Conversation.ResumeAsync(conversationReference, msg);

            using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, msg))
            {
                var dataBag = scope.Resolve <IBotData>();
                await dataBag.LoadAsync(token);

                ConversationReference pending;
                if (dataBag.PrivateConversationData.TryGetValue("persistedCookie", out pending))
                {
                    // remove persisted cookie
                    dataBag.PrivateConversationData.RemoveValue("persistedCookie");
                    await dataBag.FlushAsync(token);

                    return(Request.CreateResponse("You are now logged in! Continue talking to the bot."));
                }
                else
                {
                    // Callback is called with no pending message as a result the login flow cannot be resumed.
                    return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, new InvalidOperationException("Cannot resume!")));
                }
            }
        }
        private static Microsoft.Bot.Connector.Attachment GetSigninCard(ConversationReference conversationReference)
        {
            List <CardAction> cardButtons = new List <CardAction>();
            CardAction        plButton    = new CardAction()
            {
                Value = SharepointHelpers.GetSharepointLoginURL(conversationReference, Constants.SharepointOauthCallback.ToString()),
                Type  = "openUrl",
                Title = "Authentication Required"
            };

            cardButtons.Add(plButton);

            SigninCard plCard = new SigninCard("Please login to microsoft account", new List <CardAction>()
            {
                plButton
            });

            return(plCard.ToAttachment());
        }
        private static Microsoft.Bot.Connector.Attachment GetSkypeSigninCard(ConversationReference conversationReference)
        {
            var signinCard = new SigninCard
            {
                Text    = "Please login to microsoft account",
                Buttons = new List <CardAction> {
                    new CardAction(ActionTypes.Signin, "Authentication Required", value: SharepointHelpers.GetSharepointLoginURL(conversationReference, Constants.SharepointOauthCallback.ToString()))
                }
            };

            return(signinCard.ToAttachment());
        }