Created
April 10, 2017 01:09
-
-
Save jakkaj/9b815903e05bb5500de01b0cde8c3678 to your computer and use it in GitHub Desktop.
Authentication Service for the Ignite Bot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading.Tasks; | |
using System.Web; | |
using EventBot.SupportLibrary.Contract; | |
using Microsoft.ApplicationInsights; | |
using Microsoft.Bot.Builder.Dialogs; | |
using Microsoft.Bot.Builder.Luis.Models; | |
using Microsoft.Bot.Connector; | |
using Xamling.Azure.Portable.Contract; | |
namespace EventBot.SupportLibrary.Services | |
{ | |
public class AuthService : IAuthService | |
{ | |
private readonly IIgniteConfigService _configService; | |
private readonly ILogService tc; | |
private ResumptionCookie _resumptionCookie; | |
private IDialogContext _context; | |
public AuthService(IIgniteConfigService configService, ILogService logService) | |
{ | |
_configService = configService; | |
tc = logService; | |
} | |
public void Init(ResumptionCookie resumptionCookie, IDialogContext context) | |
{ | |
_resumptionCookie = resumptionCookie; | |
_context = context; | |
} | |
public async Task<bool> IsAuthenticated(IDialogContext context) | |
{ | |
_context = context; | |
try | |
{ | |
// AuthResult will be set in User State if authenticated | |
var data = _context.UserData; | |
bool msAuthResult; | |
data.TryGetValue<bool>("Authenticated", out bool authResult); | |
data.TryGetValue<bool>("MicrosoftEmployee", out msAuthResult); | |
if (authResult || msAuthResult) | |
{ | |
tc.TrackTrace("Authentication status verified"); | |
} | |
else | |
{ | |
// User is unauthenticated | |
tc.TrackTrace("Authentication state not found in the user data"); | |
var message = GenerateAuthenticationResponse(); | |
await _context.PostAsync(message); | |
return false; | |
} | |
} | |
catch (Exception e) | |
{ | |
// authenticated assumed false but log the unexpected exception | |
tc.TrackException(e); | |
} | |
return true; | |
} | |
public async Task SignOut(LuisResult result) | |
{ | |
try | |
{ | |
string intent = result.Intents[0].Intent; | |
tc.TrackEvent(intent); | |
await _removeAuthToken(); | |
string responseMessage = "You're all signed out!"; | |
await _context.PostAsync(responseMessage); | |
} | |
catch (Exception e) | |
{ | |
await _handleConversationException( e); | |
} | |
} | |
async Task<bool> _removeAuthToken() | |
{ | |
bool success = false; | |
try | |
{ | |
var data = _context.UserData; | |
// Remove state | |
data.RemoveValue("Authenticated"); | |
data.RemoveValue("EmailAddress"); | |
data.RemoveValue("CID"); | |
data.RemoveValue("AttendeeRole"); | |
success = true; | |
} | |
catch (Exception e) | |
{ | |
// assumed failure but log the unexpected exception | |
tc.TrackException(e); | |
} | |
return success; | |
} | |
private async Task _handleConversationException(Exception e) | |
{ | |
tc.TrackEvent("ConversationException"); | |
tc.TrackException(e); | |
string message = $"Apologies, an error ocurred whilst processing your question. Please try again later."; | |
await _context.PostAsync(message); | |
} | |
public IMessageActivity GenerateAuthenticationResponse() | |
{ | |
tc.TrackEvent("UserNotAuthenticated"); | |
// We Url Encode as it will be placed on a URI | |
var encodedResumptionCookie = UrlToken.Encode(_resumptionCookie); | |
var authUri = GetLoginUrl(encodedResumptionCookie); | |
var originalActivity = (Activity)_resumptionCookie.GetMessage(); | |
// Let's send the URL back to the user | |
IMessageActivity replyToConversation = originalActivity.CreateReply(); | |
replyToConversation.Type = ActivityTypes.Message; | |
replyToConversation.Recipient = originalActivity.From; | |
// Not all channels are equal in terms of their capability, Skype is catching up | |
switch (originalActivity.ChannelId) | |
{ | |
// These channels support cards (new skype clients now out) | |
case "slack": | |
case "facebook": | |
case "telegram": | |
case "skype": | |
replyToConversation.Attachments = new List<Attachment>(); | |
List<CardAction> cardButtons = new List<CardAction>(); | |
CardAction plButton = new CardAction() | |
{ | |
Value = authUri, | |
Type = "signin", | |
Title = "Authenticate with Ignite" | |
}; | |
cardButtons.Add(plButton); | |
SigninCard plCard = new SigninCard("Sorry, I need you to authenticate before I can help you with that", cardButtons); | |
Attachment plAttachment = plCard.ToAttachment(); | |
replyToConversation.Attachments.Add(plAttachment); | |
break; | |
// These channel's don't support cards | |
default: | |
string textResponse = $"Sorry, I need you to authenticate before I can help you with that. Please click this link, authenticate and then ask the question again: {authUri}"; | |
replyToConversation.Text = textResponse; | |
break; | |
} | |
return replyToConversation; | |
} | |
public string GetLoginUrl(string resumptionCookie) | |
{ | |
var callback = GetCallbackUrl(resumptionCookie); | |
return callback.ToString(); | |
//var callback = GetCallbackUrl(resumptionCookie); | |
//var authUri = new Uri(_configService.AuthLogin); | |
//var builder = new UriBuilder(authUri); | |
//var query = HttpUtility.ParseQueryString(builder.Query); | |
//query["cb"] = callback.ToString(); | |
//builder.Query = query.ToString(); | |
//return builder.ToString(); | |
} | |
public Uri GetCallbackUrl(string resumptionCookie) | |
{ | |
var uri = new Uri(string.Format(_configService.AuthCallback, resumptionCookie)); | |
return uri; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment