public static async Task <object> HandleOAuthCallback(HttpRequestMessage req, uint maxWriteAttempts) { try { var queryParams = req.RequestUri.ParseQueryString(); if (req.Method != HttpMethod.Post) { throw new ArgumentException("The OAuth postback handler only supports POST requests."); } var formData = await req.Content.ReadAsFormDataAsync(); string stateStr = formData["state"]; string code = formData["code"]; var resumptionCookie = UrlToken.Decode <ResumptionCookie>(stateStr); var message = resumptionCookie.GetMessage(); using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, message)) { AuthenticationSettings authSettings = AuthenticationSettings.GetFromAppSettings(); var client = scope.Resolve <IConnectorClient>(); AuthenticationResult authenticationResult = await AzureActiveDirectoryHelper.GetTokenByAuthCodeAsync(code, authSettings); IStateClient sc = scope.Resolve <IStateClient>(); //IMPORTANT: DO NOT REMOVE THE MAGIC NUMBER CHECK THAT WE DO HERE. THIS IS AN ABSOLUTE SECURITY REQUIREMENT //REMOVING THIS WILL REMOVE YOUR BOT AND YOUR USERS TO SECURITY VULNERABILITIES. //MAKE SURE YOU UNDERSTAND THE ATTACK VECTORS AND WHY THIS IS IN PLACE. int magicNumber = GenerateRandomNumber(); bool writeSuccessful = false; uint writeAttempts = 0; while (!writeSuccessful && writeAttempts++ < maxWriteAttempts) { try { BotData userData = sc.BotState.GetUserData(message.ChannelId, message.From.Id); userData.SetProperty(AuthenticationConstants.AuthResultKey, authenticationResult); userData.SetProperty(AuthenticationConstants.MagicNumberKey, magicNumber); userData.SetProperty(AuthenticationConstants.MagicNumberValidated, "false"); sc.BotState.SetUserData(message.ChannelId, message.From.Id, userData); writeSuccessful = true; } catch (HttpOperationException) { writeSuccessful = false; } } var resp = new HttpResponseMessage(HttpStatusCode.OK); if (!writeSuccessful) { message.Text = String.Empty; // fail the login process if we can't write UserData await Conversation.ResumeAsync(resumptionCookie, message); resp.Content = new StringContent("<html><body>Could not log you in at this time, please try again later</body></html>", System.Text.Encoding.UTF8, @"text/html"); } else { await Conversation.ResumeAsync(resumptionCookie, message); resp.Content = new StringContent($"<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>", System.Text.Encoding.UTF8, @"text/html"); } return(resp); } } catch (Exception ex) { // Callback is called with no pending message as a result the login flow cannot be resumed. return(req.CreateErrorResponse(HttpStatusCode.BadRequest, ex)); } }
public static async Task <AuthenticationResult> GetTokenByAuthCodeAsync(string authorizationCode, AuthenticationSettings authenticationSettings) { var tokenCache = TokenCacheFactory.GetADALTokenCache(); Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext context = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authenticationSettings.EndpointUrl + "/" + authenticationSettings.Tenant, tokenCache); Uri redirectUri = new Uri(authenticationSettings.RedirectUrl); var result = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, redirectUri, new Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential(authenticationSettings.ClientId, authenticationSettings.ClientSecret)); AuthenticationResult authResult = ConvertAuthenticationResult(result, tokenCache); return(authResult); }
//public static async Task<AuthenticationResult> GetTokenByAuthCodeAsync(string authorizationCode, AuthenticationSettings authenticationSettings, string[] scopes) //{ // var tokenCache = TokenCacheFactory.GetMSALTokenCache(); // Microsoft.Identity.Client.ConfidentialClientApplication client = new Microsoft.Identity.Client.ConfidentialClientApplication(authenticationSettings.ClientId, authenticationSettings.RedirectUrl, new Microsoft.Identity.Client.ClientCredential(authenticationSettings.ClientSecret), tokenCache); // Uri redirectUri = new Uri(authenticationSettings.RedirectUrl); // var result = await client.AcquireTokenByAuthorizationCodeAsync(scopes, authorizationCode); // AuthenticationResult authResult = ConvertAuthenticationResult(result, tokenCache); // return authResult; //} public static async Task <AuthenticationResult> GetToken(string userUniqueId, AuthenticationSettings authenticationSettings, string resourceId) { var tokenCache = TokenCacheFactory.GetADALTokenCache(); Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext context = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authenticationSettings.EndpointUrl + "/" + authenticationSettings.Tenant, tokenCache); var result = await context.AcquireTokenSilentAsync(resourceId, new Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential(authenticationSettings.ClientId, authenticationSettings.ClientSecret), new Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier(userUniqueId, Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifierType.UniqueId)); AuthenticationResult authResult = ConvertAuthenticationResult(result, tokenCache); return(authResult); }
//private static async Task<string> GetAuthUrlAsync(ResumptionCookie resumptionCookie, AuthenticationSettings authenticationSettings, string[] scopes) //{ // Uri redirectUri = new Uri(authenticationSettings.RedirectUrl); // if (authenticationSettings.Mode == AuthenticationMode.V2) // { // MSALTokenCache tokenCache = new MSALTokenCache(); // Microsoft.Identity.Client.ConfidentialClientApplication client = new Microsoft.Identity.Client.ConfidentialClientApplication(authenticationSettings.ClientId, redirectUri.ToString(), // new Microsoft.Identity.Client.ClientCredential(authenticationSettings.ClientSecret), // tokenCache); // //var uri = "https://login.microsoftonline.com/" + AuthSettings.Tenant + "/oauth2/v2.0/authorize?response_type=code" + // // "&client_id=" + AuthSettings.ClientId + // // "&client_secret=" + AuthSettings.ClientSecret + // // "&redirect_uri=" + HttpUtility.UrlEncode(AuthSettings.RedirectUrl) + // // "&scope=" + HttpUtility.UrlEncode("openid profile " + string.Join(" ", scopes)) + // // "&state=" + encodedCookie; // var stateString = EncodeResumptionCookie(resumptionCookie); // var uri = await client.GetAuthorizationRequestUrlAsync( // scopes, // null, // $"state={stateString}"); // return uri.ToString(); // } // else if (authenticationSettings.Mode == AuthenticationMode.B2C) // { // return null; // } // return null; //} public static async Task <AuthenticationResult> GetTokenByAuthCodeAsync(string authorizationCode) { AuthenticationSettings authenticationSettings = AuthenticationSettings.GetFromAppSettings(); return(await GetTokenByAuthCodeAsync(authorizationCode, authenticationSettings)); }