Skip to content
This repository has been archived by the owner on Dec 9, 2020. It is now read-only.

Port to Asp .Net Core 2? #38

Open
GeraltTheWolf opened this issue Jan 19, 2018 · 0 comments
Open

Port to Asp .Net Core 2? #38

GeraltTheWolf opened this issue Jan 19, 2018 · 0 comments

Comments

@GeraltTheWolf
Copy link

When will this be available to ASP Net Core 2.0?
To get it working on ASP .NET Core 2.0 I've made a copy of Callbak controller with a few changes.
Changes I've made are HttpResponseMessage changed to IActionResult , modified routing to Microsoft.AspNetCore.Mvc.Route.
Then I used Dependecy Injection to get MicrosoftAppCredentials and created new ConnectorClient
ConnectorClient client = new ConnectorClient(new Uri(message.ServiceUrl), credentials);
insted of using this await Conversation.ResumeAsync(conversationRef, message);, and returned
new ContentResult(); Example:

[Microsoft.AspNetCore.Mvc.Route("[controller]")]
    public class CallbackController : Controller
    {
        private static RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
        private static readonly uint MaxWriteAttempts = 5;
        private readonly MicrosoftAppCredentials credentials;

        public CallbackController(MicrosoftAppCredentials credentials)
        {
            this.credentials = credentials;
        }

        [Microsoft.AspNetCore.Mvc.HttpGet]
        public async Task<IActionResult> Callback([FromQuery] string code, [FromQuery] 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);

                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 ContentResult();
                    if (!writeSuccessful)
                    {
                        message.Text = String.Empty; // fail the login process if we can't write UserData
                     ConnectorClient client = new ConnectorClient(new Uri(message.ServiceUrl), credentials);
                        await client.Conversations.SendToConversationAsync(message);
                        resp.ContentType = @"text/html";
                        resp.Content = "<html><body>Could not log you in at this time, please try again later</body></html>";
                    }
                    else
                    {
                        message.Text = String.Empty;
                        ConnectorClient client = new ConnectorClient(new Uri(message.ServiceUrl), credentials);
                        await client.Conversations.SendToConversationAsync(message);
                        resp.ContentType = @"text/html";
                        resp.Content = $"<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>";

                    }
                    return resp;
                }
            }
            catch (Exception ex)
            {
                // Callback is called with no pending message as a result the login flow cannot be resumed.             
                return BadRequest();
            }
        }
        private int GenerateRandomNumber()
        {
            int number = 0;
            byte[] randomNumber = new byte[1];
            do
            {
                rngCsp.GetBytes(randomNumber);
                var digit = randomNumber[0] % 10;
                number = number * 10 + digit;
            } while (number.ToString().Length < 6);
            return number;
        }

    }
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant