Business App: Login and Password Encryption Sample

Hey Rob,

I am now at a different phase of my app, and got all the logging in and account creation finished and working, password encryption and email verification included. I now would like to incorporate google maps into the app, and I’m now using the business sample app as guidance on how to implement the api. I was just curious though if it is possible to use the maps api to show location of other users using the app who are online, similar to how the ios Find My Friends app works or Uber does.

BTW, should I post this as a new topic?

Thanks in advance,

-YL

If you just want to drop pins where people are and annotate those pins, it’s possible. The Business App sample should show you how to do that. What it won’t show you is how to retrieve that data from your server.

Rob

I’m not sure I understand what you mean. By drop pins, did you mean do that in the code for preset locations?

Allow me to further explain what I would like to do with my app. Hypothetically, users would want to interact with each other, and should be able to see nearby users who choose to be discoverable for others (in real time), and maybe set meet up locations too. Is this possible with corona? If so, do you have any idea as to how this would be achieved or if it has been discussed before in the forums or with sample apps?

What I mean by drop pins (which is the map lingo) is to place a marker at the location where something you care about exists. The sample you are working from drops four custom pins (Starbucks Logos) at the location where there are Starbucks located around the Palo Alto area.

In the code (I’m going from memory as I don’t have it open in front of me) there is a table that contains the latitude and longitude for each of the locations and perhaps some other info. I believe I loop over that table with a for loop and instruct the map API’s to place the pin a the lat/long spot on the map.

What I don’t do is I don’t fetch that information from a server. To do what you want, you have to have a way for each app user to find the locations of the other. Typically that means your app will report your location to your server. Then you will have a way to talk to your server and get all people near you. That should return to you a list of people, their lat/long and other info. You can then plot those pins on your map in a way similar to the sample.

If you want more real time behavior you may need to implement a way to have your server send out push notifications that can update your app, or use a multi-player game plugin feature (check out Photon Cloud in our store.coronalabs.com as a starter). Your app could reasonably send out updates and Photon cloud would broadcast values back out to everyone in near real time.

Rob

Hey Rob,

I was wondering if you would be willing to chat? You’ve been helping me a lot with my app through these forums, but it would probably be easier if we could actually have a conversation on some other platform, assuming of course you are willing to do so. I just needed some more help with the maps API like I mentioned before, and I really don’t know where else to go for help.

Thanks in advance,

YL

My access is pretty much limited to here. Other community members might be more available to have a chat with you.

Hey Rob,

I’m pretty lost again. I’m still trying to make progress on my app but I can’t seem to find in depth help with what I want to do. Today I found about Parse server (which apparently is only going on for one more year) and some stuff like REST api which im not sure what they mean. Thing is, im considering again switching platforms because I cant find much help or places to learn how to implement these functionalities into my app… more specifically, being able to locate other users on a map and be able to send them a request (for a service) and then have the other user agree to the service or decline it.

Actually you’ve done something in your own thread called “Hijacking”. You did it twice actually. The first time was asking about activity indicators that have nothing to do with business app logins and passwords.

These are community forums which means that the community pitches in to help each other. They need good thread topics to respond to and generally they don’t response once a staff member has responded.  The second hijack came when you changed the topic to discuss maps and putting markers on the map and getting data from services.

There are lots of people willing to help answer these questions and there is also the “Google machine”. There is forum search. It’s amazing what can be found by doing:  “Corona map tutorial” in a google search.

I suggest that we close this thread unless it has to do with business app login and password encryption. Start a new thread asking the question you need help with at the moment. Make sure to create a good title, let people know what you’ve tried and what resources you’ve looked at and see what happens.

Rob

I decided to post to this thread because you were following it, and you clearly know corona very well, so I thought it would be my best option to talk to someone who I had already had contact with before and seemed to be active in the forums.

I’m well aware of the things that can be found by using google, which is the first thing I do when i try to work on something i’m not familiar with. Before I made any posts at all in this forum actually, I made sure to research the subject thoroughly and try to find all the information I could. The only reason I started posting on this forum, was because I was unable to find anything that could truly help me develop my app.

To your last suggestion, I already did, a few days ago. Again, I came back to this thread because the other one wasn’t getting much attention.

You can bump your post after say 24 hours or so if you’re not getting traffic. What was it called? or better yet what is the URL to the thread?

https://forums.coronalabs.com/topic/62536-app-that-uses-maps-api/ link to the other tread.

Just added an edit to the first post too.

We recently updated the Business App sample (https://github.com/coronalabs/business-app-sample) to include form entry and reading and writing from a local SQLite database that might get you started, however I specifically did not use login’s as an example because I felt the app was complex enough.

For inputting the user information, you will new native.newTextField(). There is an option .isSecure that turns a field into a password field. This is all documented under those APIs. That’s the easy part.

From there you would use network.request() to make an HTTP request to a server that you have access to. On that server you would likely have a script written in PHP or ASP or some other web scripting language. That script would then take the values, process then and the script would talk to whatever database you’re using (MySQL, etc.), compare the username and password and if they match, return a value to your app that network.request() would present to you in it’s call back listener function. Your app can then react to the results accordingly.

That’s a basic outline of the data flow. Now lets switch up and talk about the password itself.

Your database should never allow passwords to be read back to clear text. Never store the password in clear text either. You should use some form of one way encryption. MD5 hashes uses to be the preferred way, but those have gotten to easy to hack. SHA 256 bit seems to be what most people favor today. Our OpenSSL plugin can do SHA 256.  But that’s not enough to. You need to also “salt” your passwords. Basically you need to add some additional data to the password beyond what the person typed. You can look up various salt algorithms. But the idea is that if  the user gives you the password “password123”, you would change it to: ABCD1235password123ZYXW9876 where the added text is something you control and probably should be something different for each user. You’ve made the password more complex but more importantly if it gets decrypted, the user won’t know what part they have to type in.  This is a very general description of salting.

Then when your script runs, you might do an SQL query like:

$query = "SELECT id FROM usertable WHERE username = " . $username . " AND password = " . $password;

Where the password is the encrypted + salted password. When you execute the query, it will either find the person or not. Then return something your app recognizes as success or fail.

First off I want to thank you for your help! Your response clears a lot of things up for me, but unfortunately also raises a few new questions.

I’ve never used the network.request() command before, so I’m not really sure how it works. Would i be passing something in the parameters, say for example, the php script that would be stored in the same directory as the database?

The network.request() API is fairly well documented: https://docs.coronalabs.com/api/library/network/request.html

You are most likely going to use either an HTTP GET or POST request. GET requests, any thing you need to pass to the server is done as part of the URL:  http://mysite.com/myscript.php?key1=value1&key2=value2&key3=value3

You probably have used URLs like this. The value’s have to be URL encoded if they have something other than letters and numbers in them. For instance if you want to pass the string “Hello World” as the value for key3 above it would change the URL to:

http://mysite.com/myscript.php?key1=value1&key2=value2&key3=Hello%20World

Note how the space was encoded to its hex value and prepended with a %. There are various URL encoding functions you can google for.

Then for a basic network request call looks like:

URL = "http://mysite.com/myscript.php?key1=value1&key2=value2&key3=Hello%20World"

network.request( URL, “GET”, requestListener )

In this case you also need to provide a function (in the example above named requestListener) that handles the return from the web server. The documentation should explain all of that.

HTTP POST requests don’t pass data on the URL like GET instead you create a table named “body” and in the body you put your & delimited key/value pairs. Why the difference? GET requests are limited to like 200 characters. If you need to send more data, POST is the way to go. Then there are the semantics of it. GET is generally used to “fetch” data. POST is generally used to send data. But if you’re in control of  your own script, it’s perfectly fine to use GET to send small amounts of data.

Your script can return anything but you have to parse it if its more than a simple value. It’s best to have your script output JSON. If you’re using PHP, and you store the information in an associative array (pretty much the same thing as a Lua table). you can use the PHP json_encode() function to handle making the JSON data:

$result = json\_encode( $myArray ); echo( $result );

Back in your app, inside that requestListener function you will get a table named "event (if you follow our examples) and a member of that is event.response. This will hold the output of your online script. If it’s JSON data then you can do:

local myTable = json.decode( event.response )

Now myTable will magically contain everything in the PHP $myArray with the same names and same table structure.

Rob

sorry about that haha I originally tried using <code> tags the first time i posted it. Here it is.

this is my php script used to register a new account (no encryption, just testing purposes):

\<?php require 'connection.php'; if (!$conn) {die( "Connection failed: " . mysqli\_connect\_error());} echo 'hi'; $email = mysqli\_real\_escape\_string($conn, $\_POST['email']); $password = mysqli\_real\_escape\_string($conn, $\_POST['password']); $mobile = mysqli\_real\_escape\_string($conn, $\_POST['mobile']); $gender = mysqli\_real\_escape\_string($conn, $\_POST['gender']); $query = mysqli\_prepare($conn, "INSERT INTO USER (email, password, mobile, gender) VALUES(?,?,?,?)"); mysqli\_stmt\_bind\_param($query, 'ssss', $email, $password, $mobile); mysqli\_stmt\_execute($query); mysqli\_stmt\_close($query); msqli\_close($conn); ?\>

which seems like it would work fine, but I’m still stuck in the network.request() part.

From the the documentation on corona labs, I figured I’d use the last example that uploads a text file, using POST.

It looks like this:

local function networkListener( event ) &nbsp;&nbsp;&nbsp; if ( event.isError ) then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print( "Network error: ", event.response ) &nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print ( "Upload complete!" ) &nbsp;&nbsp;&nbsp; end end local headers = {} headers["Content-Type"] = "application/json" headers["X-API-Key"] = "13b6ac91a2" local params = {} params.headers = headers -- Tell network.request() to get the request body from a file: params.body = { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --is this section where I would get what i want to post data from my textfields?, say for example: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --email = emailTextField.text &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --and if so, how would i deal with the scope problem of my textfields being inside the scene:show function? &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } --this is my register button local function continueEvent(event) &nbsp;&nbsp; &nbsp;local phase = event.phase &nbsp;&nbsp; &nbsp;if phase == "ended" then &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if emailField.text == "" or passwordField.text == "" or mobileField.text == "" then &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;alert = native.showAlert( "title", "All of the fields must be filled!", {"OK"}, onComplete ) &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;else &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;network.request( "http://cliptest.net16.net/registration\_script.php", "POST", networkListener, params ) &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;end &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return true &nbsp;&nbsp; &nbsp;end end

Can you re-edit this and put your code in the proper code tags. Use the <> button and paste the code into the window (you can highlight the code already typed in and click the <> button too.

edited!

Let’s look at the Corona code:

local function urlencode(str) &nbsp; if (str) then &nbsp;&nbsp;&nbsp; str = string.gsub (str, "\n", "\r\n") &nbsp;&nbsp;&nbsp; str = string.gsub (str, "([^%w])", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function (c) return string.format ("%%%02X", string.byte(c)) end) &nbsp;&nbsp;&nbsp; str = string.gsub (str, " ", "+") &nbsp; end &nbsp; return str&nbsp;&nbsp; &nbsp; end local function networkListener( event ) if ( event.isError ) then print( "Network error: ", event.response ) else print ( "Upload complete!", event.response ) end end local headers = {} headers["Content-Type"] = "application/json" headers["X-API-Key"] = "13b6ac91a2" -- I don't see where you're using this in your PHP script, but it's not an issue to leave it local params = {} params.headers = headers --this is my register button local function continueEvent(event) local phase = event.phase if phase == "ended" then if emailField.text == "" or passwordField.text == "" or mobileField.text == "" then alert = native.showAlert( "title", "All of the fields must be filled!", {"OK"}, onComplete ) else params.body = "email=" .. urlencode(emailField.text) .. "&password=" .. urlencode(passwordField.text) .. "&mobile=" .. urlencode(mobileField.text) network.request( "http://cliptest.net16.net/registration\_script.php", "POST", networkListener, params ) end return true end end

Look at the differences between what I did and what you did, on how I constructed the data for the POST body.

Now, some PHP servers have issues giving you a blank $_POST[] array. You can Google for solutions on that. But your PHP code has a couple of things going on that could crash it too.

\<?php require 'connection.php'; if (!$conn) {die( "Connection failed: " . mysqli\_connect\_error());} echo 'hi'; $email = mysqli\_real\_escape\_string($conn, $\_POST['email']); $password = mysqli\_real\_escape\_string($conn, $\_POST['password']); $mobile = mysqli\_real\_escape\_string($conn, $\_POST['mobile']); $gender = mysqli\_real\_escape\_string($conn, $\_POST['gender']); $query = mysqli\_prepare($conn, "INSERT INTO USER (email, password, mobile, gender) VALUES(?,?,?,?)"); mysqli\_stmt\_bind\_param($query, 'ssss', $email, $password, $mobile); mysqli\_stmt\_execute($query); mysqli\_stmt\_close($query); msqli\_close($conn); ?\>

The line:  echo ‘hi’;  will result is your event.response being the string “hi”.

These two lines:

$query = mysqli_prepare($conn, “INSERT INTO USER (email, password, mobile, gender) VALUES(?,?,?,?)”);
mysqli_stmt_bind_param($query, ‘ssss’, $email, $password, $mobile);

It’s expecting four parameters in the order presented. You appear to be only using three. You never provide gender to this and I expect that mysqli_stmt_bind_param() is failing since it needs a 4th variable.

Finally other than saying “hi” back to your Lua code you never output anything of use. You should output something:

$results = array('success'&nbsp;=\>&nbsp;1); echo( json\_encode( $results ) );

Or something like that.

Thanks for the help Rob! I made the changes to the php script and added the urlencode function to my corona code, but the json table always returns nil, and of course, the database isn’t getting updated.

I added this to the end of my php script (before the query close and connection close):

$user = array(); while(mysqli\_stmt\_fetch($query)){ $user[email] = $email; $user[password] = $password; $user[mobile] = $mobile; $user[gender] = $gender; } echo json\_encode($user);

and my corona code looks like this now (after the corrections you made):

local function urlencode(str) if (str) then str = string.gsub (str, "\n", "\r\n") str = string.gsub (str, "([^%w])", function (c) return string.format ("%%%02X", string.byte(c)) end) str = string.gsub (str, " ", "+") end return str end local function networkListener( event ) if ( event.isError ) then print( "Network error: ", event.response ) else print ( "Upload complete!" ) local myTable = json.decode( event.response ) print (myTable) end end local headers = {} headers["Content-Type"] = "application/json" -- Tell network.request() to get the request body from a file: local params = {} params.headers = headers local function continueEvent(event) local phase = event.phase if phase == "ended" then if emailField.text == "" or passwordField.text == "" or mobileField.text == "" then alert = native.showAlert( "CLIP", "All of the fields must be filled!", {"OK"}, onComplete ) else if (emailField.text:match("[A-Za-z0-9%.%%%+%-]+@[A-Za-z0-9%.%%%+%-]+%.%w%w%w?%w?")) then params.body = "email=" .. urlencode(emailField.text) .. "&password=" .. urlencode(passwordField.text) .. "&mobile=" .. urlencode(mobileField.text) network.request( "http://cliptest.net16.net/registration\_script.php", "POST", networkListener, params ) else alert = native.showAlert( "CLIP", "Invalid email", {"OK"}, onComplete ) end return true end end end

And in the console, the output I get is:

15:04:35.506  Upload complete!
15:04:35.506  nil
 

You may have errors in your PHP script. What happens if you try and call it from a browser (you may have to setup a small form to post the data or switch to GET and do it from the URL?

Rob