How to get oauth2 token with the WWW API? - c#

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.

Related

OpenID Connect Authentication Successful. Now what?

I'm writing a windows service in C# that needs to authenticate with an API and make some calls. I'm able to authenticate successfully with this API I'm talking to, but I can't seem to figure out how to use the response. The response looks like this:
{"access_token":"Es-Zjs_LI0tcXyLe3aEfgKPNLHN7CwyUhTss-cTld1A","expires_in":1800,"token_type":"Bearer","scope":"example","auth_state":1,"company":"examplecompany"}
I can get the access token out of that string if I want, but no matter how I pass it to a request, I get a 401 error. This is what my current iteration looks like:
string results = "";
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://example.ca/endpoint"),
//Headers =
//{
// { "authorization", "Bearer"},
//},
};
try
{
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
results = body;
}
}
catch (Exception ex)
{
results = "ERROR: " + ex.Message;
}
return results;
Where "token" is the string "Es-Zjs_LI0tcXyLe3aEfgKPNLHN7CwyUhTss-cTld1A" in this example. I had previously tried stitching the access_token value as a string to the "Bearer" string in the commented out section in the middle there. What am I doing wrong? Do I need to make a JwtSecurityToken out of the response?
AuthenticationResult authResult = await daemonClient.AcquireTokenForClient(new[] { MSGraphScope })
.ExecuteAsync();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
I've used the authResult.AccessToken. Not sure if it works in your scenario. The return type in my case was Microsoft.Identity.Client.AuthenticationResult type when I retrieved the token for a Graph API that I was using.
Be aware that the token you have received ("Es-Zjs_LI0tcXyLe3aEfgKPNLHN7CwyUhTss-cTld1A") is a reference token and not a JWT-token. Make sure your API accepts that type of token.
To use the token effectively in production then I would consider using the various helper methods found in the IdentityModel library and especially the Worker application helpers.
While I understand it's largely situational depending on what API you're trying to connect to, for me the solution was to use this method to pass in the authentication token:
request.Headers.TryAddWithoutValidation("Authorization", "Bearer " + token);

How to update user picture using PUT method in Unity3D

I'm a beginner in Unity3D; i have to develop a mobile app and i need to manage user profile data; i have to communicate these data with server using REST services.
Everything works fine when i send Json (eg name, email, phone number, etc.) from my app, but I can't update the profile picture.
What i need is:
Content-Type = multipart/form-data
key="profile_picture", value=file_to_upload (not the path)
I read a lot about networking in Unity and tried different combinations of UnityWebRequest, List, WWWform but nothing seems to work for this kind of PUT service.
UnityWebRequest www = new UnityWebRequest(URL + user.email, "PUT");
www.SetRequestHeader("Content-Type", "multipart/form-data");
www.SetRequestHeader("AUTHORIZATION", authorization);
//i think here i'm missing the correct way to set up the content
I can correctly simulate the update from Postman, so it's not a problem with server; i'm pretty sure that the problem is that i can't convert this logic inside the app.
Upload from Postman correctly working(1)
Upload from Postman correctly working(2)
Any kind of help and code suggestion will be appreciated.
Thanks
With Put you usually only send file data but without a form.
You can add a multipart form using UnityWebRequest.Post
IEnumerator Upload()
{
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormFileSection("profile_picture", byte[], "example.png", "image/png"));
UnityWebRequest www = UnityWebRequest.Post(url, formData);
// change the method name
www.method = "PUT";
yield return www.SendWebRequest();
if(www.error)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
}
}
using a MultipartFormFileSection
Or alternatively you can use a WWWForm
IEnumerator Upload()
{
WWWForm form = new WWWForm();
form.AddBinaryData("profile_picture", bytes, "filename.png", "image/png");
// Upload via post request
var www = UnityWebRequest.Post(screenShotURL, form);
// change the method name
www.method = "PUT";
yield return www.SendWebRequest();
if (www.error)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Finished Uploading Screenshot");
}
}
using WWWForm.AddBinaryData
Note that for user authentication you have to encode your credentials properly:
string authenticate(string username, string password)
{
string auth = username + ":" + password;
auth = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth));
auth = "Basic " + auth;
return auth;
}
www.SetRequestHeader("AUTHORIZATION", authenticate("user", "password"));
(Source)

Send POST request with Image from Unity3D

I'm trying to send an image to my NodeJS API from Unity but unfortunately I can't make it work. Here is an extract of my c# code:
private string POSTUrl = "http://myNodeJSAPI.com/upload-image";
private Dictionary<string, string> postHeader = new Dictionary<string, string>();
public WWW POST() {
WWW www;
postHeader["content-Type"] = "application/octet-stream";
postData = File.ReadAllBytes("Assets/Resources/ImageIWantToSend.png");
www = new WWW(POSTUrl, postData, postHeader);
StartCoroutine(WaitForRequest(www));
return www;
}
IEnumerator WaitForRequest(WWW www)
{
yield return www;
if (www.error == null)
{
Debug.Log("WWW Ok!: " + www.text);
}
else
{
Debug.Log("WWW Error: " + www.error);
}
}
and here the relevant part of my nodejs one:
app.post('/upload-image', rawBody, function (req, res) {
console.log("File received!");
if (req.rawBody && req.bodyLength > 0) {
fs.writeFile("/tmp/ImageIWantToSend.png", req.rawBody, function (err) {
if (err) {
return console.log(err);
}
console.log("Image has been saved! Starting other things...");
})
}
}
The request is sent but never received by the API (I get 503 bad gateway). I try the same request outside Unity and it seems to work (using Postman: basic post request with image attached as binary).
Did I make a mistake, or is there another way to achieve this?
Thanks!
EDIT: I finally solved the problem by changing application/octet-stream to text/html. If there is a better way to send data to Nodejs I'm still interested
Check out Unity's new UnityWebRequest class.It is a replacement for original WWW.
You can also use C# WebClient or HttpWebRequest class. They work with Unity if you are not using WebGL build.
This is also a good unity plugin to handle requests, though it is not free.

How can I set authorization header in my Unity3D game?

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...

Send XML to RESTful web service from Unity

I'm using WWW to interact with a RESTful web service. I have a problem sending XML files to the server through POST requests, though. This is my code:
if(Syste.IO.File.Exists(filePath)){
byte [] raw = File.ReadAllBytes(filePath);
WWWForm form = new WWWForm();
form.AddBinaryData("fileUpload", raw, "", "text/xml");
WWW www = new WWW(host + auth + "/behaviors", form);
StartCoroutine(myCoroutine(www));
}
IEnumerator myCoroutine(WWW www){
yield return www;
if (www.error == null)
{
Debug.Log("Text: " + www.text);
proceedToNextRequest = true;
} else {
Debug.Log("Error: "+ www.error);
Application.Quit();
}
}
The answer from the server is, though, "Unsupported Media Type", and I've no idea what's wrong. I generally use POSTMAN on Google Chrome to send these requests, and it works fine. Any tips?
I have found a solution for this: instead of using the WWW class(which, anyway, according to the documentation I'm pretty sure it can be used for this pupose), I'm using WebRequest. How this can be achieved is very well explained in the previous link and in this question: HTTP post XML data in C#

Categories

Resources