AuthBot
AuthBot copied to clipboard
Port To Asp .Net Core 2.0?
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;
}
}
Probably never. You know Microsoft break it and forget about it