Skip to content
This repository has been archived by the owner on Apr 5, 2024. It is now read-only.

Commit

Permalink
Async, refactor api. Closes #217
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Oct 26, 2017
1 parent d251edf commit f72cdea
Show file tree
Hide file tree
Showing 18 changed files with 1,305 additions and 2,361 deletions.
53 changes: 28 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<img align="right" src="https://raw.github.com/hueniverse/hawk/master/images/logo.png" /> **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial
HTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz).

Current version: **6.x**
Current version: **7.x**

Note: 6.x, 5.x, 4.x, 3.x, and 2.x are the same exact protocol as 1.1. The version increments reflect changes in the node API.
Note: the protocol has not changed since version 1.1. The version increments reflect changes in the node API.

[![Build Status](https://travis-ci.org/hueniverse/hawk.svg?branch=master)](https://travis-ci.org/hueniverse/hawk)

Expand Down Expand Up @@ -105,40 +105,39 @@ const Hawk = require('hawk');

// Credentials lookup function

const credentialsFunc = function (id, callback) {
const credentialsFunc = function (id) {

const credentials = {
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
algorithm: 'sha256',
user: 'Steve'
};

return callback(null, credentials);
return credentials;
};

// Create HTTP server

const handler = function (req, res) {
const handler = async function (req, res) {

// Authenticate incoming request

Hawk.server.authenticate(req, credentialsFunc, {}, (err, credentials, artifacts) => {
const ( credentials, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);

// Prepare response
// Prepare response

const payload = (!err ? `Hello ${credentials.user} ${artifacts.ext}` : 'Shoosh!');
const headers = { 'Content-Type': 'text/plain' };
const payload = (!err ? `Hello ${credentials.user} ${artifacts.ext}` : 'Shoosh!');
const headers = { 'Content-Type': 'text/plain' };

// Generate Server-Authorization response header
// Generate Server-Authorization response header

const header = Hawk.server.header(credentials, artifacts, { payload, contentType: headers['Content-Type'] });
headers['Server-Authorization'] = header;
const header = Hawk.server.header(credentials, artifacts, { payload, contentType: headers['Content-Type'] });
headers['Server-Authorization'] = header;

// Send the response back
// Send the response back

res.writeHead(!err ? 200 : 401, headers);
res.end(payload);
});
res.writeHead(!err ? 200 : 401, headers);
res.end(payload);
};

// Start server
Expand Down Expand Up @@ -171,8 +170,8 @@ const requestOptions = {

// Generate Authorization request header

const header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });
requestOptions.headers.Authorization = header.field;
const { header } = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });
requestOptions.headers.Authorization = header;

// Send authenticated request

Expand Down Expand Up @@ -385,25 +384,29 @@ const Hawk = require('hawk');

// Credentials lookup function

const credentialsFunc = function (id, callback) {
const credentialsFunc = function (id) {

const credentials = {
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
algorithm: 'sha256'
};

return callback(null, credentials);
return credentials;
};

// Create HTTP server

const handler = function (req, res) {

Hawk.uri.authenticate(req, credentialsFunc, {}, (err, credentials, attributes) => {

res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });
res.end(!err ? 'Access granted' : 'Shoosh!');
});
try {
const { credentials, attributes } = await Hawk.uri.authenticate(req, credentialsFunc);
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Access granted');
}
catch (err) {
res.writeHead(401, { 'Content-Type': 'text/plain' });
res.end('Shoosh!');
}
};

Http.createServer(handler).listen(8000, 'example.com');
Expand Down
18 changes: 9 additions & 9 deletions dist/browser.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/*
HTTP Hawk Authentication Scheme
Copyright (c) 2012-2016, Eran Hammer <eran@hammer.io>
Copyright (c) 2012-2017, Eran Hammer <eran@hammer.io>
BSD Licensed
*/

Expand All @@ -22,14 +22,14 @@ hawk.client = {
uri: 'http://example.com/resource?a=b' or object generated by hawk.utils.parseUri()
method: HTTP verb (e.g. 'GET', 'POST')
options: {
// Required
credentials: {
// Required
credentials: {
id: 'dh37fgj492je',
key: 'aoijedoaijsdlaksjdl',
algorithm: 'sha256' // 'sha1', 'sha256'
},
// Optional
ext: 'application-specific', // Application specific data sent via the ext attribute
// Optional
ext: 'application-specific', // Application specific data sent via the ext attribute
timestamp: Date.now() / 1000, // A pre-calculated timestamp in seconds
nonce: '2334f34f', // A pre-generated nonce
localtimeOffsetMsec: 400, // Time offset to sync with server time (ignored if timestamp provided)
Expand Down Expand Up @@ -125,15 +125,15 @@ hawk.client = {
/*
uri: 'http://example.com/resource?a=b'
options: {
// Required
credentials: {
// Required
credentials: {
id: 'dh37fgj492je',
key: 'aoijedoaijsdlaksjdl',
algorithm: 'sha256' // 'sha1', 'sha256'
},
ttlSec: 60 * 60, // TTL in seconds
// Optional
ext: 'application-specific', // Application specific data sent via the ext attribute
// Optional
ext: 'application-specific', // Application specific data sent via the ext attribute
localtimeOffsetMsec: 400 // Time offset to sync with server time
};
*/
Expand Down
60 changes: 32 additions & 28 deletions example/usage.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,38 @@ const internals = {

// Credentials lookup function

const credentialsFunc = function (id, callback) {
const credentialsFunc = function (id) {

return callback(null, internals.credentials[id]);
return internals.credentials[id];
};


// Create HTTP server

const handler = function (req, res) {
const handler = async function (req, res) {

Hawk.server.authenticate(req, credentialsFunc, {}, (err, credentials, artifacts) => {
try {
const { credentials, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);

const payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
const payload = 'Hello ' + credentials.user + ' ' + artifacts.ext;
const headers = {
'Content-Type': 'text/plain',
'Server-Authorization': Hawk.server.header(credentials, artifacts, { payload, contentType: 'text/plain' })
};

res.writeHead(!err ? 200 : 401, headers);
res.writeHead(200, headers);
res.end(payload);
});
}
catch (err) {
const payload = 'Shoosh!';
const headers = {
'Content-Type': 'text/plain',
'Server-Authorization': Hawk.server.header(err.credentials, err.artifacts, { payload, contentType: 'text/plain' })
};

res.writeHead(401, headers);
res.end(payload);
}
};

Http.createServer(handler).listen(8000, '127.0.0.1');
Expand All @@ -63,30 +74,23 @@ Request('http://127.0.0.1:8000/resource/1?b=1&a=2', (err, response, body) => {

// Send authenticated request

credentialsFunc('dh37fgj492je', (err, credentials) => {
const credentials = credentialsFunc('dh37fgj492je');
const header = Hawk.client.header('http://127.0.0.1:8000/resource/1?b=1&a=2', 'GET', { credentials, ext: 'and welcome!' });
const options = {
uri: 'http://127.0.0.1:8000/resource/1?b=1&a=2',
method: 'GET',
headers: {
authorization: header.header
}
};

Request(options, (err, response, body) => {

if (err) {
process.exit(1);
}

const header = Hawk.client.header('http://127.0.0.1:8000/resource/1?b=1&a=2', 'GET', { credentials, ext: 'and welcome!' });
const options = {
uri: 'http://127.0.0.1:8000/resource/1?b=1&a=2',
method: 'GET',
headers: {
authorization: header.field
}
};

Request(options, (err, response, body) => {

if (err) {
process.exit(1);
}

const isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });
console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
process.exit(0);
});
const isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });
console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
process.exit(0);
});

35 changes: 11 additions & 24 deletions lib/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/*
HTTP Hawk Authentication Scheme
Copyright (c) 2012-2016, Eran Hammer <eran@hammer.io>
Copyright (c) 2012-2017, Eran Hammer <eran@hammer.io>
BSD Licensed
*/

Expand Down Expand Up @@ -47,19 +47,13 @@ hawk.client = {

header: function (uri, method, options) {

const result = {
field: '',
artifacts: {}
};

// Validate inputs

if (!uri || (typeof uri !== 'string' && typeof uri !== 'object') ||
!method || typeof method !== 'string' ||
!options || typeof options !== 'object') {

result.err = 'Invalid argument type';
return result;
throw new Error('Invalid argument type');
}

// Application time
Expand All @@ -74,13 +68,11 @@ hawk.client = {
!credentials.key ||
!credentials.algorithm) {

result.err = 'Invalid credentials object';
return result;
throw new Error('Invalid credentials');
}

if (hawk.crypto.algorithms.indexOf(credentials.algorithm) === -1) {
result.err = 'Unknown algorithm';
return result;
throw new Error('Unknown algorithm');
}

// Parse URI
Expand All @@ -104,8 +96,6 @@ hawk.client = {
dlg: options.dlg
};

result.artifacts = artifacts;

// Calculate payload hash

if (!artifacts.hash &&
Expand All @@ -131,9 +121,7 @@ hawk.client = {
(artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
}

result.field = header;

return result;
return { artifacts, header };
},

// Generate a bewit value for a given URI
Expand Down Expand Up @@ -168,7 +156,7 @@ hawk.client = {
typeof options !== 'object' ||
!options.ttlSec) {

return '';
throw new Error('Invalid inputs');
}

options.ext = (options.ext === null || options.ext === undefined ? '' : options.ext); // Zero is valid value
Expand All @@ -185,11 +173,11 @@ hawk.client = {
!credentials.key ||
!credentials.algorithm) {

return '';
throw new Error('Invalid credentials');
}

if (hawk.crypto.algorithms.indexOf(credentials.algorithm) === -1) {
return '';
throw new Error('Unknown algorithm');
}

// Parse URI
Expand Down Expand Up @@ -318,7 +306,7 @@ hawk.client = {
message === null || message === undefined || typeof message !== 'string' ||
!options || typeof options !== 'object') {

return null;
throw new Error('Invalid inputs');
}

// Application time
Expand All @@ -333,12 +321,11 @@ hawk.client = {
!credentials.key ||
!credentials.algorithm) {

// Invalid credential object
return null;
throw new Error('Invalid credentials');
}

if (hawk.crypto.algorithms.indexOf(credentials.algorithm) === -1) {
return null;
throw new Error('Unknown algorithm');
}

// Calculate signature
Expand Down
Loading

0 comments on commit f72cdea

Please sign in to comment.