0

Currently, I have the following security measures.

  1. JWT Token using PassportJS per request after login
  2. Rate limiting on just my Login and Register endpoints at the moment
  3. Emailing a user that someone unknown has logged in from a different device

What else could I be doing to secure the backend?

calimses
  • 151
  • 2
  • 14
  • other thing is HTTPS and as long as the token is strong you are doing everything perfectly – Yadu Aug 17 '20 at 09:56
  • other thing is HTTPS and as long as the token is strong you are doing everything perfectly – Yadu Aug 17 '20 at 09:56

2 Answers2

1

Your Current Security Measures

Currently, I have the following security measures.

  1. JWT Token using PassportJS per request after login

Bear in mind that the JWT token only identifies who is in the request, not what is doing the request.

  1. Rate limiting on just my Login and Register endpoints at the moment

Congratulations by having this measure in place, but you should extend it to all endpoints and adjust the rate limit in a per endpoint basis. Try to figure out the normal rate per second/minute for a normal usage and set the rate limit just a little above it, and have monitoring in place to see when you have spikes in requests being blocked due to exceeding the rate limit.

  1. Emailing a user that someone unknown has logged in from a different device

That's a measure that people do not talk about often or even implement, but it's a very important one to ensure your users security. You can enhance it by only allowing that new login happens from a different device by sending an approoval link to the user email.

The Difference Between WHO and WHAT is Accessing the API Server

Before I dive into your question What else could I be doing to secure the backend? I would like to first clear a misconception that usually I find among developers of any seniority, that is about the difference between who and what is accessing an API server.

I wrote a series of articles around API and Mobile security, and in the article Why Does Your Mobile App Need An Api Key? you can read in detail the difference between who and what is accessing your API server, but I will extract here the main takes from it:

The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?

The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.

So think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and think about the what as the software making that request in behalf of the user you have authenticated with the PassportJS JWT token.

Other Security Measures

What else could I be doing to secure the backend?

As you may be aware by now you are lacking measures to allow your backend to attest what is doing the request, because your current measures are centered around the who in the request, that is represented by the PassportJS JWT token.

In order to allow the backend to have more confidence that is indeed receiving requests from what it expects, your mobile app, you need to approach this from both sides, the mobile app and backend.

HMAC - Digitally Sign Requests

So you can start by digitally sign the requests the mobile app does to the backend, and you can see here a simple approach of doing it so in the mobile app:

private fun calculateAPIRequestHMAC(url: URL, authHeaderValue: String): String {

        val secret = JniEnv().getHmacSecret()
        var keySpec: SecretKeySpec

        // Configure the request HMAC based on the demo stage
        when (currentDemoStage) {
            DemoStage.API_KEY_PROTECTION, DemoStage.APPROOV_APP_AUTH_PROTECTION -> {
                throw IllegalStateException("calculateAPIRequestHMAC() not used in this demo stage")
            }
            DemoStage.HMAC_STATIC_SECRET_PROTECTION -> {
                // Just use the static secret to initialise the key spec for this demo stage
                keySpec = SecretKeySpec(Base64.decode(secret, Base64.DEFAULT), "HmacSHA256")
                Log.i(TAG, "CALCULATE STATIC HMAC")
            }
            DemoStage.HMAC_DYNAMIC_SECRET_PROTECTION -> {
                Log.i(TAG, "CALCULATE DYNAMIC HMAC")
                // Obfuscate the static secret to produce a dynamic secret to initialise the key
                // spec for this demo stage
                val obfuscatedSecretData = Base64.decode(secret, Base64.DEFAULT)
                val shipFastAPIKeyData = loadShipFastAPIKey().toByteArray(Charsets.UTF_8)
                for (i in 0 until minOf(obfuscatedSecretData.size, shipFastAPIKeyData.size)) {
                    obfuscatedSecretData[i] = (obfuscatedSecretData[i].toInt() xor shipFastAPIKeyData[i].toInt()).toByte()
                }
                val obfuscatedSecret = Base64.encode(obfuscatedSecretData, Base64.DEFAULT)
                keySpec = SecretKeySpec(Base64.decode(obfuscatedSecret, Base64.DEFAULT), "HmacSHA256")
            }
        }

        Log.i(TAG, "protocol: ${url.protocol}")
        Log.i(TAG, "host: ${url.host}")
        Log.i(TAG, "path: ${url.path}")
        Log.i(TAG, "Authentication: $authHeaderValue")

        // Compute the request HMAC using the HMAC SHA-256 algorithm
        val hmac = Mac.getInstance("HmacSHA256")
        hmac.init(keySpec)
        hmac.update(url.protocol.toByteArray(Charsets.UTF_8))
        hmac.update(url.host.toByteArray(Charsets.UTF_8))
        hmac.update(url.path.toByteArray(Charsets.UTF_8))
        hmac.update(authHeaderValue.toByteArray(Charsets.UTF_8))
        return hmac.doFinal().toHex()
}

The backend verification for the dynamic HMAC is done here:

router.use(function(req, res, next) {


  log.info('---> VALIDATING DYNAMIC HMAC <---')


  let base64_decoded_hmac_secret = Buffer.from(config.SHIPFAST_API_HMAC_SECRET, 'base64')


  // Obfuscate the static secret to produce a dynamic secret to use during HMAC
  // verification for this demo stage
  let obfuscatedSecretData = base64_decoded_hmac_secret
  let shipFastAPIKeyData = new Buffer(config.SHIPFAST_API_KEY)


  for (let i = 0; i < Math.min(obfuscatedSecretData.length, shipFastAPIKeyData.length); i++) {
    obfuscatedSecretData[i] ^= shipFastAPIKeyData[i]
  }


  let obfuscatedSecret = new Buffer(obfuscatedSecretData).toString('base64')
  hmac = crypto.createHmac('sha256', Buffer.from(obfuscatedSecret, 'base64'))


  if (hmacHelpers.isValidHmac(hmac, config, req)) {
    next()
    return
  }


  res.status(400).send()


  return
})

But while this is a good step in the right direction it can be bypassed by reverse engineering the mobile app with a tool like Frida:

Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.

This type of situation can be mitigated by using the Mobile App Attestation concept, and to learn more about it I recommend you to read this answer I gave to the question How to secure an API REST for mobile app?, specially on the sections for Securing the API Server and A Possible Better Solution.

Do you Want to go the Extra Mile?

In any response to a security question I always like to reference the awesome work from the OWASP foundation.

For APIS

OWASP API Security Top 10

The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.

For Mobile Apps

OWASP Mobile Security Project - Top 10 risks

The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.

OWASP - Mobile Security Testing Guide:

The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

Exadra37
  • 5,511
  • 1
  • 20
  • 34
0

OWASP provides a REST Security Cheat Sheet here. https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
Actually there are many security measures that we can mentioning but an option similiar to your list is, If you want to allow users for multi device access to service, another security feature you can add to your project is managing active devices for each user. Users can view log of any active devices and remove any of them.

Afshin
  • 1,083
  • 6
  • 15