#requests #exonum #http-request #blockchain #authentication #http-header #http

nightly exonum-http-get-auth

Authenticate HTTP GET requests in Exonum through AWS-like header signing

1 unstable release

Uses old Rust 2015

0.1.0 Nov 5, 2017

#22 in #exonum

MIT license

7KB
64 lines

exonum-http-get-auth

Authenticate HTTP GET requests in Exonum through AWS-like header signing.

Exonum already features functionality to auth POST, so you can filter the data added to blockchain. This crate allows you to also authenticate reading.

Request validation is based on signing url, method and timestamp (requests decay in 30 sec after signing to prevent replay attacks) and putting the signature into http header.

Usage:

extern crate exonum_http_get_auth;
use exonum_http_get_auth::get_auth::authenticate_request;

Provided authenticate_request() method returns a function to be passed as an argument into the router's get() handler :

router.get("/my_endpoint", authenticate_request(key, my_endpoint), "my_endpoint");

and a little more more generic way in case you want to authenticate multiple requests with the same key:

let auth = |f| authenticate_request(key, f);
router.get("/my_endpoint", auth(my_endpoint), "my_endpoint");

Front-end side:

Proper request should have fields:

  • x-date date in ISO8601 format
  • x-auth 64-byte SHA256 signature of concated url+method+date UTF-8 array (method is always "GET")

Example:

const Exonum = require('exonum-client');
const lib = require('./lib');

function toUTF8Array(str) {
    var utf8 = [];
    for (var i=0; i < str.length; i++) {
        var charcode = str.charCodeAt(i);
        if (charcode < 0x80) utf8.push(charcode);
        else if (charcode < 0x800) {
            utf8.push(0xc0 | (charcode >> 6), 
                      0x80 | (charcode & 0x3f));
        }
        else if (charcode < 0xd800 || charcode >= 0xe000) {
            utf8.push(0xe0 | (charcode >> 12), 
                      0x80 | ((charcode>>6) & 0x3f), 
                      0x80 | (charcode & 0x3f));
        }
        else {
            //only handle chars up to U+FFFF
            utf8.push(0xef, 0xbf, 0xbd); 
        }
    }
    return utf8;
}

const date = new Date().toISOString();
console.log(date);
const method = 'GET';
const address = 'http://127.0.0.1:8000/my_endpoint';

const keys = Exonum.keyPair();

const data = toUTF8Array(address+method+date);

const signature = Exonum.sign(keys, data);

var reqHeaders = new Headers();
reqHeaders.append('x-date', date);
reqHeaders.append('x-auth', signature);

var options = { method: method,
                headers: reqHeaders,
                mode: "cors" };

var authRequest = new Request(address, options);

fetch(authRequest)
    .then(result => {
        console.log(result.json());
    })
    .catch(error => {
         console.log(error);
}); 

Dependencies

~23–33MB
~502K SLoC