How to build a safe API for Unity - c#

I want to build an API for Unity. I noticed many APIs in Unity like Vuforia, requires developers to generate a key on website, and then paste the key into Unity editor, I wonder how does it work? When will Unity send the key to website to validate? Which protocol is this so I can research more on the internet?

When will Unity send the key to website to validate?
It depends. Some send the key during every request. Some send the key once, then generate a temporary token that will be used to make other requests.
Which protocol is this so I can research more on the internet?
Most web API use the REST protocol.
Usually POST or GET request methods.
I wonder how does it work?
It's not complicated. You need to know C#, MySQL and PHP(any back-end language). If you know these 3 languages, you can do it.
The MySQL is used to store user information such as username, password. User can go on the website and create a private key. That key will be saved on the database and linked to that user with MySQL.
When you make a request from Unity(C#) to the server, you can get the key from the user then embed in a form(WWWForm). You can use that form (WWWForm.AddField("API_KEY", "Your key")) to make request to the server with the WWW or UnityWebRequest API.
When the PHP receives request from your Unity. You read the form sent from Unity with PHP ($_POST["API_KEY"]) and then check if the key is in the database with MySQL. If the key exist, go ahead and do what the request want. If the key does not exist in the database echo error message.
That's it. Below is an example of an API that converts Image to Text. It requires key to function. Some functions are not implemented and is only used to show how API key authentication is done.
C#:
public Texture2D texture;
public void sendData()
{
string reqUrl = "http://yourServerUrl.com/app/imagetospeech.php";
WWWForm reqForm = new WWWForm();
//Add API key
reqForm.AddField("API_KEY", "AEH392HEIQSKLZ82V4HCBZL093MD");
//Add Image to convert to Text
reqForm.AddBinaryData("REQ_IMAGE", texture.EncodeToPNG());
WWW www = new WWW(reqUrl, reqForm);
StartCoroutine(WaitForRequest(www));
}
private IEnumerator WaitForRequest(WWW www)
{
yield return www;
//Check if we failed to send
if (string.IsNullOrEmpty(www.error))
{
UnityEngine.Debug.Log(www.text);
}
}
PHP:
<?php
function keyExist($keyInput)
{
//MySQL code to check if key is in the table
//$retval = NOT IMPLEMENTED!
if (!$retval) {
return false;
} else {
return true;
}
}
function convertImageToText($imageInput)
{
//$retval = NOT IMPLEMENTED!
if (!$retval) {
return "";
} else {
return $retval;
}
}
//Get API key from Unity
$apiKey = $_POST["API_KEY"];
//Check if API key exist
if (keyExist($apiKey)) {
//Get the image from Unity
$imageFile = $_FILES['REQ_IMAGE'];
if (!empty($imageFile)) {
//Success
echo convertImageToText($imageFile);
} else {
echo "Failed!";
}
}
?>

Related

Authentication in Dialogflow API V2 using C#

I have .NET Web API Project for the fulfillment API as our webhook in my Dialogflow agent. In our Post method of the controller, after getting the request from Dialogflow, I implement the explicit authentication as shown in the Google Cloud documentation for C#.
//jsonFileName is the name of the serviceAccountKey json generated from the Google Cloud Platform that's encrypted internally
public bool AuthExplicit(string projectId, string jsonFileName)
{
try
{
string JsonCredential = DecryptHelper.Decrypt(jsonFileName);
var credential = GoogleCredential.FromJson(JsonCredential).CreateScoped(LanguageServiceClient.DefaultScopes);
var channel = new Grpc.Core.Channel(
LanguageServiceClient.DefaultEndpoint.ToString(),
credential.ToChannelCredentials());
var client = LanguageServiceClient.Create(channel);
AnalyzeSentiment(client);
if (client != null)
{
return true;
}
else
{
return false;
}
}
internal void AnalyzeSentiment(LanguageServiceClient client)
{
var response = client.AnalyzeSentiment(new Document()
{
Content = "Authenticated.",
Type = Document.Types.Type.PlainText
});
var sentiment = response.DocumentSentiment;
string score = $"Score: {sentiment.Score}";
string magnitude = $"Magnitude: {sentiment.Magnitude}";
}
The difference with the code is that after getting the client, when we call the AnalyzeSentiment() method, it doesn't do anything, and the projectId parameter is never used to authenticate. GCP docs are quite confusing, since when there is an AuthExplicit() that uses projectId, it uses it as a parameter for the buckets and only prints this on the console.
It works fine, until we test the service account key with a different agent. Expected output is that authentication would fail, but somehow it still passes.
Once the Post method goes through the AuthExplicit() method, it would only return a boolean. Is this the right way to authenticate? Or is there something else needed to invoke?
The difference with the code is that after getting the client, when we call the AnalyzeSentiment() method, it doesn't do anything,
Does client.AnalyzeSentiment() return an empty response? Does the call hang forever?
It works fine, until we test the service account key with a different agent.
What is a different agent? A different User-Agent header?
Once the Post method goes through the AuthExplicit() method, it would only return a boolean. Is this the right way to authenticate? Or is there something else needed to invoke?
What does 'the Post method' refer to? What is the 'it' that would only return a boolean?

Login to html webpage with unity

So I work with unity and I was making a program that pulls data from a webpage. The only problem that I have now, is that I have to login to the webpage. I have a username and password there .I tried everything but it doesn't work. Could someone help me pls?
Here is the website:
https://dia.smartschool.be/login
Here is my script:
public class Login : MonoBehaviour
{
public InputField username;
public InputField password;
string LoginURL = "https://dia.smartschool.be/login";
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void taskready()
{
Debug.Log("pressed");
StartCoroutine(LoginToSS(username.text, password.text));
}
IEnumerator LoginToSS(string ss_username, string ss_password)
{
WWWForm form = new WWWForm();
form.AddField("login_form[_username]", ss_username);
form.AddField("login_form[_password]", ss_password);
form.AddField("login_form[_token]", "Click");
WWW www = new WWW(LoginURL, form);
yield return www;
Debug.Log(www.text);
Debug.Log(ss_username);
Debug.Log(ss_password);
}
}
By looking at the page in question its pretty clear why this wouldn't work - you are passing "[Click]" string as the token, where as you should be using a token that the website presents to you when it displays the form - when trying in different browsers the token is different so chances are the website wants to keep track of 'who tries to login' as a basic security feature.
I am not quite sure what the BEST way to obtain the token is, but the most obvious one is get the form first with WWW, and search the string manually. I imagine it would accept the loin once you supply it with a valid, just obtained token

You are using download over http. Currently Unity adds NSAllowsArbitraryLoads to Info.plist to simplify transition

making an app for both iOS and Android with Unity.
I'm now stuck on an iOS problem:
You are using download over http. Currently unity adds `NSAllowsArbitraryLoads` to `Info.plist` to simplify transition, but it will be removed soon. Please consider updating to https.
unsupported URL
The actual problem is:
- I connect to an https address
- I did set the Allow Arbitrary Loads to YES
Yet, it's not working.
Here's my code:
string GET = "mail="+mail+"&nome="+nome+"&cognome="+cognome;
// get parameters
WWW response = new WWW (SERVER+"adduser/?"+GET);
// calling page, address is like 'https://website.com/'
while (!response.isDone && response.error != "") {
yield return null;
}
if (response.error != "") {
print (response.error);
return false;
}
obviously, this is in a IEnumerator function and it ALWAYS returns the previous error.
Apple stopped allowing http connections on iOS devices. You can still use http connection by adding NSAppTransportSecurity to the info.plist but this will be removed in the future.It is recommended that you use https connection from now.
http://yourdomain.com will give you this error.
https://yourdomain.com will NOT give you this error and is what Apple
recommends now.
UnityWebRequest was introduced to automatically solve this problem by adding NSAppTransportSecurity to the info.plist.
IEnumerator makeRequest()
{
string GET = "mail=" + mail + "&nome=" + nome + "&cognome=" + cognome;
UnityWebRequest www = UnityWebRequest.Get(SERVER + "adduser/?" + GET);
yield return www.Send();
if (www.isError)
{
Debug.Log("Error while downloading: " + www.error);
}
else
{
// Show results as text
Debug.Log(www.downloadHandler.text);
// Or retrieve results as binary data
byte[] results = www.downloadHandler.data;
}
}
Note that your app may be rejected if you add NSAppTransportSecurity to the info.plist without good explanation to Apple. Again, it is recommended that you upgrade your server and use https instead of http.

Sending data from unity to firebase producing error - Invalid data; couldn't parse JSON object

Just use Unity3d with Firebase I have a url of database where i want to send data.
Code below i am using
void Start()
{
BtnSendScore();
}
public void BtnSendScore() {
StartCoroutine(SendScore("Muhammad Faizan Khan", 100));
}
public IEnumerator SendScore(string name, int score){
string url = "https://xyz.firebaseio.com/scores.json";
WWWForm objForm =new WWWForm();
objForm.AddField("playerName", name);
objForm.AddField("score", score);
objForm.AddField("scoreDate", DateTime.Now.ToString());
WWW www = new WWW(url, objForm);
yield return www;
if (www.error == null)
{
Debug.Log("Adedd ::" + www.data);
}
else {
Debug.LogError("Error ::" + www.error);
}
}
Found this error? What the problem is i check on stackoverflow with jquery it talking about stringify.
Adedd ::{ "error" : "Invalid data; couldn't parse JSON object,
array, or value. Perhaps you're using invalid characters in your key
names." }
Remember I didn't mess with database in firebase just create database and got url. No keys added.
To write to the Firebase Database using the REST API, you'll need to pass the data as JSON in the body of the request. The Firebase REST API does not take the data as form parameters. See the Firebase documentation for some examples of how the API works.
This post looks like a promising starting point as does this answer.

Unity C#, WWWForm post to Python Flask Server

Hi I am making a game in unity and I need to post information to my python flask server I think that the best method is to use the WWWForms in Unity C# but I can't seem to make it post. Here is my C# Unity Code:
IEnumerator Upload() {
WWWForm form = new WWWForm();
form.AddField("Username", "Stan");
form.AddField("Password", "123456");
using(UnityWebRequest www = UnityWebRequest.Post("http://myserver.com/newuser/", form)) {
yield return www.Send();
if(www.isError) {
Debug.Log(www.error);
}
else {
Debug.Log("Form upload complete!");
}
}
}
It alsways says "From upload complete" and I don't get any errors but when I check my SQL Database it hasn't received the information.
I am pretty sure that my server side code is right because I can post successfully to it through the Form but here is the code anyway:
Python Flask:
class Users(db.Model):
__tablename__ = "userstable"
userid = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(4096))
password = db.Column(db.String(4096))
#app.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html")
#app.route("/newuser", methods=["GET", "POST"])
def NewUser():
if request.method == "GET":
return render_template("NewUser.html")
new_user = Users(username=request.form["Username"], password=request.form["Password"])
db.session.add(new_user)
db.session.commit()
return redirect(url_for('NewUser'))
Please Help, and if possible it would be nice to know how to do get requests as well, Thanks!
Stan.

Categories

Resources