index.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // src/middleware/basic-auth/index.ts
  2. import { HTTPException } from "../../http-exception.js";
  3. import { auth } from "../../utils/basic-auth.js";
  4. import { timingSafeEqual } from "../../utils/buffer.js";
  5. var basicAuth = (options, ...users) => {
  6. const usernamePasswordInOptions = "username" in options && "password" in options;
  7. const verifyUserInOptions = "verifyUser" in options;
  8. if (!(usernamePasswordInOptions || verifyUserInOptions)) {
  9. throw new Error(
  10. 'basic auth middleware requires options for "username and password" or "verifyUser"'
  11. );
  12. }
  13. if (!options.realm) {
  14. options.realm = "Secure Area";
  15. }
  16. if (!options.invalidUserMessage) {
  17. options.invalidUserMessage = "Unauthorized";
  18. }
  19. if (usernamePasswordInOptions) {
  20. users.unshift({ username: options.username, password: options.password });
  21. }
  22. return async function basicAuth2(ctx, next) {
  23. const requestUser = auth(ctx.req.raw);
  24. if (requestUser) {
  25. if (verifyUserInOptions) {
  26. if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
  27. if (options.onAuthSuccess) {
  28. await options.onAuthSuccess(ctx, requestUser.username);
  29. }
  30. await next();
  31. return;
  32. }
  33. } else {
  34. for (const user of users) {
  35. const [usernameEqual, passwordEqual] = await Promise.all([
  36. timingSafeEqual(user.username, requestUser.username, options.hashFunction),
  37. timingSafeEqual(user.password, requestUser.password, options.hashFunction)
  38. ]);
  39. if (usernameEqual && passwordEqual) {
  40. if (options.onAuthSuccess) {
  41. await options.onAuthSuccess(ctx, requestUser.username);
  42. }
  43. await next();
  44. return;
  45. }
  46. }
  47. }
  48. }
  49. const status = 401;
  50. const headers = {
  51. "WWW-Authenticate": 'Basic realm="' + options.realm?.replace(/"/g, '\\"') + '"'
  52. };
  53. const responseMessage = typeof options.invalidUserMessage === "function" ? await options.invalidUserMessage(ctx) : options.invalidUserMessage;
  54. const res = typeof responseMessage === "string" ? new Response(responseMessage, { status, headers }) : new Response(JSON.stringify(responseMessage), {
  55. status,
  56. headers: {
  57. ...headers,
  58. "content-type": "application/json"
  59. }
  60. });
  61. throw new HTTPException(status, { res });
  62. };
  63. };
  64. export {
  65. basicAuth
  66. };