« index

Coverage for /Users/yunong/workspace/node-restify/lib/plugins/authorization.js : 90%

138 lines | 125 run | 13 missing | 0 partial | 19 blocks | 9 blocks run | 10 blocks missing

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

  // Copyright 2012 Mark Cavage, Inc.  All rights reserved.
  
  var httpSignature = require('http-signature');
  
  var errors = require('../errors');
  
  
  ///--- Globals
  
  var InvalidHeaderError = errors.InvalidHeaderError;
  
  var OPTIONS = {
      algorithms: [
          'rsa-sha1',
          'rsa-sha256',
          'rsa-sha512',
          'dsa-sha1',
          'hmac-sha1',
          'hmac-sha256',
          'hmac-sha512'
      ]
  };
  
  
  ///--- Helpers
  
  function parseBasic(string) {
      var decoded;
      var index;
      var pieces;
  
      decoded = (new Buffer(string, 'base64')).toString('utf8');
      if (!decoded)
          throw new InvalidHeaderError('Authorization header invalid');
  
      index = decoded.indexOf(':');
      if (index === -1) {
          pieces = [decoded];
      } else {
          pieces = [decoded.slice(0, index), decoded.slice(index + 1)];
      }
  
      if (!pieces || typeof (pieces[0]) !== 'string')
          throw new InvalidHeaderError('Authorization header invalid');
  
      // Allows for usernameless authentication
      if (!pieces[0])
          pieces[0] = null;
  
      // Allows for passwordless authentication
      if (!pieces[1])
          pieces[1] = null;
  
      return ({
          username: pieces[0],
          password: pieces[1]
      });
  }
  
  
  function parseSignature(request, options) {
      options = options || {};
      options.algorithms = OPTIONS.algorithms;
      try {
          return (httpSignature.parseRequest(request, options));
      } catch (e) {
          throw new InvalidHeaderError('Authorization header invalid: ' +
              e.message);
      }
  }
  
  
  /**
   * Returns a plugin that will parse the client's Authorization header.
   *
   * Subsequent handlers will see `req.authorization`, which looks like:
   *
   * {
   *   scheme: <Basic|Signature|...>,
   *   credentials: <Undecoded value of header>,
   *   basic: {
   *     username: $user
   *     password: $password
   *   }
   * }
   *
   * `req.username` will also be set, and defaults to 'anonymous'.
   *
   * @return {Function} restify handler.
   * @throws {TypeError} on bad input
   */
  function authorizationParser(options) {
  
      function parseAuthorization(req, res, next) {
          req.authorization = {};
          req.username = 'anonymous';
  
          if (!req.headers.authorization)
              return (next());
  
          var pieces = req.headers.authorization.split(' ', 2);
          if (!pieces || pieces.length !== 2) {
              var e = new InvalidHeaderError('BasicAuth content ' +
                  'is invalid.');
              return (next(e));
          }
  
          req.authorization.scheme = pieces[0];
          req.authorization.credentials = pieces[1];
  
          try {
              switch (pieces[0].toLowerCase()) {
                  case 'basic':
                      req.authorization.basic = parseBasic(pieces[1]);
                      req.username = req.authorization.basic.username;
                      break;
  
                  case 'signature':
                      req.authorization.signature =
                          parseSignature(req, options);
                      req.username =
                          req.authorization.signature.keyId;
                      break;
  
                  default:
                      break;
              }
          } catch (e2) {
              return (next(e2));
          }
  
          return (next());
      }
  
      return (parseAuthorization);
  }
  
  module.exports = authorizationParser;
« index | cover.io