How to authenticate to Office 365 portal via C# - c#

I have an Exchange tenant with Microsoft (company.onmicrosoft.com), an admin account (admin#company.onmicrosoft.com), and the admin page through which I manage my (settings).
Recently, there is a project I took on to automatically parse some web data from the admin page via C#. I've read a lot of articles all relating to SharePoint and have read up on STS, SRF files, and active/passive federation services.
So, let's get to it:
I started off with https://login.microsoftonline.com/login.srf but with Fiddler realized I could just skip straight through to https://login.microsoftonline.com/ppsecure/post.srf and achieve the same result.
So, I go to login, enter my credentials, and it then forwards me the admin page. Simple enough, right?
So, I decided to replicate the network traffic and have relied on the following posts and examples:
http://allthatjs.com/2012/03/28/remote-authentication-in-sharepoint-online/
http://garymcallisteronline.blogspot.co.uk/2012/11/claims-explained.html
http://www.wictorwilen.se/post/how-to-do-active-authentication-to-office-365-and-sharepoint-online.aspx
http://blogs.msdn.com/b/cjohnson/archive/2011/05/03/authentication-with-sharepoint-online-and-the-client-side-object-model.aspx
http://blogs.msdn.com/b/cjohnson/archive/2011/05/14/part-2-headless-authentication-with-sharepoint-online-and-the-client-side-object-model.aspx
All these websites have great C# examples on screen scraped authentication, ADFS, and a bunch of other useful information. The problem is that all of it is for SharePoint.
So, I mixed and matched code and came up with the following:
static void Main3()
{
CookieContainer cookies = new CookieContainer();
//using Bungie example from http://stackoverflow.com/questions/2508656/logging-into-a-site-that-uses-live-com-authentication
//Uri url = new Uri("https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&ct=1268167141&rver=5.5.4177.0&wp=LBI&wreply=http:%2F%2Fwww.bungie.net%2FDefault.aspx&id=42917");
Uri url = new Uri("https://portal.microsoftonline.com/");
HttpWebRequest http = (HttpWebRequest)HttpWebRequest.Create(url);
http.Timeout = 30000;
http.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0";
http.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
http.AllowAutoRedirect = false;
http.Headers.Add("Accept-Language", "en-us,en;q=0.5");
http.Headers.Add("Accept-Encoding", "gzip, deflate"); //this option creates the two cookies but loads garbage HTML. Removing this option allows the HTML to load normally
http.KeepAlive = true;
http.CookieContainer = new CookieContainer();
http.Method = WebRequestMethods.Http.Get;
HttpWebResponse response = (HttpWebResponse)http.GetResponse();
//gets the cookies (they are set in the eighth header)
string[] strCookies = response.Headers.GetValues(8);
response.Close();
Cookie manualCookie;
string sManualCookiesString = "MSPRequ|lt=1389810702&id=271346&co=1;MSPOK|$uuid-02eeaf29-b8a5-441f-a6a6-319ed926d8bc$uuid-7f106156-1398-405f-83e5-61f177c7be25$uuid-3d2f189d-8f79-4216-97cf-23c5c22ff8ad$uuid-b93c9354-5802-4c82-ac7d-7838d2f7bdbc$uuid-071c3106-1c97-4e1e-930c-36f33b6f0b93; MSPShared|1; MSPSoftVis|#:#; MSPBack|1389810501";
//Manually insert the cookies since the request only returns two cookies and we need six cookies
foreach (string sCookieAndValue in sManualCookiesString.Split(';'))
{
string sCookieName = sCookieAndValue.Split('|')[0].Trim();
string sCookieValue = sCookieAndValue.Split('|')[1].Trim();
manualCookie = new Cookie(sCookieName, "\"" + sCookieValue + "\"");
Uri manualURL = new Uri("http://login.microsoftonline.com");
http.CookieContainer.Add(manualURL, manualCookie);
}
/* //Removed because the above request only returns MSPRequ and MSPOK cookies but leaves out the others. It's obviously broken :(
string name, value;
for (int i = 0; i < strCookies.Length; i++)
{
name = strCookies[i].Substring(0, strCookies[i].IndexOf("="));
value = strCookies[i].Substring(strCookies[i].IndexOf("=") + 1, strCookies[i].IndexOf(";") - strCookies[i].IndexOf("=") - 1);
manualCookie = new Cookie(name, "\"" + value + "\"");
Uri manualURL = new Uri("http://login.microsoftonline.com");
//http.CookieContainer.Add(manualURL, manualCookie);
}
*/
//stores the cookies to be used later
cookies = http.CookieContainer;
http = (HttpWebRequest)HttpWebRequest.Create(url);
response = (HttpWebResponse)http.GetResponse();
StreamReader readStream = new StreamReader(response.GetResponseStream());
string HTML = readStream.ReadToEnd();
readStream.Close();
//Get the PPSX value: these values are a bit strange and could indicate progress since I've seen a few of the following:
// P, Pa, Pas, Pass, Passp, Passpo, Passport, PassportRN
// As you can see it adds one letter at a time which could indicate where in the login process it is, but I don't know
string PPSX = HTML.Remove(0, HTML.IndexOf("PPSX"));
PPSX = PPSX.Remove(0, PPSX.IndexOf("value") + 7);
PPSX = PPSX.Substring(0, PPSX.IndexOf("\""));
//PPSX = "PassP"; //debug
//Get this random PPFT value
string PPFT = HTML.Remove(0, HTML.IndexOf("PPFT"));
PPFT = PPFT.Remove(0, PPFT.IndexOf("value") + 7);
PPFT = PPFT.Substring(0, PPFT.IndexOf("\""));
//Get the random URL you POST to
//string POSTURL = HTML.Remove(0, HTML.IndexOf("https://login.microsoftonline.com/ppsecure/post.srf?wa=wsignin1.0&rpsnv=2&ct="));
//POSTURL = POSTURL.Substring(0, POSTURL.IndexOf("\""));
//debug:
//based on Fiddler, this page is the next page that's loaded
string POSTURL = "https://login.microsoftonline.com/GetUserRealm.srf?login=admin%company.onmicrosoft.com&handler=1&extended=1 ";
//POST with cookies
HttpWebRequest http2 = (HttpWebRequest)HttpWebRequest.Create(POSTURL);
//http.AllowAutoRedirect = false;
http2.Accept = "application/json, text/javascript, */*; q=0.01";
http2.Headers.Add("Accept-Encoding", "gzip, deflate");
http2.Headers.Add("Accept-Language", "en-us,en;q=0.5");
http2.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0";
//http.ContentLength = 0;
http2.KeepAlive = true;
http.CookieContainer = cookies;
http2.Referer = "https://login.microsoftonline.com/ppsecure/post.srf";
http2.Method = WebRequestMethods.Http.Post;
Stream ostream = http2.GetRequestStream();
//used to convert strings into bytes
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
//Post information found via Fiddler. Values have been altered for anonymity
byte[] buffer = encoding.GetBytes(
"login=" + sUsername
+ "&passwd=" + sPassword
+ "&PPSX=" + PPSX
+ "&PPFT=" + PPFT
+ "&n1=107313"
+ "&n2=-1389941230500"
+ "&n3=-1389941230500"
+ "&n4=112373"
+ "&n5=112373"
+ "&n6=112373"
+ "&n7=112373"
+ "&n8=NaN"
+ "&n9=112373"
+ "&n10=112360"
+ "&n11=112358"
+ "&n12=112323"
+ "&n13=112324"
+ "&n14=112396"
+ "&n15=26"
+ "&n16=11239"
+ "&n17=112369"
+ "&n18=112315"
+ "&n19=880.9711230112345"
+ "&n20=1"
+ "&n21=1"
+ "&n22=1381236981084.398"
+ "&n23=1"
+ "&n24=46.789501123103664"
+ "&n25=0"
+ "&n26=0"
+ "&n27=0"
+ "&n28=0"
+ "&n29=-1318912363023"
+ "&n30=-1318912363023"
+ "&n31=false"
+ "&n32=false"
+ "&type=11"
+ "&LoginOptions=3" //this is 2 sometimes
+ "&NewUser=1"
+ "&idsbho=1"
+ "&PwdPad="
+ "&sso="
+ "&vv="
+ "&uiver=1"
+ "&i12=1"
+ "&i13=Firefox"
+ "&i14=26.0"
+ "&i15=1480"
+ "&i16=964"
);
ostream.Write(buffer, 0, buffer.Length);
ostream.Close();
HttpWebResponse response2 = (HttpWebResponse)http.GetResponse();
readStream = new StreamReader(response2.GetResponseStream());
HTML = readStream.ReadToEnd();
response2.Close();
ostream.Dispose();
foreach (Cookie cookie in response2.Cookies) //this returns no cookies
{
Console.WriteLine(cookie.Name + ": ");
Console.WriteLine(cookie.Value);
Console.WriteLine(cookie.Expires);
Console.WriteLine();
}
POSTURL = "https://login.microsoftonline.com/ppsecure/post.srf?bk=1389198967";
//POST with cookies
http = (HttpWebRequest)HttpWebRequest.Create(POSTURL);
http.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0";
http.AllowAutoRedirect = false;
http.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
http.Headers.Add("Accept-Language", "en-us,en;q=0.5");
http.KeepAlive = true;
http.CookieContainer = cookies;
http.Referer = "https://login.microsoftonline.com/ppsecure/post.srf";
http.Method = WebRequestMethods.Http.Post;
ostream = http.GetRequestStream();
//used to convert strings into bytes
encoding = new System.Text.ASCIIEncoding();
//Post information
ostream.Write(buffer, 0, buffer.Length);
ostream.Close();
HttpWebResponse response3 = (HttpWebResponse)http.GetResponse();
readStream = new StreamReader(response3.GetResponseStream());
HTML = readStream.ReadToEnd();
response3.Close();
ostream.Dispose();
foreach (Cookie cookie in response3.Cookies) //sadly this returns no cookies when it should have 18 cookies in addition to a bunch of BOX.CacheKey cookies
{
Console.WriteLine(cookie.Name + ": ");
Console.WriteLine(cookie.Value);
Console.WriteLine(cookie.Expires);
Console.WriteLine();
}
}
Does anyone know enough about how the website works to provide some guidance on where I'm failing? The website also uses JavaScript to create cookies (you can visit the first page and enter a random address and you'll see some dots move from left to right in the username field.
Maybe I'm taking the wrong approach but any assistance would be appreciated. I can provide the Fiddler summary session log if need be.
Thank you!
P.S. Sorry about all .com replacements for the actual period character but I don't have enough reputation points. Just search for [dot]com and replace with .com to undo.

Put a WebBrowser control on a form and control it using its methods and events - it will handle all the redirects/cookies/etc for you.
You can hide it if you need to so the user won't even know you're using a web browser...

You want to login into Office 365 portal, not SharePoint admin portal, so the articles about how to login into SharePoint won't help for your case.
I did a search, I think to login into Office 365 portal, you need Microsoft Online Services Sign-In Assistant first.
Microsoft provides some examples on how to manage office365 user:
Office 365: Office 365 Dashboard
Office 365: Manage licenses and subscriptions for Office 365
Both examples are based on Microsoft Online Services Sign-In Assistant and powershell cmdlet , so in C#, we can use the functions in this component to login. But it seems there's not much document about this component. So if you can use Powershell, you can follow the examples to do it. If you can't, you may need dig into the login command and see how to implement it in C#.

You will need the Modules for Office 365 installed in the machine for communication.
Powershell Commands
$UserCredential = Get-Credential
Import-PSSession $Session
Import-Module ActiveDirectory
Import-Module MsOnline
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
Import-Module ActiveDirectory
Import-Module MsOnline
Get-Module
Then you can do any thing
Create user & mailboxes, Email alias etc.
You may have to reference power shell in the C# code to make it work work from a custom website or windows app
This will connect to Office 365:
http://technet.microsoft.com/en-us/library/jj984289(v=exchg.150).aspx

Related

Downloading files from Web using basic URL Authorization

I can successfully download a file using the following link in a browser:
https://userbob:qwerty#assoc-datafeeds-na.amazon.com/datafeed/getReport?filename=feedreport-1265.xml.gz
Now I need to to do this in my C# application.
Solution 1: using WebClient
string url = $"https://assoc-datafeeds-na.amazon.com/datafeed/getReport?filename=feedreport-1265.xml.gz";
using (var webClient = new WebClient())
{
string authInfo =Convert.ToBase64String(Encoding.Default.GetBytes("userbob:qwerty"));
webClient.Headers[HttpRequestHeader.Authorization] = "Basic " + authInfo;
webClient.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
webClient.Headers[HttpRequestHeader.UserAgent] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
var data = webClient.DownloadData(url);
}
DownloadData throws an exception: The remote server returned an error: (500) Internal Server Error.
Solution 2: using WebRequest
var request = WebRequest.Create(url);
string authInfo =Convert.ToBase64String(Encoding.Default.GetBytes("userbob:qwerty"));
((HttpWebRequest)request).CookieContainer = new CookieContainer();
request.Headers["Authorization"] = "Basic " + authInfo;
((HttpWebRequest)request).UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
((HttpWebRequest)request).ContentType = "application/octet-stream";
var response = request.GetResponse();
The same exception on the last line. I feel I am missing some header or setting to fully mimic browser behavior.
Interestingly, if I omit Authorization header in either of the solutions, I get 401:Unauthorized exceptions. That makes me think that I pass authorization and the problem is in something else. What am I missing ?
You have to pass token by converting to Base64:
var username = "xxxxxxx";
var password = "yyyyyyy";
var token = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(username + ":" + password));
request.Headers.Add("Authorization", "Basic " + token);

Bing Search API Azure Marketplace Authentication in c#

How can one authenticate to the bing search api without using the BingSearchContainer.
With bing search container we can do something like this:
var bing = new BingSearchContainer(new Uri("https://api.datamarket.azure.com/Bing/Search/")) { Credentials = new NetworkCredential(bingKey, bingKey) };
But this doesn't help me because i need to pass some other proxy to access the internet.
Can anyone help me with this?
One way is to create a WebRequest with basic authorization.
Like this:
//some demo uri
Uri uri = new Uri("https://api.datamarket.azure.com/Bing/Search/Composite?Sources=%27web%27&Query=%27xbox%27&$format=json");
System.Net.WebRequest req = System.Net.WebRequest.Create(uri);
byte[] byteKey = System.Text.ASCIIEncoding.ASCII.GetBytes(bingKey + ":" + bingKey);
string stringKey = System.Convert.ToBase64String(byteKey);
req.Headers.Add("Authorization", "Basic " + stringKey);
req.Proxy = new System.Net.WebProxy("proxy_url", true);
req.Proxy.Credentials = new NetworkCredential("", "", "");
System.Net.WebResponse resp = req.GetResponse();

TeamCity - Unable to authenticate via API

I've been struggling with authentication in TeamCity through the API lately. I can access the resources directly in my browser (http://usr:pw#teamcity:8111/httpAuth/app/rest/...), but doing so programmatically returns 401-Unauthorized.
WebRequest request = WebRequest.Create("http://user:pwd#teamcity:8111/httpAuth/app/rest/projects");
request.Method = WebRequestMethods.Http.Get;
try
{
request.Timeout = Timeout.Infinite;
WebResponse response = request.GetResponse(); //Returns 401:Unauthorized
I can use guestAuth(http://teamcity:8111/guestAuth/app/rest/projects) without any problem, so there should not be any problem with the WebRequest itself.
Does anyone have an idea?
Try to add your credentials and then make request.it will be get what you need.
var username = "abc";
var password = "123";
var encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
request.Headers.Add("Authorization", "Basic " + encoded);

HttpWebResponse don't allow popUp

I making HttpWebRequest/HttpWebResponse and when i get response i get error ->
An Add-on for this Website failed to run. Click Security Setting in the Internet Options for Potential conflicts.
I can't just press allow popUps from website i need to program this, enable popUp or add registry keys to this website.
Here my code
string postData += "userid=" + strUser + "&";
postData += "numID=" + strUserId + "&";
postData += "userPassword=" + strPass + "&";
HttpWebRequest postRequest = (HttpWebRequest)WebRequest.Create(loginPostUrl);
postRequest.CookieContainer = new CookieContainer();
postRequest.CookieContainer = _cookies;
postRequest.Method = WebRequestMethods.Http.Post;
postRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0";
postRequest.AllowWriteStreamBuffering = true;
postRequest.ProtocolVersion = HttpVersion.Version11;
postRequest.AllowAutoRedirect = true;
postRequest.ContentType = "application/x-www-form-urlencoded";
byte[] byteArray = Encoding.ASCII.GetBytes(postData);
postRequest.ContentLength = byteArray.Length;
Stream newStream = postRequest.GetRequestStream(); //open connection
newStream.Write(byteArray, 0, byteArray.Length); // Send the data.
newStream.Close();
HttpWebResponse postResponseAfterLogin = (HttpWebResponse)postRequest.GetResponse();
//After inserting User and Password
Stream streamResponseLoginForm = postResponseAfterLogin.GetResponseStream();
StreamReader streamReadLoginForm = new StreamReader(streamResponseLoginForm);
outString = streamReadLoginForm.ReadToEnd();//This is afer login btn pressed here we
I tried to login with WatIn
using (var browser = new IE("www.blabla.com"))
{
browser.TextField(Find.ById("userID")).Value = strUser;
browser.TextField(Find.ById("numID")).Value = strUserId;
browser.TextField(Find.ById("userPassword")).Value = strPass;
browser.Image(Find.ById("inputSend")).Click();
Thread.Sleep(WaitTime+2000);
}
This not work to.I see this popUp the IE does't allow popUp from website www.blabla.com"
How to allow popup from website or and my website www.blabla.com" to list of websites that allow popup ?
You have to go to internet options -> Privacy -> and uncheck Turn On POPUP and save.
As your Activex controls are get installed You have to allow them by this methopd only.

Automate downloads from password protected website [duplicate]

This question already has answers here:
Login to the page with HttpWebRequest
(2 answers)
Closed 6 years ago.
I need some help with a work project I have been assigned. At the moment we manually go to the site, logon and then download 2 excel files from a supplier's website every month. The files are then loaded into SQL.
We want to automate this process. Now the loading of the files into SQL I can do, but I am not sure how I can automate logging onto the website entering my user details and collecting the files. I mostly deal with SQL and have very little .NET experience, so any code samples would be most appreciated.
Just to confirm. The logon form is on a aspx page. just a basic form with a table containing the username & password fields, the forgotten password link and the logon button
You can either use webclient or httpwebrequest.
Login to the page with HttpWebRequest
How do you login to a webpage and retrieve its content in C#?
Httpwebrequest example:
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://sso.bhmobile.ba/sso/login");
req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705;)";
req.Method = "POST";
req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
req.Headers.Add("Accept-Language: en-us,en;q=0.5");
req.Headers.Add("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
req.KeepAlive = true;
req.Headers.Add("Keep-Alive: 300");
req.Referer ="http://sso.bhmobile.ba/sso/login";
req.ContentType = "application/x-www-form-urlencoded";
String Username = "username";
String PassWord = "Password";
StreamWriter sw = new StreamWriter(req.GetRequestStream());
sw.Write("application=portal&url=http%3A%2F%2Fwww.bhmobile.ba%2Fportal%2Fredirect%3Bjsessionid%3D1C568AAA1FB8B5C757CF5F68BE6ECE65%3Ftype%3Dssologin%26url%3D%2Fportal%2Fshow%3Bjsessionid%3D1C568AAA1FB8B5C757CF5F68BE6ECE65%3Fidc%3D1023278&realm=sso&userid=" + Username + "&password=" + password + "&x=16&y=11");
sw.Close();
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string tmp = reader.ReadToEnd();
foreach (Cookie cook in response.Cookies)
{
tmp += "\n" + cook.Name + ": " + cook.Value;
}
Response.Write(tmp);
Response.End();
Webclient example:
WebClient wc = new WebClient();
wc.Credentials = new NetworkCredential("username", "password");
string url = "http://foo.com";
try
{
using (Stream stream = wc.OpenRead(new Uri(url)))
{
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
catch (WebException e)
{
//Error handeling
}

Categories