Format API keys in hexa instead of base64

This commit is contained in:
ManyTheFish 2022-07-05 14:13:20 +02:00
parent 8a64ee0c14
commit a146fd45b9
7 changed files with 38 additions and 22 deletions

18
Cargo.lock generated
View File

@ -2003,7 +2003,6 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
name = "meilisearch-auth" name = "meilisearch-auth"
version = "0.28.0" version = "0.28.0"
dependencies = [ dependencies = [
"base64",
"enum-iterator", "enum-iterator",
"hmac", "hmac",
"meilisearch-types", "meilisearch-types",
@ -2014,7 +2013,7 @@ dependencies = [
"sha2", "sha2",
"thiserror", "thiserror",
"time 0.3.9", "time 0.3.9",
"uuid", "uuid 1.1.2",
] ]
[[package]] [[package]]
@ -2083,7 +2082,7 @@ dependencies = [
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"urlencoding", "urlencoding",
"uuid", "uuid 1.1.2",
"vergen", "vergen",
"walkdir", "walkdir",
"yaup", "yaup",
@ -2147,7 +2146,7 @@ dependencies = [
"thiserror", "thiserror",
"time 0.3.9", "time 0.3.9",
"tokio", "tokio",
"uuid", "uuid 1.1.2",
"walkdir", "walkdir",
"whoami", "whoami",
] ]
@ -2229,7 +2228,7 @@ dependencies = [
"tempfile", "tempfile",
"thiserror", "thiserror",
"time 0.3.9", "time 0.3.9",
"uuid", "uuid 0.8.2",
] ]
[[package]] [[package]]
@ -3676,6 +3675,15 @@ name = "uuid"
version = "0.8.2" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom",
]
[[package]]
name = "uuid"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
dependencies = [ dependencies = [
"getrandom", "getrandom",
"serde", "serde",

View File

@ -4,7 +4,6 @@ version = "0.28.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
base64 = "0.13.0"
enum-iterator = "0.7.0" enum-iterator = "0.7.0"
hmac = "0.12.1" hmac = "0.12.1"
meilisearch-types = { path = "../meilisearch-types" } meilisearch-types = { path = "../meilisearch-types" }
@ -15,4 +14,4 @@ serde_json = { version = "1.0.79", features = ["preserve_order"] }
sha2 = "0.10.2" sha2 = "0.10.2"
thiserror = "1.0.30" thiserror = "1.0.30"
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] } time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
uuid = { version = "0.8.2", features = ["serde", "v4"] } uuid = { version = "1.1.2", features = ["serde", "v4"] }

View File

@ -18,7 +18,7 @@ pub use action::{actions, Action};
use error::{AuthControllerError, Result}; use error::{AuthControllerError, Result};
pub use key::Key; pub use key::Key;
use meilisearch_types::star_or::StarOr; use meilisearch_types::star_or::StarOr;
use store::generate_key_as_base64; use store::generate_key_as_hexa;
pub use store::open_auth_store_env; pub use store::open_auth_store_env;
use store::HeedAuthStore; use store::HeedAuthStore;
@ -139,7 +139,7 @@ impl AuthController {
pub fn generate_key(&self, uid: Uuid) -> Option<String> { pub fn generate_key(&self, uid: Uuid) -> Option<String> {
self.master_key self.master_key
.as_ref() .as_ref()
.map(|master_key| generate_key_as_base64(uid.as_bytes(), master_key.as_bytes())) .map(|master_key| generate_key_as_hexa(uid, master_key.as_bytes()))
} }
/// Check if the provided key is authorized to make a specific action /// Check if the provided key is authorized to make a specific action

View File

@ -13,8 +13,9 @@ use hmac::{Hmac, Mac};
use meilisearch_types::star_or::StarOr; use meilisearch_types::star_or::StarOr;
use milli::heed::types::{ByteSlice, DecodeIgnore, SerdeJson}; use milli::heed::types::{ByteSlice, DecodeIgnore, SerdeJson};
use milli::heed::{Database, Env, EnvOpenOptions, RwTxn}; use milli::heed::{Database, Env, EnvOpenOptions, RwTxn};
use sha2::{Digest, Sha256}; use sha2::Sha256;
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::fmt::Hyphenated;
use uuid::Uuid; use uuid::Uuid;
use super::error::Result; use super::error::Result;
@ -132,13 +133,16 @@ impl HeedAuthStore {
.remap_data_type::<DecodeIgnore>() .remap_data_type::<DecodeIgnore>()
.iter(&rtxn)? .iter(&rtxn)?
.filter_map(|res| match res { .filter_map(|res| match res {
Ok((uid, _)) Ok((uid, _)) => {
if generate_key_as_base64(uid, master_key).as_bytes() == encoded_key =>
{
let (uid, _) = try_split_array_at(uid)?; let (uid, _) = try_split_array_at(uid)?;
Some(Uuid::from_bytes(*uid)) let uid = Uuid::from_bytes(*uid);
if generate_key_as_hexa(uid, master_key).as_bytes() == encoded_key {
Some(uid)
} else {
None
} }
_ => None, }
Err(_) => None,
}) })
.next(); .next();
@ -244,13 +248,17 @@ impl<'a> milli::heed::BytesEncode<'a> for KeyIdActionCodec {
} }
} }
pub fn generate_key_as_base64(uid: &[u8], master_key: &[u8]) -> String { pub fn generate_key_as_hexa(uid: Uuid, master_key: &[u8]) -> String {
let master_key_sha = Sha256::digest(master_key); // format uid as hyphenated allowing user to generate their own keys.
let mut mac = Hmac::<Sha256>::new_from_slice(master_key_sha.as_slice()).unwrap(); let mut uid_buffer = [0; Hyphenated::LENGTH];
mac.update(uid); let uid = uid.hyphenated().encode_lower(&mut uid_buffer);
// new_from_slice function never fail.
let mut mac = Hmac::<Sha256>::new_from_slice(master_key).unwrap();
mac.update(uid.as_bytes());
let result = mac.finalize(); let result = mac.finalize();
base64::encode_config(result.into_bytes(), base64::URL_SAFE_NO_PAD) format!("{:x}", result.into_bytes())
} }
/// Divides one slice into two at an index, returns `None` if mid is out of bounds. /// Divides one slice into two at an index, returns `None` if mid is out of bounds.

View File

@ -75,7 +75,7 @@ thiserror = "1.0.30"
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] } time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
tokio = { version = "1.17.0", features = ["full"] } tokio = { version = "1.17.0", features = ["full"] }
tokio-stream = "0.1.8" tokio-stream = "0.1.8"
uuid = { version = "0.8.2", features = ["serde", "v4"] } uuid = { version = "1.1.2", features = ["serde", "v4"] }
walkdir = "2.3.2" walkdir = "2.3.2"
[dev-dependencies] [dev-dependencies]

View File

@ -42,6 +42,7 @@ async fn add_valid_api_key() {
"name": "indexing-key", "name": "indexing-key",
"description": "Indexing API key", "description": "Indexing API key",
"uid": "4bc0887a-0e41-4f3b-935d-0c451dcee9c8", "uid": "4bc0887a-0e41-4f3b-935d-0c451dcee9c8",
"key": "d9e776b8412f1db6974c9a5556b961c3559440b6588216f4ea5d9ed49f7c8f3c",
"indexes": ["products"], "indexes": ["products"],
"actions": [ "actions": [
"search", "search",

View File

@ -51,7 +51,7 @@ tempfile = "3.3.0"
thiserror = "1.0.30" thiserror = "1.0.30"
time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] } time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] }
tokio = { version = "1.17.0", features = ["full"] } tokio = { version = "1.17.0", features = ["full"] }
uuid = { version = "0.8.2", features = ["serde", "v4"] } uuid = { version = "1.1.2", features = ["serde", "v4"] }
walkdir = "2.3.2" walkdir = "2.3.2"
whoami = { version = "1.2.1", optional = true } whoami = { version = "1.2.1", optional = true }