Name: js-handler/node_modules/restify/lib/plugins/authorization.js
| 1: | // Copyright 2012 Mark Cavage, Inc. All rights reserved. |
| 2: | |
| 3: | var httpSignature = require('http-signature'); |
| 4: | |
| 5: | var errors = require('../errors'); |
| 6: | |
| 7: | |
| 8: | |
| 9: | ///--- Globals |
| 10: | |
| 11: | var InvalidHeaderError = errors.InvalidHeaderError; |
| 12: | |
| 13: | var OPTIONS = { |
| 14: | algorithms: [ |
| 15: | 'rsa-sha1', |
| 16: | 'rsa-sha256', |
| 17: | 'rsa-sha512', |
| 18: | 'dsa-sha1', |
| 19: | 'hmac-sha1', |
| 20: | 'hmac-sha256', |
| 21: | 'hmac-sha512' |
| 22: | ] |
| 23: | }; |
| 24: | |
| 25: | |
| 26: | |
| 27: | ///--- Helpers |
| 28: | |
| 29: | function parseBasic(string) { |
| 30: | var decoded; |
| 31: | var index; |
| 32: | var pieces; |
| 33: | |
| 34: | decoded = (new Buffer(string, 'base64')).toString('utf8'); |
| 35: | if (!decoded) |
| 36: | throw new InvalidHeaderError('Authorization header invalid'); |
| 37: | |
| 38: | index = decoded.indexOf(':'); |
| 39: | if (index === -1) { |
| 40: | pieces = [decoded]; |
| 41: | } else { |
| 42: | pieces = [decoded.slice(0, index), decoded.slice(index + 1)]; |
| 43: | } |
| 44: | |
| 45: | if (!pieces || typeof (pieces[0]) !== 'string') |
| 46: | throw new InvalidHeaderError('Authorization header invalid'); |
| 47: | |
| 48: | // Allows for usernameless authentication |
| 49: | if (!pieces[0]) |
| 50: | pieces[0] = null; |
| 51: | |
| 52: | // Allows for passwordless authentication |
| 53: | if (!pieces[1]) |
| 54: | pieces[1] = null; |
| 55: | |
| 56: | return ({ |
| 57: | username: pieces[0], |
| 58: | password: pieces[1] |
| 59: | }); |
| 60: | } |
| 61: | |
| 62: | |
| 63: | function parseSignature(request) { |
| 64: | try { |
| 65: | return (httpSignature.parseRequest(request, OPTIONS)); |
| 66: | } catch (e) { |
| 67: | throw new InvalidHeaderError('Authorization header invalid: ' + |
| 68: | e.message); |
| 69: | } |
| 70: | } |
| 71: | |
| 72: | |
| 73: | |
| 74: | /** |
| 75: | * Returns a plugin that will parse the client's Authorization header. |
| 76: | * |
| 77: | * Subsequent handlers will see `req.authorization`, which looks like: |
| 78: | * |
| 79: | * { |
| 80: | * scheme: <Basic|Signature|...>, |
| 81: | * credentials: <Undecoded value of header>, |
| 82: | * basic: { |
| 83: | * username: $user |
| 84: | * password: $password |
| 85: | * } |
| 86: | * } |
| 87: | * |
| 88: | * `req.username` will also be set, and defaults to 'anonymous'. |
| 89: | * |
| 90: | * @return {Function} restify handler. |
| 91: | * @throws {TypeError} on bad input |
| 92: | */ |
| 93: | function authorizationParser() { |
| 94: | |
| 95: | function parseAuthorization(req, res, next) { |
| 96: | req.authorization = {}; |
| 97: | req.username = 'anonymous'; |
| 98: | |
| 99: | if (!req.headers.authorization) |
| 100: | return (next()); |
| 101: | |
| 102: | var pieces = req.headers.authorization.split(' ', 2); |
| 103: | if (!pieces || pieces.length !== 2) { |
| 104: | var e = new InvalidHeaderError('BasicAuth content ' + |
| 105: | 'is invalid.'); |
| 106: | return (next(e)); |
| 107: | } |
| 108: | |
| 109: | req.authorization.scheme = pieces[0]; |
| 110: | req.authorization.credentials = pieces[1]; |
| 111: | |
| 112: | try { |
| 113: | switch (pieces[0].toLowerCase()) { |
| 114: | case 'basic': |
| 115: | req.authorization.basic = parseBasic(pieces[1]); |
| 116: | req.username = req.authorization.basic.username; |
| 117: | break; |
| 118: | |
| 119: | case 'signature': |
| 120: | req.authorization.signature = |
| 121: | parseSignature(req); |
| 122: | req.username = |
| 123: | req.authorization.signature.keyId; |
| 124: | break; |
| 125: | |
| 126: | default: |
| 127: | break; |
| 128: | } |
| 129: | } catch (e2) { |
| 130: | return (next(e2)); |
| 131: | } |
| 132: | |
| 133: | return (next()); |
| 134: | } |
| 135: | |
| 136: | return (parseAuthorization); |
| 137: | } |
| 138: | |
| 139: | module.exports = authorizationParser; |
