|
@@ -0,0 +1,57 @@
|
|
|
|
|
+#include "auth.hpp"
|
|
|
|
|
+#include <openssl/rand.h>
|
|
|
|
|
+#include <array>
|
|
|
|
|
+#include <stdexcept>
|
|
|
|
|
+
|
|
|
|
|
+namespace svapi {
|
|
|
|
|
+
|
|
|
|
|
+std::optional<std::string> bearerToken(const std::string& h) {
|
|
|
|
|
+ constexpr const char* P = "Bearer "; constexpr size_t L = 7;
|
|
|
|
|
+ if (h.size() <= L || h.compare(0, L, P) != 0) return std::nullopt;
|
|
|
|
|
+ return h.substr(L);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::optional<std::string> cookieValue(const std::string& header, const std::string& name) {
|
|
|
|
|
+ size_t pos = 0;
|
|
|
|
|
+ while (pos < header.size()) {
|
|
|
|
|
+ size_t semi = header.find(';', pos);
|
|
|
|
|
+ std::string pair = header.substr(pos, semi == std::string::npos ? std::string::npos : semi - pos);
|
|
|
|
|
+ size_t s = pair.find_first_not_of(" \t"); if (s != std::string::npos) pair = pair.substr(s);
|
|
|
|
|
+ size_t eq = pair.find('=');
|
|
|
|
|
+ if (eq != std::string::npos && pair.substr(0, eq) == name) return pair.substr(eq + 1);
|
|
|
|
|
+ if (semi == std::string::npos) break;
|
|
|
|
|
+ pos = semi + 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ return std::nullopt;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::string randomToken() {
|
|
|
|
|
+ std::array<unsigned char, 16> buf{};
|
|
|
|
|
+ if (RAND_bytes(buf.data(), (int)buf.size()) != 1) throw std::runtime_error("RAND_bytes failed");
|
|
|
|
|
+ static const char* hex = "0123456789abcdef"; std::string o; o.reserve(32);
|
|
|
|
|
+ for (unsigned char b : buf) { o.push_back(hex[b >> 4]); o.push_back(hex[b & 0xF]); }
|
|
|
|
|
+ return o;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+SessionStore::SessionStore(std::chrono::minutes ttl) : ttl_(ttl) {}
|
|
|
|
|
+
|
|
|
|
|
+std::string SessionStore::create(const std::string& apiKeyValue, std::chrono::system_clock::time_point now) {
|
|
|
|
|
+ std::string tok = randomToken();
|
|
|
|
|
+ std::lock_guard<std::mutex> lk(m_);
|
|
|
|
|
+ sessions_[tok] = Entry{apiKeyValue, now + ttl_};
|
|
|
|
|
+ return tok;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::optional<std::string> SessionStore::keyFor(const std::string& token, std::chrono::system_clock::time_point now) {
|
|
|
|
|
+ std::lock_guard<std::mutex> lk(m_);
|
|
|
|
|
+ auto it = sessions_.find(token);
|
|
|
|
|
+ if (it == sessions_.end()) return std::nullopt;
|
|
|
|
|
+ if (now >= it->second.expiry) { sessions_.erase(it); return std::nullopt; }
|
|
|
|
|
+ return it->second.key;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void SessionStore::remove(const std::string& token) { std::lock_guard<std::mutex> lk(m_); sessions_.erase(token); }
|
|
|
|
|
+
|
|
|
|
|
+void SessionStore::setTtl(std::chrono::minutes ttl) { std::lock_guard<std::mutex> lk(m_); ttl_ = ttl; }
|
|
|
|
|
+
|
|
|
|
|
+} // namespace svapi
|