Skip to content

Instantly share code, notes, and snippets.

@bill-mfv
Last active March 12, 2019 03:01
Show Gist options
  • Save bill-mfv/aa50780152d687e9d54dd65967efcbb2 to your computer and use it in GitHub Desktop.
Save bill-mfv/aa50780152d687e9d54dd65967efcbb2 to your computer and use it in GitHub Desktop.
Protocol between Frontend and Backend

Protocol between Frontend and Backend

  • Frontend and Backend using the same key
    Example:
    key = 'cdbdb4ff58e66858cba67787312e2e324c4b217e48680d443a42d96496556834ab549f199b5081d2926e644398e6408ba9ed72d96b1119fc7d4474938ee7c0f7';

  • The signature that Frontend send to Backend have format:
    "#{base64_encoded_timestamp}--#{sha256 hash}"

  • In Frontend

    • Using https://www.npmjs.com/package/crypto-js

    • The signature can be created by code: (test it here https://codesandbox.io/s/0oyv4wmrow)

      var HmacSHA256 = require("crypto-js/hmac-sha256");  
      
      var time = new Date().getTime() / 1000;  
      var base64_encoded_timestamp = btoa(time);  
      var key =
        "cdbdb4ff58e66858cba67787312e2e324c4b217e48680d443a42d96496556834ab549f199b5081d2926e644398e6408ba9ed72d96b1119fc7d4474938ee7c0f7";  
      
      var sha256_hash = HmacSHA256(base64_encoded_timestamp, key);  
      var signature = base64_encoded_timestamp + "--" + sha256_hash;  
      
      document.getElementById("app").innerHTML = signature;  
  • Send the request to Backend
    signature=[$base64_encoded_timestamp]--[$sha256_hash]

  • In Backend

    • Backend get the params[signature] to verify.
    • First step is getting the time (using '--' as separator), decode it and compare the time to the Time.now.utc in server. If the different between 2 times is less than 2 minutes, process next step. Otherwise, return { success: false, message: 'Invalid Timestamp' }.
    • Next step is using key to verify the signature. If fail, return { success: false, message: 'Invalid Signature' }.
    • If the request passes 2 steps above, it's a valid request and the API will return approriate data.
    def verify_signature(signature)   
      secret   = 'cdbdb4ff58e66858cba67787312e2e324c4b217e48680d443a42d96496556834ab549f199b5081d2926e644398e6408ba9ed72d96b1119fc7d4474938ee7c0f7'   
      verifier = ActiveSupport::MessageVerifier.new(secret, serializer: JSON, digest: "SHA256")  
    
      sig  = signature
      time = Base64.decode64(sig.split('--').first).to_i rescue nil
    
      if time && (Time.now.utc.to_i - time.to_i < 2.minutes)
        verifier.verify(signature)
        return {success: true}
      else
        puts 'Invalid Timestamp'
        return { success: false, message: 'Invalid Timestamp', status: "error" }
      end
    
    rescue ActiveSupport::MessageVerifier::InvalidSignature
      puts 'Invalid Signature'
      return { success: false, message:  'Invalid Signature', status: "error"  }
    end 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment