Home

Awesome

cookie-auth

simple http authentication/authorization that uses cookies intsead of passwords.

Works exactly like tickets do when you go to a movie theater or catch a bus. First you get a ticket, in the form of a url, which can be emailed to you. Then that ticket is redeemed, you request that url and a cookie is written with the response, like the ticket being torn when you enter the theater. Now that cookie shows you are authorized to use the website, like the ticket stub shows you are authorized to watch the movie.

Example

ticket-auth just encapsulates the logic around tickets, but doesn't handle sending the tickets to users (i.e. via email)

  var Tickets = require('ticket-auth')

  //initialize database
  var Level = require('level')
  var SubLevel = require('level-sublevel')
  var db = SubLevel(level(path, {valueEncoding: 'json'}))

  //create Tickets instance
  var auth = Tickets(db)

  //a resource can be any string.
  var resource = 'test resoruce'

  //create a ticket to a resoruce
  auth.create(resource, function (err, ticket) {
    //redeem that ticket into a ticket_stub (which is a cookie)
    auth.redeem(ticket, function (err, ticket_stub) {
      //check which resource a ticket_stub accesses
      auth.check(ticket_stub, function (err, _resource) {
        assert.equal(_resource, resource)
      })
    })
  })

here is an example of redeeming a ticket.

  var Tickets = require('ticket-auth')

  //initialize database
  var Level = require('level')
  var SubLevel = require('level-sublevel')
  var db = SubLevel(level(path, {valueEncoding: 'json'}))

  //create Tickets instance
  var auth = Tickets(db)

  var Tiny = require('tiny-route') //router
  var Stack = require('stack') //middleware

  //here is the actual http server!

  require('http').createServer(Stack(
    //url for redeeming a ticket. /redeem/<ticket_code>
    Tiny.get(/^\/redeem\/([0-9a-f]+)/, function (req, res, next) {
      api.auth.redeem(req.params[0], function (err, cookie) {
        if(err) return next(err)
        //ticket is redeemed! set it as a cookie, 
        res.setHeader('Set-Cookie', cookie)
        res.setHeader('Location', '/') //redirect to the login page.
        res.statusCode = 303
        res.end()
      })
    }),
    function (req, res) {
    })
  ).listen(8000)

testing with curl

note, to make curl work with cookies must set a "cookie jar" it seems: -c file sets the file to write to, and -b file sets the file to write to. You'd think you'd want those both to be the same file! The man page is not clear about this at all.

curl localhost:8000 -c ./jar -b ./jar

the man page says that -c should work, but it only seems to write the jar but not read it! once the cookie is written, you can use -b or --cookie

but that doesn't make sense because there isn't even a b in cookie.

what are "cookies": crash course

A cookie is always key=value and has "attributes" that tell the browser what to do. you need Expires={date} and Path=/.

Without Expires set in the future, the cookie will be a "session cookie" and will expire after the browser exits.

Without Path=/ the browser will only send the cookie on the path that it got it from.

Authorization uses "cookies". Cookies are something delicious you eat, so it really doesn't make any sense to call things used for authentication "cookies", especially when those things behave a lot like a familiar ticket and ticket stub, as is familiar to people who have ridden a bus or gone to the movies.

first a "ticket" is created. this is a high entropy (unguessable) token.

node index.js auth.create <resource>
1d67c0e114b10dc9cc96ea9cd2966f76c42539db

in this case, <resource> should probably be an email address. this token would be emailed to the user, embedded in a link back to the server.

http://localhost:8000/redeem/1d67c0e114b10dc9cc96ea9cd2966f76c42539db the server creates a cookie and sends it to you in the response, which is also a redirect to the rest of the app (though it could easily be a redirect to edit your newly created profile)

This is exactly like tearing off the ticket and giving you back the ticket stub when you enter the theater. Possession of the ticket stub shows you are authorized to see the movie.

To can test this using curl


curl localhost:8000/redeem/1d67c0e114b10dc9cc96ea9cd2966f76c42539db -c jar -b jar -v
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /redeem/1d67c0e114b10dc9cc96ea9cd2966f76c42539db HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 200 OK
* Replaced cookie cookie="437734b0886caf51a8961b1033abb392b07333c1" for domain localhost, path /, expire 1491397335
< Set-Cookie: cookie=437734b0886caf51a8961b1033abb392b07333c1;Path=/;Expires=Wed Apr 05 2017 13:02:15 GMT+1200 (NZST)FirstPartyOnly;HttpOnly;
< Location: /
< Date: Tue, 05 Apr 2016 01:02:15 GMT
< Connection: keep-alive
< Content-Length: 0
< 
* Connection #0 to host localhost left intact

note that curl can be quite finnecky about using cookies and to both write and read cookies you need to use -c jar -b jar arguments where jar is the "cookie jar"

License

MIT