Comparing version 0.5.3 to 0.6.0
@@ -5,2 +5,3 @@ // Load modules | ||
var Cryptiles = require('cryptiles'); | ||
var Sntp = require('sntp'); | ||
var Crypto = require('./crypto'); | ||
@@ -20,2 +21,3 @@ var Utils = require('./utils'); | ||
exports.error = exports.Error = Boom; | ||
exports.sntp = Sntp; | ||
exports.uri = Uri; | ||
@@ -80,8 +82,2 @@ exports.utils = Utils; | ||
* | ||
* ntp - optional hostname of the ntp server used to synchronize time between the client and the server. The | ||
* ntp server name is included when the client's timestamp is stale along with the server's | ||
* current timestamp. This allows browser-based clients to sync their application clock directly | ||
* with the server, while native clients can be smarter about managing time sync and caching | ||
* multiple clock offsets using the ntp server value provided. Defaults to 'pool.ntp.org'. | ||
* | ||
* payload - optional payload for validation. The client calculates the hash value and includes it via the 'hash' | ||
@@ -102,7 +98,6 @@ * header attribute. The server always ensures the value provided has been included in the request | ||
options.timestampSkewSec = options.timestampSkewSec || 60; // 60 seconds | ||
options.ntp = options.ntp || 'pool.ntp.org'; // pool.ntp.org | ||
// Application time | ||
var now = Date.now() + (options.localtimeOffsetMsec || 0); | ||
var now = Utils.now() + (options.localtimeOffsetMsec || 0); | ||
@@ -119,3 +114,3 @@ // Convert node Http request object to a request configuration object | ||
if (!request.authorization) { | ||
return callback(Boom.unauthorized('', 'Hawk', { ts: now, ntp: options.ntp })); | ||
return callback(Boom.unauthorized(null, 'Hawk', { ts: now })); | ||
} | ||
@@ -130,3 +125,3 @@ | ||
if (scheme.toLowerCase() !== 'hawk') { | ||
return callback(Boom.unauthorized('', 'Hawk', { ts: now, ntp: options.ntp })); | ||
return callback(Boom.unauthorized(null, 'Hawk', { ts: now })); | ||
} | ||
@@ -185,3 +180,3 @@ | ||
if (Math.abs((attributes.ts * 1000) - now) > (options.timestampSkewSec * 1000)) { | ||
return callback(Boom.unauthorized('Stale timestamp', 'Hawk', { ts: now, ntp: options.ntp }), null, attributes); | ||
return callback(Boom.unauthorized('Stale timestamp', 'Hawk', { ts: now }), null, attributes); | ||
} | ||
@@ -276,3 +271,3 @@ | ||
var now = Date.now() + (options.localtimeOffsetMsec || 0); | ||
var now = Utils.now() + (options.localtimeOffsetMsec || 0); | ||
@@ -279,0 +274,0 @@ // Check request |
@@ -26,3 +26,3 @@ // Load modules | ||
var now = Date.now() + (options.localtimeOffsetMsec || 0); | ||
var now = Utils.now() + (options.localtimeOffsetMsec || 0); | ||
@@ -36,2 +36,16 @@ // Convert node Http request object to a request configuration object | ||
// Extract bewit | ||
// 1 2 3 4 | ||
var resource = request.url.match(/^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/); | ||
if (!resource) { | ||
return callback(Boom.unauthorized(null, 'Hawk')); | ||
} | ||
// Bewit not empty | ||
if (!resource[3]) { | ||
return callback(Boom.unauthorized('Empty bewit', 'Hawk')); | ||
} | ||
// Verify method is GET | ||
@@ -45,8 +59,6 @@ | ||
// Extract bewit | ||
// No other authentication | ||
// 1 2 3 4 | ||
var resource = request.url.match(/^(\/.*)([\?&])bewit\=([^&$]+)(?:&(.+))?$/); | ||
if (!resource) { | ||
return callback(Boom.unauthorized('Missing bewit', 'Hawk')); | ||
if (request.authorization) { | ||
return callback(Boom.badRequest('Multiple authentications', 'Hawk')); | ||
} | ||
@@ -61,3 +73,3 @@ | ||
// Bewit format: id\exp\mac\ext | ||
// Bewit format: id\exp\mac\ext ('\' is used because it is a reserved header attribute character) | ||
@@ -160,3 +172,3 @@ var bewitParts = bewitString.split('\\'); | ||
var now = Date.now() + (options.localtimeOffsetMsec || 0); | ||
var now = Utils.now() + (options.localtimeOffsetMsec || 0); | ||
@@ -163,0 +175,0 @@ // Check request |
// Load modules | ||
var Hoek = require('hoek'); | ||
var Sntp = require('sntp'); | ||
@@ -86,1 +87,7 @@ | ||
exports.now = function () { | ||
return Sntp.now(); | ||
}; | ||
{ | ||
"name": "hawk", | ||
"description": "HTTP Hawk Authentication Scheme", | ||
"version": "0.5.3", | ||
"version": "0.6.0", | ||
"author": "Eran Hammer <eran@hueniverse.com> (http://hueniverse.com)", | ||
@@ -20,4 +20,5 @@ "contributors": [], | ||
"hoek": "0.0.x", | ||
"boom": "0.0.x", | ||
"cryptiles": "0.0.x" | ||
"boom": "0.1.x", | ||
"cryptiles": "0.0.x", | ||
"sntp": "0.1.x" | ||
}, | ||
@@ -24,0 +25,0 @@ "devDependencies": { |
119
README.md
@@ -6,3 +6,3 @@ ![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png) | ||
Current version: **0.5.3** | ||
Current version: **0.6.0** | ||
@@ -14,3 +14,3 @@ [![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk) | ||
- [**Introduction**](#introduction) | ||
- [Time Synchronization](#time-synchronization) | ||
- [Replay Protection](#replay-protection) | ||
- [Usage Example](#usage-example) | ||
@@ -40,11 +40,26 @@ - [Protocol Example](#protocol-example) | ||
**Hawk** is an HTTP authentication scheme providing methods for making authenticated HTTP requests with | ||
**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with | ||
partial cryptographic verification of the request, covering the HTTP method, request URI, host, and optionally | ||
the request payload. | ||
Similar to the HTTP [Basic access authentication scheme](http://www.ietf.org/rfc/rfc2617.txt), the **Hawk** | ||
scheme utilizes a set of client credentials which include an identifier and key. However, in contrast with | ||
the Basic scheme, the key is never included in authenticated requests but is used to calculate a request MAC | ||
value which is included instead. | ||
Similar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of | ||
client credentials which include a identifier (username) and key (password). Likewise, just as with the Digest scheme, | ||
the key is never included in authenticated requests; instead, it is used to calculate a request MAC value which is | ||
included in its place. | ||
However, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of | ||
replay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less | ||
interaction with the server ("chattiness"). | ||
Also unlike Digest, this scheme is not intended to protect the key itself (called the password in Digest) because | ||
the client and server must both have access to the key material in the clear. | ||
The primary design goals of this scheme are to: | ||
* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources, | ||
* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where to send an authenticated request), and | ||
* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client failure to validate the server's identity as part of its TLS handshake. | ||
In addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using | ||
a query parameter called _bewit_ (leather straps used to attach a tracking device to the leg of a hawk). | ||
The **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server, | ||
@@ -55,38 +70,28 @@ which is beyond the scope of this module. Typically, the shared credentials are established via an initial | ||
The primary design goals of this mechanism are to: | ||
* simplify and improve HTTP authentication for services that are unwilling or unable to employ TLS for every request, | ||
* secure the shared credentials against leakage when sent over a secure channel to the wrong server (e.g., when the client uses some form of dynamic configuration to determine where to send an authenticated request), and | ||
* mitigate the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client failure to validate the server's identity as part of its TLS handshake. | ||
Unlike the HTTP [Digest authentication scheme](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** provides optional | ||
protection against replay attacks which does not require prior interaction with the server. Instead, the client | ||
provides a timestamp and a nonce which the server can use to prevent replay attacks outside a narrow time window. | ||
Also unlike Digest, this mechanism is not intended to protect the key itself (user's password in Digest) because | ||
the client and server must both have access to the key material in the clear. | ||
## Replay Protection | ||
In addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using | ||
a query parameter called _bewit_ (leather straps used to attach a tracking device to the leg of a hawk). | ||
Without replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more | ||
than once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when | ||
making requests; this gives the server enough information to prevent replay attacks. | ||
The nonce is generated by the client, and is a string unique across all requests with the same timestamp and | ||
key identifier combination. | ||
## Time Synchronization | ||
The timestamp enables the server to restrict the validity period of the credentials; requests occuring afterwards | ||
are rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks. | ||
By default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in | ||
translates to a maximum of 2 minutes as the skew can be positive or negative). | ||
When making requests, the client includes a timestamp and nonce in order to enable the server to prevent replay | ||
attacks. The nonce is generated by the client and is a string unique across all requests with the same timestamp and | ||
key identifier combination. Without replay protection, an attacker can use a compromised (but otherwise valid and | ||
authenticated) request more than once, gaining long term access to a protected resource. | ||
Using a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client | ||
clock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types | ||
(e.g. browsers) to deploy NTP, the server provides the client with its current time in response to a bad timestamp or | ||
as part of an authentication challenge. | ||
Including a timestamp with the nonce removes the need to retain an infinite number of nonce values for future checks. | ||
The timestamp enables the server to restrict the time period after which a request with an old timestamp is rejected. | ||
However, this requires the client's clock to be in sync with the server's clock. Unlike other protocols, **Hawk** | ||
requires the client to ensure its clock is in sync. To accomplish that, the server provides the client with its current | ||
time in response to a bad timestamp or as part of a challenge. | ||
There is no expectation that the client will adjust its system clock to match the server (in fact, this would be a | ||
potential attack vector). Instead, the client only uses the server's time to calculate an offset used only | ||
for communications with that particular server. The protocol rewards clients with synchronized clocks by reducing | ||
the number of round trips required to authentication to a single request. | ||
In addition, to increase the protocol scalability for clients communicating with many different servers, the server | ||
provides the name of an NTP server which can be used as a time reference for clock sync with the server. | ||
There is no expectation that the client will adjust its system clock to match the server. In fact, that would be a | ||
potential attack vector on the client. Instead, the client only uses the server's time to calculate an offset used only | ||
for communications with that particular server. | ||
## Usage Example | ||
@@ -159,3 +164,10 @@ | ||
**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local | ||
machine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method. | ||
```javascript | ||
Hawk.sntp.start(); | ||
``` | ||
## Protocol Example | ||
@@ -176,3 +188,3 @@ | ||
HTTP/1.1 401 Unauthorized | ||
WWW-Authenticate: Hawk ts="1353832200", ntp="pool.ntp.org" | ||
WWW-Authenticate: Hawk ts="1353832200" | ||
``` | ||
@@ -221,3 +233,3 @@ | ||
Host: example.com:8000 | ||
Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=" | ||
Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=" | ||
``` | ||
@@ -259,6 +271,20 @@ | ||
Host: example.com:8000 | ||
Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="CBbyqZ/H0rd6nKdg3O9FS5uiQZ5NmgcXUPLut9heuyo=", ext="some-app-ext-data", mac="D0pHf7mKEh55AxFZ+qyiJ/fVE8uL0YgkoJjOMcOhVQU=" | ||
Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="CBbyqZ/H0rd6nKdg3O9FS5uiQZ5NmgcXUPLut9heuyo=", ext="some-app-ext-data", mac="D0pHf7mKEh55AxFZ+qyiJ/fVE8uL0YgkoJjOMcOhVQU=" | ||
``` | ||
It is up to the server if and when it validates the payload for any given request, based solely on it's security policy | ||
and the nature of the data included. | ||
If the payload is available at the time of authentication, the server uses the hash value provided by the client to construct | ||
the normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value | ||
with the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash. | ||
However, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed | ||
at a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value | ||
provided by the client after validating the MAC. | ||
It is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value | ||
included in the header was nor modified. Without calculating the payload hash on the server and comparing it to the value provided | ||
by the client, the payload may be modified by an attacker. | ||
# Single URI Authorization | ||
@@ -411,10 +437,6 @@ | ||
When receiving a request with a bad timestamp, the server provides the client with its current time as well as the name of an | ||
NTP server which can be used as a time reference. The client must never use the time received from the server to adjust its own | ||
clock, and must only use it to calculate an offset for communicating with that particular server. | ||
When receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use | ||
the time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with | ||
that particular server. | ||
In addition, the client must not draw any correlation between the server's time provided via the 'ts' attribute and the current | ||
time at the NTP server indicated via the 'ntp' variable. In other works, the client must not make any conclusion about the NTP | ||
server indicated based on the server response. | ||
### Bewit Limitations | ||
@@ -494,10 +516,3 @@ | ||
### Is the NTP attribute really necessary? | ||
It's a good investment for the future. While clients can use the server time to calculate clock skew, large scale deployment | ||
of clients talking to many servers is going to make this very expensive. Such clients will need to maintain a large data set | ||
of clock offsets, and keep updating it. Instead, the NTP information allows them to keep track of much fewer clocks, especially | ||
when using the default 'pool.ntp.org' service. | ||
# Acknowledgements | ||
@@ -504,0 +519,0 @@ |
@@ -178,3 +178,3 @@ // Load modules | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -197,3 +197,3 @@ expect(err).to.not.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353832234000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -216,3 +216,3 @@ expect(err).to.not.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1357926341000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1357926341000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -235,3 +235,3 @@ expect(err).to.not.exist; | ||
Hawk.authenticate(req, credentialsFunc, { payload: 'body', localtimeOffsetMsec: 1353832234000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { payload: 'body', localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -259,4 +259,4 @@ expect(err).to.exist; | ||
var header = err.toResponse().headers['WWW-Authenticate']; | ||
var ts = header.match(/^Hawk ts\=\"(\d+)\"\, ntp\=\"pool.ntp.org\"\, error=\"Stale timestamp\"$/); | ||
var now = Date.now(); | ||
var ts = header.match(/^Hawk ts\=\"(\d+)\"\, error=\"Stale timestamp\"$/); | ||
var now = Hawk.utils.now(); | ||
expect(parseInt(ts[1], 10)).to.be.within(now - 1, now + 1); | ||
@@ -279,3 +279,3 @@ done(); | ||
var options = { | ||
localtimeOffsetMsec: 1353788437000 - Date.now(), | ||
localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(), | ||
nonceFunc: function (nonce, ts, callback) { | ||
@@ -316,6 +316,6 @@ | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
expect(err).to.exist; | ||
expect(err.toResponse().payload.message).to.equal(''); | ||
expect(err.toResponse().payload.message).to.not.exist; | ||
done(); | ||
@@ -335,3 +335,3 @@ }); | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -356,5 +356,6 @@ expect(err).to.exist; | ||
expect(err).to.exist; | ||
expect(err.isMissing).to.equal(true); | ||
var header = err.toResponse().headers['WWW-Authenticate']; | ||
var ts = header.match(/^Hawk ts\=\"(\d+)\"\, ntp\=\"pool.ntp.org\"$/); | ||
var now = Date.now(); | ||
var ts = header.match(/^Hawk ts\=\"(\d+)\"$/); | ||
var now = Hawk.utils.now(); | ||
expect(parseInt(ts[1], 10)).to.be.within(now - 1, now + 1); | ||
@@ -375,3 +376,3 @@ done(); | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -394,3 +395,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -413,3 +414,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -432,3 +433,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -451,3 +452,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -470,3 +471,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -489,3 +490,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -508,3 +509,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -527,3 +528,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -546,3 +547,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -565,3 +566,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -585,3 +586,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -605,3 +606,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -629,3 +630,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -653,3 +654,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -682,3 +683,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -713,3 +714,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -744,3 +745,3 @@ expect(err).to.exist; | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Date.now() }, function (err, credentials, attributes) { | ||
Hawk.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, attributes) { | ||
@@ -747,0 +748,0 @@ expect(err).to.exist; |
@@ -112,2 +112,20 @@ // Load modules | ||
it('should fail on multiple authentication', function (done) { | ||
var req = { | ||
method: 'GET', | ||
url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ', | ||
host: 'example.com', | ||
port: 8080, | ||
authorization: 'Basic asdasdasdasd' | ||
}; | ||
Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) { | ||
expect(err).to.exist; | ||
expect(err.toResponse().payload.message).to.equal('Multiple authentications'); | ||
done(); | ||
}); | ||
}); | ||
it('should fail on method other than GET', function (done) { | ||
@@ -124,3 +142,3 @@ | ||
var exp = Math.floor(Date.now() / 1000) + 60; | ||
var exp = Math.floor(Hawk.utils.now() / 1000) + 60; | ||
var ext = 'some-app-data'; | ||
@@ -183,3 +201,4 @@ var mac = Hawk.crypto.calculateMac({ | ||
expect(err).to.exist; | ||
expect(err.toResponse().payload.message).to.equal('Missing bewit'); | ||
expect(err.toResponse().payload.message).to.equal('Empty bewit'); | ||
expect(err.isMissing).to.not.exist; | ||
done(); | ||
@@ -202,2 +221,3 @@ }); | ||
expect(err.toResponse().payload.message).to.equal('Invalid bewit encoding'); | ||
expect(err.isMissing).to.not.exist; | ||
done(); | ||
@@ -219,3 +239,4 @@ }); | ||
expect(err).to.exist; | ||
expect(err.toResponse().payload.message).to.equal('Missing bewit'); | ||
expect(err.toResponse().payload.message).to.not.exist; | ||
expect(err.isMissing).to.equal(true); | ||
done(); | ||
@@ -372,3 +393,3 @@ }); | ||
var bewit = Hawk.uri.getBewit(credentials, '/somewhere/over/the/rainbow', 'example.com', 443, 300, { localtimeOffsetMsec: 1356420407232 - Date.now(), ext: 'xandyandz' }); | ||
var bewit = Hawk.uri.getBewit(credentials, '/somewhere/over/the/rainbow', 'example.com', 443, 300, { localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' }); | ||
expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6'); | ||
@@ -375,0 +396,0 @@ done(); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
182498
19
1603
516
4
+ Addedsntp@0.1.x
+ Addedboom@0.1.0(transitive)
+ Addedhoek@0.7.6(transitive)
+ Addedsntp@0.1.4(transitive)
- Removedboom@0.0.2(transitive)
Updatedboom@0.1.x