I'm having some problems where I'm trying to send Authorization header to my server in Unity. I've already done this in my Windows Phone project that I'm porting to Unity but when I send the request to my server it returns 500 Internal Server Error.
Here is my code where I do the call:
string hash = Helper.GetHashString();
byte[] toEncodeAsBytes = System.Text.Encoding.UTF8.GetBytes(username + ":" + password);
string base64 = System.Convert.ToBase64String(toEncodeAsBytes);
Hashtable headers = new Hashtable();
headers["Authorization"] = "Basic " + base64;
StartCoroutine(Server.Authorize(Config.SERVER_URL + "/Auth/" + hash, LoginEventResponse, headers));
The Server.Authorize:
public static IEnumerator Authorize(string path, DelegateEventFunction myEvent, Hashtable headers)
{
WWW www = new WWW(SERVER_URL + path, null, headers);
yield return www;
When the www returns I get the error (500) as mentioned above. The code that I'm porting from, and is working is:
string hash = Helper.GetHashString();
byte[] toEncodeAsBytes = System.Text.Encoding.UTF8.GetBytes(Model.Username + ":" + Model.Password);
string base64 = Convert.ToBase64String(toEncodeAsBytes);
HttpClient loginClient = new HttpClient();
loginClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64);
string loginResponse = await loginClient.GetStringAsync(Config.SERVER_URL + "/Auth/" + hash);
Very much the same besides the Unitys use of WWW instead of HttpClient. Maybe this is solvable by buying PRO version letting me tap into native libraries, but every webcall works besides this one there I try to send in Authorization header.
Anyone got a tips?
EDIT
I've got this off the logs:
Error X-Token: chars_and_numbers,,chars_and_numbers2
Error Exception: Sequence contains no elements in System.Core
Google indicates that there is something wring with the encoding? I use the same method, UTF8 all the way...
Related
I have written a WPF application that sends a POST WebHTTPRequest to a WCF service. The service required windows credentials to perform operations on the server. When the service receives the HTTP request, it is unable to parse the Authorization header.
The POST request begins like this.
HttpWebRequest req = WebRequest.CreateHttp(url);
req.ContentType = "application/json;charset=UTF-8";
req.Accept = "application/json";
req.Headers.Add("Authorization", Base64Encode(Details.username + ":" + Details.password + ":" + Details.domain));
req.Method = "POST";
byte[] reqBytes = Encoding.ASCII.GetBytes(body.ToString());
And is received on the service like this
IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest;
WebHeaderCollection headers = request.Headers;
if (headers["Authorization"] != null)
{
cred = headers["Authorization"];
} else
{
HttpContext.Current.Response.Write(result);
return;
}
I print the "cred" variable to a log file and what I get begins something like this "敎潧楴瑡䥙䝉䅺䝙" which, quite clearly, is wrong. Can anybody tell me why I'm getting this output as opposed to the input consisting of the English characters I sent the request with?
The problem is that you encoded a UTF-8 encoded string into Base64.
You specified that the charset type for your JSON file is UTF-8 here:
req.ContentType = "application/json;charset=UTF-8";
So when you tried to encode your Authentication into Base64 it would have ruined your string.
req.Headers.Add("Authorization", Base64Encode(Details.username + ":" + Details.password + ":" + Details.domain));
Try a different way of encoding the string
I am working on a project that requires to oauth2 token to communicate. The backend gives me a curl command, but I have no idea how to put it into WWW form in Unity because I have no former experience with http or json file. Could you help me to access the token? Thanks. Here how the curl code looks like:
$ curl -v -u {CLIENT_ID}:{CLIENT_SECRET} "https://api.domo.com/oauth/token?grant_type=client_credentials&scope={SCOPE}"
and here is an example:
$ curl -v -u 441e307a-b2a1-4a99-8561-174e5b153fsa:f103fc453d08bdh049edc9a1913e3f5266447a06d1d2751258c89771fbcc8087 "https://api.domo.com/oauth/token?grant_type=client_credentials&scope=data%20user"
Thank you so much!
To get oauth2 token with the WWW API, use the WWWForm to create form that contains the grant_type, client_id and client_secret. When you make the request, the token should be returned in Json format. Use Unity's JsonUtility to convert it to string you can easily obtain.
Retrieving Token:
[Serializable]
public class TokenClassName
{
public string access_token;
}
IEnumerator GetAccessToken()
{
var url = "http://yoururl.com";
var form = new WWWForm();
form.AddField("grant_type", "client_credentials");
form.AddField("client_id", "login-secret");
form.AddField("client_secret", "secretpassword");
WWW www = new WWW(url, form);
//wait for request to complete
yield return www;
//and check for errors
if (String.IsNullOrEmpty(www.error))
{
string resultContent = www.text;
UnityEngine.Debug.Log(resultContent);
TokenClassName json = JsonUtility.FromJson<TokenClassName>(resultContent);
UnityEngine.Debug.Log("Token: " + json.access_token);
}
else
{
//something wrong!
UnityEngine.Debug.Log("WWW Error: " + www.error);
}
}
Using the Token:
After you receive the token, it will be stored in the json.access_token variable. You can use then use that to make requests by adding it to the Header of your other WWW requests. That header is stored in a Dictionary like this:
headers.Add("Authorization", "Bearer " + token);
Here is an full example for making a request with the received token:
IEnumerator makeRequestWithToken(string token)
{
var url = "http://yoururl.com";
Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add("Authorization", "Bearer " + token);
WWWForm formData = new WWWForm();
formData.AddField("YourField", "YourVal");
formData.AddField("YourField", "YourVal");
WWW www = new WWW(url, formData.data, headers);
yield return www;
//and check for errors
if (String.IsNullOrEmpty(www.error))
{
string resultContent = www.text;
UnityEngine.Debug.Log(resultContent);
}
else
{
//something wrong!
UnityEngine.Debug.Log("WWW Error: " + www.error);
}
}
Unity now uses UnityWebRequest. If possible start using that. Here is an example of retrieving oauth2 with UnityWebRequest.
Note that both functions are coroutine functions and must be started with the StartCoroutine function like StartCoroutine(GetAccessToken()); and StartCoroutine(makeRequestWithToken("YourToken"));.
I got it working using the following method:
Refer to Travis's fitbit code
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(_clientID + ":" + _consumerSecret);
var encoded = Convert.ToBase64String(plainTextBytes);
var form = new WWWForm();
form.AddField("client_id", _clientID);
form.AddField("grant_type", "authorization_code");
form.AddField("redirect_uri", WWW.UnEscapeURL(CallBackUrl));
form.AddField("code", _returnCode);
var headers = form.headers;
headers["Authorization"] = "Basic " + encoded;
_wwwRequest = new WWW("https://api.fitbit.com/oauth2/token", form.data, headers);
Relate to your backend, see what kind of oauth2 they are using, you can see the oauth2 documentation Here. Feel free to leave a comment for question.
I'm trying to get Atom feed for an email account using HttpClient. Before I tried to get mail.google.com and use them with custom HttpClientHandler but it didn't work.
I've searched for solution and managed to find out that I can use `Authorization header to pass credentials to the server but this doesn't work either. Am I doing something wrong? Why am I gtting 401 error? Does this method no longer work?
Here's my code:
public async Task<bool> CheckMail()
{
AMailRefresher.handler.CookieContainer = new CookieContainer();
string url = "https://mail.google.com/mail/feed/atom";
var encoded = StringToByte64(user + ":" + password);
HttpResponseMessage res = null;
try
{
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, url);
req.Headers.Add("Authorization", "Basic " + encoded);
res = await AMailRefresher.http.SendAsync(req);
}
catch { }
var xml = await res.Content.ReadAsStringAsync();
if (lastFeedScan == null)
lastFeedScan = xml;
if (xml != lastFeedScan)
{
lastFeedScan = xml;
return true;
}
return false;
}
private static string StringToByte64(string text)
{
ASCIIEncoding encoding = new ASCIIEncoding();
var bytes = encoding.GetBytes(text);
return Convert.ToBase64String(bytes, 0, bytes.Length);
}
If you have enabled 2-Step Verification for your Google account (i.e. new logins send a code in a text message to your phone which you must then enter to authorize the login) then you cannot use your (base 64 encoded) normal password with this approach. Instead, you must create an App password in order to bypass the 2-Step Verification. See Sign in using App Passwords for detail. The How to generate an App password section directs you to App passwords where you can create a custom, unique 16 character password for your application to use instead.
I am new here and I hope someone can help me. I try to connect to twitch.tv I am trying to get an oauth2 authentication on twitch.tv with a small C# program. I am using the twitch.tv authentication request. Here is my C# code:
var loginURL = "https://api.twitch.tv/kraken/oauth2/authorize?
response_type=code&"+
client_id="+ clientID+"
"&redirect_uri=http://localhost&"+
"state=TWStreamingStateAuthenticated";
this.richTextBox1.Text = loginURL;
string code = get_DownLoadString(loginURL);
this.richTextBox1.Text = code;
This is the part, which does not work. It gives me the Error 400: Bad Request.
WebRequest request = WebRequest.Create("https://api.twitch.tv/kraken/oauth2/token");
request.Method = "POST";
string postData = "client_id=" + clientID +
"&client_secret=" + clientSecret +
"&grant_type=authorization_code" +
"&redirect_uri=http://localhost" +
"&code=" + code +
"&state=TWStreamingStateAuthenticated";
ASCIIEncoding encoding = new ASCIIEncoding();
postData = HttpUtility.UrlEncode(postData);
byte[] byteArray = encoding.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream datatream = request.GetRequestStream();
datatream.Write(byteArray, 0, byteArray.Length);
datatream.Close();
WebResponse respone = request.GetResponse();
MessageBox.Show(((HttpWebResponse)respone).StatusDescription);
I hope someone can help me.
And here is the Get_DownloadString(string URL) Method.
private static string get_DownLoadString(string URL)
{
try
{
string temp = (new WebClient().DownloadString(URL));
return temp;
}
catch (WebException)
{
return null;
}
}
This code doesn't look right to me:
string postData = "client_id=" + clientID +
"&client_secret=" + clientSecret +
"&grant_type=authorization_code" +
"&redirect_uri=http://localhost" +
"&code=" + code +
"&state=TWStreamingStateAuthenticated";
ASCIIEncoding encoding = new ASCIIEncoding();
postData = HttpUtility.UrlEncode(postData);
byte[] byteArray = encoding.GetBytes(postData);
// ...
You are URL-encoding the entire post-data string. This has the effect of converting the & and = signs in the post data to %26 and %3d respectively. When the remote server receives this data, it will scan through it looking for the & and = signs in order to separate out the parameter names and values. Of course, it won't find any, so it will assume you have one big parameter name with no value. The server is probably expecting values for each of the six parameters you are attempting to send, but seeing values for none of them, and this may be why you are getting a 400 Bad Request error.
Instead of URL-encoding the whole string, URL-encode parameter values that may contain characters other than letters and numbers. I would try the following instead:
string postData = "client_id=" + HttpUtility.UrlEncode(clientID) +
"&client_secret=" + HttpUtility.UrlEncode(clientSecret) +
"&grant_type=authorization_code" +
"&redirect_uri=" + HttpUtility.UrlEncode("http://localhost") +
"&code=" + HttpUtility.UrlEncode(code) +
"&state=TWStreamingStateAuthenticated";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byteArray = encoding.GetBytes(postData);
// ...
This way, the remote server will still see the & and = characters, and so will be able to pull out the parameter names and values. Because we've URL-encoded the client ID, client secret, URL and code, any characters they contain that may have meaning in a URL will not have that meaning and will be received by the remote server as intended.
Also, if you are still getting a 400 Bad Request error response, try reading the contents of the response stream, obtained by calling GetResponseStream() on the response. Often that will contain a message that will help you figure out what's gone wrong.
Having had a closer look at your code, it seems you have a misunderstanding about how OAuth authentication works. Your getDownload_String method will not get the access code you want, it will only get the HTML text of a Twitch login page.
This is how OAuth authentication works:
Your app sends the user to a login URL, to allow the user to log in to Twitch.
In the web browser, the user then enters their login credentials and submits the page to Twitch.
The Twitch API then responds by redirecting the user's web browser to the redirect URL, with a code appended. Your web app then reads this code out of the URL.
If your code is in a web app it will be able to respond to the URL redirected to in step 3. Alternatively, you may be able to use a WebBrowser control (Windows Forms, WPF) to handle the Twitch login, and handle a Navigating event. If the URL being navigated to begins with the redirect URL, grab the code out of the URL, cancel the navigation and hide the login web-browser control.
The presence of what appears to be a RichTextBox control, along with your comment about your code being a 'small C# application', makes me think that your code is a Windows Forms or WPF application. If this is the case, then you will need to either:
use a WebBrowser control as I described above,
replace your WinForms/WPF app with a web app, or
get in contact with Twitch to request the use of the password flow (which appears not to require a redirect), and use that instead.
I'm not very good with any networking type of things (as far as C# goes) but I need to post data (not get!) to a web url and then return what it outputs.
So far I'm using this for post and determining if it's logged in or not.
//credentials
string username = textBox1.Text;
string password = textBox2.Text;
using (WebClient client = new WebClient())
{
byte[] data = Encoding.Default.GetBytes("username="+username+"&password="+password);
client.Headers["Content-Type"] = "application/Json";
try
{
var response2 = client.UploadData(base_url + "/users/authenticate", "POST", data);
MessageBox.Show(Encoding.Default.GetString(response2));
}
catch { }
}
Note: Error I'm getting is 400 bad request. Any ideas?
Looking at the vine code, I would say you need to send it JSON data instead of URL data. With something simple like that you can just write the string.
String jsonData = "{\"username\": \"" + username + "\", \"password\": \"" + password + "\"}";
Updated to add encoding and be more strict with JSON data
PHP's JSON decoder wants UTF-8 encoded data, so also change the encoding line to
byte[] data = Encoding.UTF8.GetBytes(jsonData);