You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
2.3 KiB

  1. /*!
  2. * basic-auth
  3. * Copyright(c) 2013 TJ Holowaychuk
  4. * Copyright(c) 2014 Jonathan Ong
  5. * Copyright(c) 2015-2016 Douglas Christopher Wilson
  6. * MIT Licensed
  7. */
  8. 'use strict'
  9. /**
  10. * Module dependencies.
  11. * @private
  12. */
  13. var Buffer = require('safe-buffer').Buffer
  14. /**
  15. * Module exports.
  16. * @public
  17. */
  18. module.exports = auth
  19. module.exports.parse = parse
  20. /**
  21. * RegExp for basic auth credentials
  22. *
  23. * credentials = auth-scheme 1*SP token68
  24. * auth-scheme = "Basic" ; case insensitive
  25. * token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"="
  26. * @private
  27. */
  28. var CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/
  29. /**
  30. * RegExp for basic auth user/pass
  31. *
  32. * user-pass = userid ":" password
  33. * userid = *<TEXT excluding ":">
  34. * password = *TEXT
  35. * @private
  36. */
  37. var USER_PASS_REGEXP = /^([^:]*):(.*)$/
  38. /**
  39. * Parse the Authorization header field of a request.
  40. *
  41. * @param {object} req
  42. * @return {object} with .name and .pass
  43. * @public
  44. */
  45. function auth (req) {
  46. if (!req) {
  47. throw new TypeError('argument req is required')
  48. }
  49. if (typeof req !== 'object') {
  50. throw new TypeError('argument req is required to be an object')
  51. }
  52. // get header
  53. var header = getAuthorization(req)
  54. // parse header
  55. return parse(header)
  56. }
  57. /**
  58. * Decode base64 string.
  59. * @private
  60. */
  61. function decodeBase64 (str) {
  62. return Buffer.from(str, 'base64').toString()
  63. }
  64. /**
  65. * Get the Authorization header from request object.
  66. * @private
  67. */
  68. function getAuthorization (req) {
  69. if (!req.headers || typeof req.headers !== 'object') {
  70. throw new TypeError('argument req is required to have headers property')
  71. }
  72. return req.headers.authorization
  73. }
  74. /**
  75. * Parse basic auth to object.
  76. *
  77. * @param {string} string
  78. * @return {object}
  79. * @public
  80. */
  81. function parse (string) {
  82. if (typeof string !== 'string') {
  83. return undefined
  84. }
  85. // parse header
  86. var match = CREDENTIALS_REGEXP.exec(string)
  87. if (!match) {
  88. return undefined
  89. }
  90. // decode user pass
  91. var userPass = USER_PASS_REGEXP.exec(decodeBase64(match[1]))
  92. if (!userPass) {
  93. return undefined
  94. }
  95. // return credentials object
  96. return new Credentials(userPass[1], userPass[2])
  97. }
  98. /**
  99. * Object to represent user credentials.
  100. * @private
  101. */
  102. function Credentials (name, pass) {
  103. this.name = name
  104. this.pass = pass
  105. }