Skip to content

Instantly share code, notes, and snippets.

@jakkaj
Created April 10, 2017 01:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakkaj/9b815903e05bb5500de01b0cde8c3678 to your computer and use it in GitHub Desktop.
Save jakkaj/9b815903e05bb5500de01b0cde8c3678 to your computer and use it in GitHub Desktop.
Authentication Service for the Ignite Bot
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