I am developing C# WinForms application to trade on Stex.com.
They upgraded their api to api3.
It uses google authentication app to login.
That's why there's no way to get access token without man's behavior.
Finally, I determined to use postman to get access token and I want to refresh token when the token is expired.
I think it the best way.
So I got the access token and refresh token via postman.
https://help.stex.com/en/articles/2740368-how-to-connect-to-the-stex-api-v3-using-postman .
now it's the turn to refresh my token.
so this is what I wrote.
string refresh_token = "def50200b03974080...";
string client_id = "502";
string client_secret = "SeTs50aFxV1RoMFBW1b4RVNQhh2wEdICaYQrpE3s";
string AccessToken = "eyJ0eXAiOiJKV1QiLCJhbGciO...";
string url = #"https://api3.stex.com/oauth/token";
var request = HttpWebRequest.Create(url);
request.Method = "POST";
request.Headers.Add("Authorization", "Bearer " + AccessToken);
request.ContentType = "application/x-www-form-urlencoded";
NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
outgoingQueryString.Add("grant_type", "refresh_token");
outgoingQueryString.Add("refresh_token", refresh_token);
outgoingQueryString.Add("client_id", client_id);
outgoingQueryString.Add("client_secret", client_secret);
outgoingQueryString.Add("scope", "trade profile reports");
outgoingQueryString.Add("redirect_uri", #"https://www.getpostman.com/oauth2/callback");
byte[] postBytes = new ASCIIEncoding().GetBytes(outgoingQueryString.ToString());
Stream postStream = request.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();
using (WebResponse response = request.GetResponse())
{
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
{
dynamic jsonResponseText = streamReader.ReadToEnd();
}
}
It shows 401(Unauthorized) error.
And when I remove ContentType, it shows 400(Bad Request) error.
If anyone did this, please help me.
guys!
Finally, I found the issue.
The issue was due to my ignorance.
Calm down and have a relax when you get issue.
:)
I created 2 api3 clients and so client_secret was different.
Thank you.
Related
I'm trying to write a script in c# capable to retrieve some information from a website. These information are protected so I need to login before I can read them. That's what I think should be my procedure:
First of all use a POST request to login into the website. Here my first problem: the page where I find the login form is this https://idp.kk-abcdefg.com/idp/Authn/UserPassword . Should I submit the POST request to this page or should I use a different address?
I've tested the headers using some tools of Firefox or Chrome but I can't understand which is the right procedure. I have noticed that If I open this login page I receive some cookies. If I delete these cookies and try to login by inserting user and password (via browser) I get an error as a response from the website .. it says that I need to activate cookies to be able to login. So it seems like when I open the login page for the first time I receive some cookies and then I need to send them together with the first POST request for login. Does it make sense for any of you?
That's the code I'm using right now:
string formUrl = "https://idp.kk-abcdefg.de/idp/Authn/UserPassword";
string formParams = string.Format("j_username=MyUserName&j_password=MyPassword”);
string cookieHeader;
string pageSource;
WebRequest req = WebRequest.Create(formUrl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
WebResponse resp = req.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
And I believe this is working because the result of pageSource changes if I use correct user / pass or I write them wrong. But when user / pass are correct, I'm still not able to login because I get the following error message: "This application requires cookies. Please make sure cookies are enabled in the settings of your browser. Please reload the login page and try logging in again".
This is the same error that I get if I disable cookies in my browser or if I delete cookies that I get when I load the login page for the first time.
Can you help me with all that? My idea is that I need to save the cookies received when I open the login page for the first time and then send them together with following requests but I don't know how to do ..
Thanks a lot!
In Web Application, once the user is logged in successfully a cookie is sent back to the browser to track the user session and to determine if the user is logged in or not during further requests. Furthermore login process of your application requires cookies to be sent from client along with username and password. So when you are trying to perform login without browser it complains about missing cookies.
If you know what cookies and their values need to be sent along with username and password for login, you can send them using cookieContainer in WebRequest as following.
string formUrl = "https://idp.kk-abcdefg.de/idp/Authn/UserPassword";
string formParams = string.Format("j_username=MyUserName&j_password=MyPassword");
string cookieHeader;
string pageSource;
CookieContainer cookieContainer = new CookieContainer();
Cookie cookie1 = new Cookie("<<cookiename>>", "<<cookievalue>>","/", "<<yourdomainname>>");
Cookie cookie2 = new Cookie("<<cookiename>>", "<<cookievalue>>", "/", "<<yourdomainname>>");
cookieContainer.Add(cookie1);
cookieContainer.Add(cookie2);
// You can keep adding all required cookies this way.
var req = (HttpWebRequest)WebRequest.Create(formUrl);
req.CookieContainer = cookieContainer;
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
WebResponse resp = req.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];
// You can access the cookies coming as part of response as following.
HttpWebResponse response = resp as HttpWebResponse;
if(response != null)
{
var cookiesCollections = response.Cookies;
}
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
If you don't know the cookies and you need to get the cookies first by requesting login page before posting username and password then use following.
var loginPageUrl = "<<Your Login Page url>>";
CookieContainer cookieContainer = new CookieContainer();
var req = (HttpWebRequest)WebRequest.Create(loginPageUrl);
req.CookieContainer = cookieContainer;
req.Method = "GET";
WebResponse resp = req.GetResponse();
HttpWebResponse response = resp as HttpWebResponse;
CookieCollection cookies;
if (response != null)
{
cookies = response.Cookies; //Use this cookies in above code to send with username and password.
}
You send the request login twice and use single CookieContainer object!
I am trying to use OAuth 2 in my Asp.net app (C#). The problem is I need to use a shared google account. To do this, my plan is to seed the authentication with a token, an expiration date, and a refresh token, and then when authentication is required I check the expiration date and use the refresh token.
The example I've been using for Authentication looks like this:
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows an application to upload files to the
// authenticated user's YouTube channel, but doesn't allow other types of access.
new[] { YouTubeService.Scope.YoutubeUpload },
"user",
CancellationToken.None
);
}
And doesn't seem to contain an object with a refresh token.
How do I get the Refresh token and expiration date?
The solution was to do a post action and parse the results manually instead of using any of the Google classes.
string gurl = "code=" + code + "&client_id=" + client_id +
"&client_secret=" + client_secret + "&redirect_uri=" + redirect_uri + "&grant_type=" + grant_type;
string url = "https://www.googleapis.com/oauth2/v3/token";
// creates the post data for the POST request
string postData = (gurl);
// create the POST request
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Host ="www.googleapis.com";
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = postData.Length;
// POST the data
using (StreamWriter requestWriter2 = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter2.Write(postData);
}
//This actually does the request and gets the response back
HttpWebResponse resp = (HttpWebResponse)webRequest.GetResponse();
string googleAuth;
using (StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()))
{
//dumps the HTML from the response into a string variable
googleAuth = responseReader.ReadToEnd();
}
From there I mainly need to parse the googleAuth string to get at the Token, the Refresh Token, and the expiration period. I kept expecting there to be a solution inside the Google classes for what must be an incredibly common request, but apparently I'll be creating my own class.
I am trying to login to Gmail by posting data.
Here is my code:
HttpWebRequest hi = (HttpWebRequest)HttpWebRequest.Create("https://www.google.com/accounts/ServiceLoginAuth?service=mail");
hi.Method = "POST";
//string PostData = "continue=https%3A%2F%2Fmail.google.com%2Fmail%2F%3Ftab%3Dwm&service=mail&rm=false&dsh=-28214021908461826<mpl=default&scc=1&GALX=6-CDla8snug&pstMsg=1&dnConn=&checkConnection=youtube%3A1271%3A1&checkedDomains=youtube&timeStmp=&secTok=&Email=EMAILADDRESS4u&Passwd=PASSWORD&signIn=Sign+in&rmShown=1";
hi.ContentType = "application/x-www-form-urlencoded";
byte[] post = UnicodeEncoding.UTF8.GetBytes(PostData);
Stream stream = await hi.GetRequestStreamAsync();
stream.Write(post, 0, PostData.Length);
WebResponse response = await hi.GetResponseAsync();
string pageSource;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
mywebview1.NavigateToString(pageSource);
But when I try to run this, I get an error. How can I resolve this issue?
Your browser's cookie functionality is turned off. Please turn it on.
We have already one question related to this...
Have a look..
Using WebRequest cookie in WebBrowser
Use cookies from CookieContainer in WebBrowser
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/00a29544-8cf4-4de2-8e7c-e7931b0e2221
I am using GitHub API v3 with C#. I am able to get the access token and using that I am able to get the user information and repo info.
But when I try to create a new repo I am getting the error as Unauthorized.
I am using HttpWebRequest to post data, which can be seen below. Please suggest me some C# sample or sample code.
(..)string[] paramName, string[] paramVal, string json, string accessToken)
{
HttpWebRequest req = WebRequest.Create(new Uri(url)) as HttpWebRequest;
req.Method = "POST";
req.ContentType = "application/json";
StreamWriter writer = new StreamWriter(req.GetRequestStream());
writer.Write(json);
writer.Close();
string result = null;
using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse)
{
StreamReader reader =
new StreamReader(resp.GetResponseStream());
result = reader.ReadToEnd();
}(..)
Note: I am not sure where i need to add the accesstoken. I have tried in headers as well as in the url, but none of them works.
Are you using the C# Github API example code? I would look at that code to see if it does what you need.
You can use basic auth pretty easily by just adding auth to the request headers:
request.Headers.Add("Authorization","Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(username +":"+password)));
Sorry havent used the access token stuff yet.
You need to add this token here:
req.UserAgent = "My App";
req.Headers.Add("Authorization", string.Format("Token {0}", "..token..");
Try
rec.Credentials = CredentialCache.DefaultCredentials;
or use non-default credentials.
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.credentials.aspx
I would like to know why my asp.net application will not add the header to my post when it is named 'Authorization' but will work fine when I change one character, say "Authorizations". In documentation for other sites they always use the name "Authorization" so I would like to as well and at this point I just want to under stand why.
I have read a few topics about this but have not found any logical reason why.
Here is my code below:
string fileName = "c:\\xyz.xml";
string uri = "http://myserver/Default.aspx";
req = WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "text/xml";
byte[] authBytes = Encoding.UTF8.GetBytes("DDSServices:jCole2011".ToCharArray());
req.Headers.Add("Authorization", "BASIC " + Convert.ToBase64String(authBytes) );
req.Headers.Add("test", "test");
UTF8Encoding encoder = new UTF8Encoding();
byte[] data = encoder.GetBytes(this.GetTextFromXMLFile(fileName));
req.ContentLength = data.Length;
Stream reqStream = req.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
req.Headers.Add("Authorization", "BASIC" + Convert.ToBase64String(authBytes));
System.Net.WebResponse response = req.GetResponse();
System.IO.StreamReader reader = new StreamReader(response.GetResponseStream());
string str = reader.ReadToEnd();
The other annoying this is when i add the watched variable through fiddler it works fine.
I was ran into a question how to add Authentication/Credentials to the headers. I found the solution in the following way.
string _auth = string.Format("{0}:{1}", "myUser","myPwd");
string _enc = Convert.ToBase64String(Encoding.ASCII.GetBytes(_auth));
string _cred = string.Format("{0} {1}", "Basic", _enc);
req.Headers[HttpRequestHeader.Authorization] = _cred;
Which gave me those headers I want (pasted Wireshark descriptions),
Authorization: Basic bXlVc2VyOm15UHdk\r\n
Credentials: myUser:myPwd
For HTTP Basic Authorization, you should be using the Credentials property.
req.Credentials = new NetworkCredential("DDSServices", "jCole2011");
This should do what you want. Rather than setting the Authorization header.
NetworkCredential is a good solution but the site you are calling has to handle an unauthorized with a 401 AND a WWW-Authenticate header in the response.
Client:
request.Credentials = new CredentialCache {{aUri, "Basic", new NetworkCredential(aUserName, aPassword)}};
Server:
Response.ClearContent();
Response.StatusCode = 401;
Response.AddHeader("WWW-Authenticate", "Basic");
Response.End();
This will result in 2 hits to the server. The initial call will go to the server without credentials. When the server responds with a 401 AND the WWW-Authenticate header (with the type of authentication required), the request will be resent with the credentials in the request.