Skip to content

Instantly share code, notes, and snippets.

@jakkaj
Created April 10, 2017 01:16
Show Gist options
  • Save jakkaj/b133f0aa69d2e296d381fb955ec2bb67 to your computer and use it in GitHub Desktop.
Save jakkaj/b133f0aa69d2e296d381fb955ec2bb67 to your computer and use it in GitHub Desktop.
Login Handler for Ignite Australia bot
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Arlo.SDK.Contract;
using EventBot.SupportLibrary.Contract;
using EventBot.SupportLibrary.Entity;
using EventBot.SupportLibrary.Utils.JwtHelpers;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using Xamling.Azure.Portable.Contract;
using XamlingCore.Portable.Contract.Config;
using XamlingCore.Portable.Model.Other;
using XamlingCore.Portable.View.Special;
namespace EventBot.SupportLibrary.Services
{
/// <summary>
/// Handles the login returned from the external login provider
/// </summary>
public class LoginHandlerService : ILoginHandlerService
{
private readonly ILogService _logService;
private readonly IContactService _contactService;
private readonly IEventService _eventService;
private readonly IConfig _config;
private Activity _activity;
public LoginHandlerService(ILogService logService,
IContactService contactService, IEventService eventService, IConfig config)
{
_logService = logService;
_contactService = contactService;
_eventService = eventService;
_config = config;
}
public async Task Bounce(string queryString)
{
var httpClient = new HttpClient();
var message = new HttpRequestMessage(HttpMethod.Post, queryString);
message.Content = new StringContent("SomeToken");
await httpClient.SendAsync(message);
}
public async Task<bool> HandleLoginReturned([NotNull]string resumptionCookieString, [NotNull]string token)
{
var resumptionCookie = UrlToken.Decode<ResumptionCookie>(resumptionCookieString);
_activity = (Activity)resumptionCookie.GetMessage();
_logService.TrackTrace("LoginToken", XSeverityLevel.Information,
new Dictionary<string, string> {{"Token", token}});
var claims = _validateToken(token);
if (claims == null)
{
await _returnClaimsFail();
return false;
}
if (!claims.ContainsKey(WebConstants.Claims.ContactId))
{
await _returnClaimsFail();
}
var contactId = claims[WebConstants.Claims.ContactId];
var currentEvent = await _eventService.GetCurrentEvent();
var contact = await _contactService.MapContactIdToRegistration(currentEvent, contactId);
if (contact == null)
{
await _returnNoContact();
return false;
}
var sc = _activity.GetStateClient();
var data = await sc.BotState.GetUserDataAsync(_activity.ChannelId, _activity.From.Id);
data.SetProperty("Authenticated", true);
data.SetProperty("EmailAddress", contact.Contact.Email);
data.SetProperty("CID", contact.RegistrationID);
data.SetProperty("UserId", contact.Contact.ContactID);
data.SetProperty("AttendeeRole", "Idunno");
data.SetProperty("AttendeeID", contact.RegistrationID);
data.SetProperty("FirstName", contact.Contact.FirstName ?? "");
data.SetProperty("LastName", contact.Contact.LastName ?? "");
_logService.TrackTrace("AuthController - cid: " + contact.RegistrationID);
await sc.BotState.SetUserDataAsync(_activity.ChannelId, _activity.From.Id, data);
_logService.TrackTrace($"Successfully authenticated. Email: {contact.Contact.Email}, CID: {contact.RegistrationID}, Role: {data.GetProperty<string>("AttendeeRole")}");
await _reply($"Hi {contact.Contact.FirstName}, welcome to Ignite!");
return true;
}
async Task _returnNoContact()
{
_logService.TrackEvent("AuthenticationFailed");
_logService.TrackTrace($"AuthenticationController::No arlo contact found");
await _reply("We had some trouble finding you in the system! That doesn't sound terribly optimal. ");
}
async Task _returnClaimsFail()
{
_logService.TrackEvent("AuthenticationFailed");
_logService.TrackTrace($"AuthenticationController::Post: Couldn't find the required claims");
await _reply("A claims error ocurred during authentication, please try again later.");
}
async Task _reply(string reply)
{
var client = new ConnectorClient(new Uri(_activity.ServiceUrl));
Activity replyActivity = _activity.CreateReply(reply);
await client.Conversations.ReplyToActivityAsync(replyActivity);
}
Dictionary<string, string> _validateToken(string token)
{
//var dict = new Dictionary<string, string>();
//dict.Add(WebConstants.Claims.ContactId, "3813");
//return dict;
var key = _config[WebConstants.Config.JwtPublicKey];
var audience = _config[WebConstants.Config.JwtAudience];
var issuer = _config[WebConstants.Config.JwtIssuer];
var result = JwtValidator.ValidateWithRsaKey(token, key, issuer, audience);
if (!result.IsValid)
{
_logService.TrackTrace("JWT Validation Failed", XSeverityLevel.Critical, new Dictionary<string, string>
{
{"Token", token},
{"Fail Reason", result.FailReason}
});
return null;
}
_logService.TrackTrace("JWT Validated", XSeverityLevel.Information, new Dictionary<string, string>
{
{"Token", token}
});
return result.Claims;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment