See https://pocoproject.org/forum/viewtopic.php?f=10&t=6326&p=11426&hilit=mongodb+auth#p11485
| 41 | #if POCO_VERSION < 0x01070800 |
| 42 | /// See https://pocoproject.org/forum/viewtopic.php?f=10&t=6326&p=11426&hilit=mongodb+auth#p11485 |
| 43 | void authenticate(Poco::MongoDB::Connection & connection, const std::string & database, const std::string & user, const std::string & password) |
| 44 | { |
| 45 | Poco::MongoDB::Database db(database); |
| 46 | |
| 47 | /// Challenge-response authentication. |
| 48 | std::string nonce; |
| 49 | |
| 50 | /// First step: request nonce. |
| 51 | { |
| 52 | auto command = db.createCommand(); |
| 53 | command->setNumberToReturn(1); |
| 54 | command->selector().add<Int32>("getnonce", 1); |
| 55 | |
| 56 | Poco::MongoDB::ResponseMessage response; |
| 57 | connection.sendRequest(*command, response); |
| 58 | |
| 59 | if (response.documents().empty()) |
| 60 | throw Exception( |
| 61 | "Cannot authenticate in MongoDB: server returned empty response for 'getnonce' command", |
| 62 | ErrorCodes::MONGODB_CANNOT_AUTHENTICATE); |
| 63 | |
| 64 | auto doc = response.documents()[0]; |
| 65 | try |
| 66 | { |
| 67 | double ok = doc->get<double>("ok", 0); |
| 68 | if (ok != 1) |
| 69 | throw Exception( |
| 70 | "Cannot authenticate in MongoDB: server returned response for 'getnonce' command that" |
| 71 | " has field 'ok' missing or having wrong value", |
| 72 | ErrorCodes::MONGODB_CANNOT_AUTHENTICATE); |
| 73 | |
| 74 | nonce = doc->get<std::string>("nonce", ""); |
| 75 | if (nonce.empty()) |
| 76 | throw Exception( |
| 77 | "Cannot authenticate in MongoDB: server returned response for 'getnonce' command that" |
| 78 | " has field 'nonce' missing or empty", |
| 79 | ErrorCodes::MONGODB_CANNOT_AUTHENTICATE); |
| 80 | } |
| 81 | catch (Poco::NotFoundException & e) |
| 82 | { |
| 83 | throw Exception( |
| 84 | "Cannot authenticate in MongoDB: server returned response for 'getnonce' command that has missing required field: " |
| 85 | + e.displayText(), |
| 86 | ErrorCodes::MONGODB_CANNOT_AUTHENTICATE); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | /// Second step: use nonce to calculate digest and send it back to the server. |
| 91 | /// Digest is hex_md5(n.nonce + username + hex_md5(username + ":mongo:" + password)) |
| 92 | { |
| 93 | std::string first = user + ":mongo:" + password; |
| 94 | |
| 95 | Poco::MD5Engine md5; |
| 96 | md5.update(first); |
| 97 | std::string digest_first(Poco::DigestEngine::digestToHex(md5.digest())); |
| 98 | std::string second = nonce + user + digest_first; |
| 99 | md5.reset(); |
| 100 | md5.update(second); |
no test coverage detected