basic_auth.d 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /**
  2. Implements HTTP Basic Auth.
  3. Copyright: © 2012 Sönke Ludwig
  4. License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
  5. Authors: Sönke Ludwig
  6. */
  7. module vibe.http.auth.basic_auth;
  8. import vibe.http.server;
  9. import vibe.core.log;
  10. import std.base64;
  11. import std.exception;
  12. import std.string;
  13. @safe:
  14. /**
  15. Returns a request handler that enforces request to be authenticated using HTTP Basic Auth.
  16. */
  17. HTTPServerRequestDelegateS performBasicAuth(string realm, PasswordVerifyCallback pwcheck)
  18. {
  19. void handleRequest(scope HTTPServerRequest req, scope HTTPServerResponse res)
  20. @safe {
  21. if (!checkBasicAuth(req, pwcheck)) {
  22. res.statusCode = HTTPStatus.unauthorized;
  23. res.contentType = "text/plain";
  24. res.headers["WWW-Authenticate"] = "Basic realm=\""~realm~"\"";
  25. res.bodyWriter.write("Authorization required");
  26. }
  27. }
  28. return &handleRequest;
  29. }
  30. /// Scheduled for deprecation - use a `@safe` callback instead.
  31. HTTPServerRequestDelegateS performBasicAuth(string realm, bool delegate(string, string) @system pwcheck)
  32. @system {
  33. return performBasicAuth(realm, (u, p) @trusted => pwcheck(u, p));
  34. }
  35. /**
  36. Enforces HTTP Basic Auth authentication on the given req/res pair.
  37. Params:
  38. req = Request object that is to be checked
  39. res = Response object that will be used for authentication errors
  40. realm = HTTP Basic Auth realm reported to the client
  41. pwcheck = A delegate queried for validating user/password pairs
  42. Returns: Returns the name of the authenticated user.
  43. Throws: Throws a HTTPStatusExeption in case of an authentication failure.
  44. */
  45. string performBasicAuth(scope HTTPServerRequest req, scope HTTPServerResponse res, string realm, scope PasswordVerifyCallback pwcheck)
  46. {
  47. if (checkBasicAuth(req, pwcheck))
  48. return req.username;
  49. res.headers["WWW-Authenticate"] = "Basic realm=\""~realm~"\"";
  50. throw new HTTPStatusException(HTTPStatus.unauthorized);
  51. }
  52. /// Scheduled for deprecation - use a `@safe` callback instead.
  53. string performBasicAuth(scope HTTPServerRequest req, scope HTTPServerResponse res, string realm, scope bool delegate(string, string) @system pwcheck)
  54. @system {
  55. return performBasicAuth(req, res, realm, (u, p) @trusted => pwcheck(u, p));
  56. }
  57. /**
  58. Checks for valid HTTP Basic Auth authentication on the given request.
  59. Upon successful authorization, the name of the authorized user will
  60. be stored in `req.username`.
  61. Params:
  62. req = Request object that is to be checked
  63. pwcheck = A delegate queried for validating user/password pairs
  64. Returns: Returns `true` $(I iff) a valid Basic Auth header is present
  65. and the credentials were verified successfully by the validation
  66. callback.
  67. Throws: Throws a `HTTPStatusExeption` with `HTTPStatusCode.badRequest`
  68. if the "Authorization" header is malformed.
  69. */
  70. bool checkBasicAuth(scope HTTPServerRequest req, scope PasswordVerifyCallback pwcheck)
  71. {
  72. auto pauth = "Authorization" in req.headers;
  73. if (pauth && (*pauth).startsWith("Basic ")) {
  74. string user_pw = () @trusted { return cast(string)Base64.decode((*pauth)[6 .. $]); } ();
  75. auto idx = user_pw.indexOf(":");
  76. enforceBadRequest(idx >= 0, "Invalid auth string format!");
  77. string user = user_pw[0 .. idx];
  78. string password = user_pw[idx+1 .. $];
  79. if (pwcheck(user, password)) {
  80. req.username = user;
  81. return true;
  82. }
  83. }
  84. return false;
  85. }
  86. static import vibe.http.internal.basic_auth_client;
  87. alias addBasicAuth = vibe.http.internal.basic_auth_client.addBasicAuth;
  88. alias PasswordVerifyCallback = bool delegate(string user, string password);