REST API security design

Question

I have made an PHP rest api. I want to connect to the API via an IOS and Android app. But I don't know how to secure everything.

I register the device at my database when the app fires for the first time

Table devices:

id random enabled
1  12345  1

Every device has an id and an random. The random value is unique in that table. The actual device receives the id and random value.

What I have right now:

I validate each request at the php side:

private function validateUrl(){
        $url = $_SERVER['REQUEST_URI'];
        $signature = isset($_GET['signature']) ? $_GET["signature"] : null;
        $url = str_replace('&signature=' . $signature, '',$url);
        $url = "" . $url;
        $correctSignature = md5($url . "TNynVX9k2HqYSXnd");

        if($signature != $correctSignature){
            echo die(json_encode([array('status' => "not valid")]));
        }
    }

The request at (in this case) the IOS side:

private func random () -> Int {

    var result = "";

    for _ in 1...3 {
        let randomNumber = arc4random_uniform(99)
        result += String(randomNumber);
    }

    return Int(result)!;
}

private func md5(string string: String) -> String {
    var digest = [UInt8](count: Int(CC_MD5_DIGEST_LENGTH), repeatedValue: 0)
    if let data = string.dataUsingEncoding(NSUTF8StringEncoding) {
        CC_MD5(data.bytes, CC_LONG(data.length), &digest)
    }

    var digestHex = ""
    for index in 0..<Int(CC_MD5_DIGEST_LENGTH) {
        digestHex += String(format: "%02x", digest[index])
    }

    return digestHex
}

func createUrl(url : String) -> String {
    var newUrl = url;
    newUrl += "?&random=\(random())";
    let secret = "TNynVX9k2HqYSXnd"
    let signature = md5(string: newUrl + secret)

    newUrl += "&signature=" + signature;

    return newUrl;
}

This works great but as you see I have an static API key. Something where I have my concerns about. So I thought maybe I can create an API key based on the id and random from my database. Is that more secure?

Something like:

func createUrl(url : String) -> String {
    var newUrl = url;

    let signature = md5(string: [device id here] + [device random here])

    newUrl += "&signature=" + signature;
    newUrl += "&deviceId=" + [device id here];

    return newUrl;
}

And at my PHP side I can get the deviceId property from the url. Compare it to the database, retrieve the id and random value. MD5 them. Compare that to the signature. And when there is an match it's ok. Otherwise not. Is that an solid implementation?

Or in simple terms. Can I replace the api key with the combination of id + random?


Show source
| rest   | security   | swift   | ios   | php   2017-01-07 21:01 1 Answers

Answers ( 1 )

  1. 2017-01-10 02:01

    Looks like you are using the same secret client side and server side, which can be an issue since anyone who has access to the *.apk or *.ipa could disassemble it and find the token, which is pretty easy with open source tools (https://github.com/iBotPeaches/Apktool). Especially on Android where the APK is pretty much a jar with some other assets. Are you generating the random token client side? Since it looks to be an int, that's only 32 bits of entropy, not enough to be secure.

    Usually, the token is created server side rather than client side. There are many different ways of doing this. One is a JSON Web Token (JWT) which basically encodes data like an id or expires data into a token which is signed with a private key. Only the server knows the private key, and thus it's the trusted source for creating them, but others can have access to a public key which can be used to verify the token.

    If you don't want to deal with JWT's and signing, a second option is just opaque tokens that are created server side. The key is a large amount of entropy like a large UUID.

    There is a lot of information on asymmetric algorithms that generate a mathematically linked public/private key pair.

    You can read more here: https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/

◀ Go back