Skip to content

Instantly share code, notes, and snippets.

@benbenbenbenbenben
Last active August 6, 2022 20:22
Show Gist options
  • Save benbenbenbenbenben/8310a6f31fc660a6a4b7f0357f28922f to your computer and use it in GitHub Desktop.
Save benbenbenbenbenben/8310a6f31fc660a6a4b7f0357f28922f to your computer and use it in GitHub Desktop.
how to login to microsoftonline.com/your.tenancy.xyz using WebRequest
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
namespace Dynamics365
{
public class MicrosoftOnlineLogin
{
public static CookieContainer Login(string username, string password, string application)
{
var wtrealm = HttpUtility.UrlEncode("spn:00000015-0000-0000-c000-000000000000");
var wreply = HttpUtility.UrlEncode(application);
var tenant = username.Split('@').Last().ToLower();
var interactiveUrl = $"https://login.microsoftonline.com/{tenant}/wsfed?wa=wsignin1.0&wtrealm={wtrealm}&wreply={wreply}";
var loginUrl = $"https://login.microsoftonline.com/{tenant}/login";
var cookies = new CookieContainer();
// 1. GET ms login page
HttpWebRequest getLoginClient = (HttpWebRequest)WebRequest.Create(interactiveUrl);
getLoginClient.CookieContainer = cookies;
var getLoginResponse = getLoginClient.GetResponse();
var getLoginResponseStream = new StreamReader(getLoginResponse.GetResponseStream());
var getLoginResponseBody = getLoginResponseStream.ReadToEnd();
// 2. POST to ms/tenant/login
HttpWebRequest postLoginClient = (HttpWebRequest)WebRequest.Create(loginUrl);
postLoginClient.CookieContainer = cookies;
postLoginClient.Headers.Clear();
postLoginClient.Headers.Add("accept-Encoding: gzip, deflate, br");
postLoginClient.Headers.Add("Accept-Language: en-US,en;q=0.8;en-GB;q=0.6");
// 2.b. copy cookie in to POST
// postLoginClient.Headers.Add("Cookie", getLoginResponse.Headers["Set-Cookie"]);
// 2.c. prepare body
var postLoginBody = (new Dictionary<string, string>()
{
["login"] = username,
["passwd"] = password,
["ctx"] = Regex.Match(getLoginResponseBody, "hidden.*ctx.*value=\"(.*)\"").Groups[1].Value,
["flowToken"] = Regex.Match(getLoginResponseBody, "hidden.*flowToken.*value=\"(.*)\"").Groups[1].Value,
["canary"] = Regex.Match(getLoginResponseBody, "hidden.*canary.*value=\"(.*)\"").Groups[1].Value,
["type"] = "11",
["LoginOptions"] = "3",
["NewUser"] = "1",
["idsbho"] = "1",
["PwdPad"] = "",
["sso"] = "",
["vv"] = "",
["uiver"] = "1"
}).Aggregate(HttpUtility.ParseQueryString(""), (seed, current) =>
{
seed.Add(current.Key, current.Value);
return seed;
}).ToString();
postLoginClient.Method = "POST";
postLoginClient.ContentType = "application/x-www-form-urlencoded";
postLoginClient.ContentLength = postLoginBody.Length;
// 2.d. dispatch request and read response
var postLoginRequestStream = postLoginClient.GetRequestStream();
using (var sw = new StreamWriter(postLoginRequestStream))
{
sw.Write(postLoginBody);
sw.Flush();
sw.Close();
}
var postLoginResponse = postLoginClient.GetResponse();
var postLoginResponseBody = string.Empty;
using (var decomp = new GZipStream(postLoginResponse.GetResponseStream(), CompressionMode.Decompress))
{
byte[] buffer = new byte[1024];
using (var ms = new MemoryStream())
{
int nRead;
while ((nRead = decomp.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, nRead);
}
ms.Position = 0;
var tr = new StreamReader(ms);
postLoginResponseBody = tr.ReadToEnd();
}
}
// 3. POST to app instance
HttpWebRequest axPostClient = (HttpWebRequest)WebRequest.Create(application);
axPostClient.CookieContainer = cookies;
axPostClient.Headers.Add("Cache-Control: max-age=0");
axPostClient.Headers.Add("Origin: https://login.microsoftonline.com");
axPostClient.Headers.Add("Upgrade-Insecure-Requests: 1");
//axPostClient.Headers.Add("User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2767.0 Safari/537.36");
axPostClient.ContentType = "application/x-www-form-urlencoded";
axPostClient.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
axPostClient.Referer = loginUrl;
axPostClient.Headers.Add("Accept-Encoding: gzip, deflate, br");
axPostClient.Headers.Add("Accept-Language: en-GB,en-US;q=0.8,en;q=0.6");
var axPostBody = (new Dictionary<string, string>()
{
["wa"] = "wsignin1.0",
["wresult"] =
HttpUtility.HtmlDecode(Regex.Match(postLoginResponseBody, "name=\"wresult\" value=\"([^\"]*)\"").Groups[1].Value),
["wctx"] = "rm=0&id=passive&ru=/"
}).Aggregate(HttpUtility.ParseQueryString(""), (seed, current) =>
{
seed.Add(current.Key, current.Value);
return seed;
}).ToString();
axPostClient.Method = "POST";
axPostClient.ContentLength = axPostBody.Length;
var axPostRequestStream = axPostClient.GetRequestStream();
using (var sw = new StreamWriter(axPostRequestStream))
{
sw.Write(axPostBody);
sw.Flush();
sw.Close();
}
var axPostResponse = axPostClient.GetResponse();
var axPostResponseBody = string.Empty;
using (var decomp = new GZipStream(axPostResponse.GetResponseStream(), CompressionMode.Decompress))
{
byte[] buffer = new byte[1024];
using (var ms = new MemoryStream())
{
int nRead;
while ((nRead = decomp.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, nRead);
}
ms.Position = 0;
var tr = new StreamReader(ms);
axPostResponseBody = tr.ReadToEnd();
}
}
return cookies;
}
}
}
@benbenbenbenbenben
Copy link
Author

If you are trying to integrate build tools with Dynamics AX7 / Dynamics 365 and you can't get hold of your Office 365 administrator then you might need something like this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment