mozilla / hawk Goto Github PK
View Code? Open in Web Editor NEWINACTIVE - HTTP Holder-Of-Key Authentication Scheme
License: Other
INACTIVE - HTTP Holder-Of-Key Authentication Scheme
License: Other
It doesn't look like the bewit supports the app
and dlg
parameters. Is there a reason for this?
E.g.,
Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data",
When I run npm test
, the unit tests all pass, but then it fails with a coverage message.
$ npm test
> [email protected] test c:\Documents and Settings\apenneba\Desktop\src\hawk
> make test-cov
node node_modules/lab/bin/lab -r threshold -t 100
..................................................
..................................................
................
116 tests complete (306 ms)
Coverage: 0.00%
Code coverage below threshold: 0.00 < 100
make: *** [test-cov] Error 1
npm ERR! Test failed. See above for more details.
npm ERR! not ok code 0
Needed for protecting the ts with a server-generated mac.
in the example you send the authorization data like this
{"authorization":"Hawk id=\"dh37fgj492je\", ts=\"1360868338\", nonce=\"MTU2LD\", ext=\"and welcome!\", mac=\"+GU8is0px4MPjKbPxuJrlYjA5/ZwX/dD3o6vClALpYA=\"",...}
But isn't the 'id' really an internal user-id in a database.
Why not provide the username instead and then lookup the user-id serverside?
All the examples shows how to use hawk as a handler for http.createServer()
, then the authentication function uses the request object to validate header or bewit but we don't know what hawks expect from the request object.
I have seen that express.js for instance change the url property while keeping the original url in originalUrl
thus breaking the authentication.
It will be nice to have at least a section in the readme that mentions what things hawk expect from the request object, what properties and in what format.
Few I can think of:
The intro dances around the question of whether this is intended for browser, non-browser or both uses.
When comparing to Basic, would be good to (even parenthetically) use the terms "username" and "password", as that's what most of the planet understands. F'ing crypto geeks.
The big win of Hawk over Digest is that the client is responsible for nonce generation, so it's less chatty and stateful. I think you should play that up more.
I actually read it through to the end :)
kinda need browser code in order to sign from most clients :)
There appears to be a mismatch between the code and the docs regarding the inclusion of the credential's id in the normalized string:
I'd like to store salted credential keys in my users database is this possible or does Hawk require unsalted keys only ?
I'm having a problem related to the way utils.parseHost guess the port number:
https://github.com/hueniverse/hawk/blob/master/lib/utils.js#L57
I'm generating links with port 443, because my link looks like https://url/blabla but my application runs behind a reverse proxy on "http" and my reverse proxy handles https.
Right now it uses req.connection.encrypted is false so it uses 80, i think we can thrust x-forwarded-proto
.
It's special, and it's easy to canonicalise.
I'm having issues with passing complete urls from the framework I'm trying to integrate Hawk into. To make Hawk authentication work in this scenario I have to skip the trailing '?'.
There was a note about that in the source. What are the implications of skipping the url options part?
Hi there!
We started using Hapi for our REST server and thought we might give Hawk a go for our authentification. I spent a little bit of time battling with a browser implementation of the Hawk scheme and I got this working: https://github.com/MathieuLoutre/hawk-browser-client
It's only a draft, but all the current client unit tests of Hawk are passing. It's definitely not maintainable in its current state and makes use of rewritten/extracted bits of code from the different libraries Hawk makes use of. It's basically a port of the current client code, but with libraries that can be used in the browser (minus the NTP stuff).
I figured it might help newcomers.
Isn't this just OAuth 2.0 Message Authentication Code (MAC) Tokens without section (5) Use with OAuth 2.0? Is there some meaningful difference that I have overlooked?
Hi!
I hope this is an appropriate channel to ask this question. I'm trying to figure out what the benefits are of Hawk over HTTP digest.
The only I really see, is the usage of sha-256 over md5.
Is that correct, or is there more to it?
Some spec text about the size of the window would be nice, even if it's just a mention that the default is 60 seconds in your implemenation.
Also, guidance that under certain limits, they're going to start seeing issues even with good clock sync; e.g., a one-second window will cause problems with mobile, Australia, etc. Might be good to recommend a minimum (5 or 10 seconds?).
Hi Eran,
I ported your implementation to .NET. It's available here, https://github.com/pcibraro/hawknet
Thanks
Pablo.
Unless I'm mistaken, the hash
token in the Authorization header is optional, yet the server test indicates that it's required.
At current there is an assumption that the client and server both agree on the version of Hawk the are communicating with. For the future it would help if the protocol version was sent as part of the authentication header and bewit so that the server can handle multiple versions of the protocol.
Hey Eran,
I've made a PHP implementation of Hawk https://github.com/alexbilbie/PHP-Hawk which you might be interested in.
I've tried to follow the README and your code example as closely as I can.
What do you think?
Another Java port of Hawk is here: https://github.com/algermissen/hawkj.
Depends on #11
… it currently isn't (https://github.com/hueniverse/hawk/blob/master/lib/utils.js#L45).
Thanks!
In the browser plugin, the NTP offset is calculated and stored in memory. On page reload, this information would be lost. If this information is stored in LocalStorage for instance and retrieved on first execution of the script and used again.
For testing purposes, a library like node-localstorage could be used.
I could have a go and submit a pull request if it's interesting.
I'm working on a PyHawk, a library compatible with Hawk 0.13.
It seems to working for client, server, and bewit urls.
API isn't finalized, but otherwise I'd love some feedback and/or testers over in that repo.
Aside - A Hawk validation service would be awesome to test compliance. I'm using your usage.js
in this fashion, but it doesn't cover a wide range of inputs and outputs.
Thanks for an awesome project!
Say the server has the public key of a client. Is it possible to use hawk with pki without introducing any extra round-trips (i.e. to establish a shared secret)?
While writing compatibility tests for my Java port, I have problems with the payload hashing in test case
'should return a valid authorization header (sha1)'
AFAIU the payload normalized string will be
"hawk.1.payload\ntext/plain\nsomething to write about"
and the test expects the sha1 hash to be
bsvY3IfUllw6V5rvk4tStEvpBhE=
However, my Java test ends up with the hash
9LxQVpfaAgyiyNeOgD8TEKP6RnM=
I expected the error to be on my side (though the sha256 tests work fine) but verifying with an online hash tool confirmed my value (being a hex of "f4bc505697da020ca2c8d78e803f1310a3fa4673".
Any idea what might cause the difference or what I am doing wrong?
My test is here https://github.com/algermissen/hawkj/blob/master/src/test/java/net/jalg/hawkj/HawkCompatibilityTest.java#L42
Jan
When used in hapi:
https://github.com/spumko/hapi/blob/master/lib/auth/hawk.js#L63
It would be better if instead of creating a local copy of the payload to generate the pre-response hash, we could get a hash object and update it with the chunks.
In a server environment you always sync the OS clock using NTP.
So having this extra mechanism for time synchronization seems a little excessive.
Besides it makes the library more difficult to port. :)
We are thinking of using Hawk and use the authoirzation via the querystring instead of the header (we want to embed ready-to-use "next" links for paging as part of our API responses). Our HTTP endpoints are all TLS protected.
This would require to change a bit the library to try with the header first and if not, try with a querystring.
Do you think that makes sense?
Nice and simple implementation btw!
Do you really think this is necessary? I.e., are we living in a world where different well-run NTP servers can be even a few seconds out of sync? How will this actually be useful?
Looking at 0.5 and the payload hash, is there a reason to have it in the authentication header? Seems like the server-side process for authentication should be:
And this process doesn't need the client-side payload hash.
Of course, there does need to be some way for the server to know if the request's MAC was calculated with a payload hash so that the server knows what to do, but sending the payload hash in the authentication header seems like overkill to me. Thoughts?
You don't say anything about whether it's OK to reuse a nonce, or whether the server should check them.
My .02 - require clients to use a new nonce for each request, within a given time period, and let servers decide if they want to enforce it.
I'm working on a Java implementation of Hawk. Currently appears to be compliant with 0.1.0.
The repository is at https://github.com/wealdtech/hawk
It's generally a good practice to "tag" messages with a constant that identifies which message in the protocol the sender thinks it's sending. In hawk, that would mean adding a constant string to the beginning of the stuff you're HMACing. For example, you could add the string:
Hawk authentication
or whatever you like to "name" that message. The idea is that this helps prevent the message from being re-used in another, surprising context. Similarly, you might want to use a different tag for the bewit HMACs. Perhaps something like "Hawk bewit".
Of course, the receiver needs to verify that the message it receives contains the proper tag.
This issue is just about good cryptographic hygiene and unlikely to represent an actual weakness in the protocol.
Does it make sense to include the HTTP status code of the response in the response MAC? It seems like it's the main component of the response that can be tampered with on an untrusted connection.
I've been looking at your answer to issue 24, and not sure what you're saying in your second paragraph. Are you suggesting that if the payload is not available then Hawk should trust the hash passed in for initial authentication and then hope that somewhere down the line the hash is validated?
I don't see any good coming from sending the hash; at best the server will ignore it as it calculates its own; at worst it will use it without confirming it (either throw laziness/misunderstanding or because the payload is unavailable). Seems to me that it is just inviting implementations to authenticate successfully when they shouldn't.
oss/hawk - [master] » make test
domain.js:66
throw er;
^
ReferenceError: setImmediate is not defined
at Object.internals.protect (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:235:5)
at internals.executeTests (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:178:19)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:128:13)
at Object.async.eachSeries (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:144:9)
at Object.internals.executeTests (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:173:11)
at exports.execute (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:137:27)
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:545:21)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:221:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:128:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:139:25)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:223:17)
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:550:34)
at internals.executeDeps (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:164:9)
at Object.async.eachSeries (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:124:20)
at Object.internals.executeDeps (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:159:11)
at exports.execute (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:133:27)
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:545:21)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:221:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:128:13)
at async.eachSeries (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:144:9)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:220:9)
at Object.doSeries [as mapSeries] (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:210:23)
at Object.async.series (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:543:19)
at exports.execute (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:130:15)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:128:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:139:25)
at exports.execute (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:146:13)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:226:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:136:25)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:223:17)
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:550:34)
at internals.executeDeps (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:164:9)
at Object.async.eachSeries (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:124:20)
at Object.internals.executeDeps (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:159:11)
at /Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:141:27
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:545:21)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:221:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:128:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:139:25)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:223:17)
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:550:34)
at internals.executeTests (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:198:9)
at Object.async.eachSeries (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:124:20)
at Object.internals.executeTests (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:173:11)
at exports.execute (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:137:27)
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:545:21)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:221:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:128:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:139:25)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:223:17)
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:550:34)
at internals.executeDeps (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:164:9)
at Object.async.eachSeries (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:124:20)
at Object.internals.executeDeps (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:159:11)
at exports.execute (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:133:27)
at async.series.results (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:545:21)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:221:13)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:128:13)
at async.eachSeries (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:144:9)
at _asyncMap (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:220:9)
at Object.doSeries [as mapSeries] (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:210:23)
at Object.async.series (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:543:19)
at exports.execute (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:130:15)
at async.eachSeries.iterate (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:128:13)
at Object.async.eachSeries (/Users/jfroma/Projects/oss/hawk/node_modules/lab/node_modules/async/lib/async.js:144:9)
at Object.exports.execute (/Users/jfroma/Projects/oss/hawk/node_modules/lab/lib/execute.js:128:11)
at Object.<anonymous> (/Users/jfroma/Projects/oss/hawk/node_modules/lab/bin/lab:5:9)
at Module._compile (module.js:449:26)
at Object.Module._extensions..js (module.js:467:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.runMain (module.js:492:10)
at process.startup.processNextTick.process._tickCallback (node.js:245:9)
make: *** [test] Error 1
oss/hawk - [master] » node --version
v0.8.23
I guess this version of node doesn't have setImmediate
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.