Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate authentication methods #3988

Merged
merged 63 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
6a79657
WIP
gguillemas Apr 23, 2024
feade8f
Allow defining access on root
gguillemas Apr 23, 2024
9d58b53
Draft implementation of record signin
gguillemas Apr 24, 2024
f63cb68
Draft implementation of token authentication
gguillemas Apr 25, 2024
c90d895
Draft custom issuer support
gguillemas Apr 26, 2024
d4e9fea
Improve query formatting
gguillemas May 2, 2024
fde5576
Backward compatible parsing of define statements
gguillemas May 2, 2024
aaaee77
WIP: Remove legacy scopes and tokens
gguillemas May 3, 2024
8d15e76
WIP: `cargo fmt`
gguillemas May 3, 2024
c386e98
Remove legacy scopes and tokens
gguillemas May 6, 2024
a3ceda3
`cargo fmt`
gguillemas May 6, 2024
a655899
Add missing imports
gguillemas May 7, 2024
541c059
Fix failing test
gguillemas May 7, 2024
9d6b5a8
Keep JWKS as a feature
gguillemas May 7, 2024
4db94e8
Fix clippy and some tests
gguillemas May 7, 2024
46f3e43
Use correct type
gguillemas May 7, 2024
5d1160a
Add global `$access` parameter
gguillemas May 7, 2024
7ce04b3
Update library and first attempt and fixing tests
gguillemas May 7, 2024
a274cac
Fix fuzzing
gguillemas May 7, 2024
a04dfe8
Merge branch 'main' into gerard/consolidate-auth
gguillemas May 7, 2024
6b5f695
Fix compatibility with LQv2
gguillemas May 7, 2024
98e5e95
Fix WS tests
gguillemas May 8, 2024
6c6135f
Fix API tests
gguillemas May 8, 2024
8956a1d
`cargo fmt`
gguillemas May 8, 2024
200aa16
Again, `cargo fmt` but on `lib`
gguillemas May 8, 2024
987f0c7
Fix format errors
gguillemas May 8, 2024
dfc06f2
Fix example comment
gguillemas May 8, 2024
be88d14
Improve display format
gguillemas May 9, 2024
3d1dff4
Correctly add issuer when set
gguillemas May 9, 2024
ebcd370
Fix test
gguillemas May 9, 2024
62ceac7
Fix test
gguillemas May 9, 2024
88a2a4b
Merge branch 'main' into gerard/consolidate-auth
gguillemas May 9, 2024
3ca382c
Fix some warnings and tests
gguillemas May 9, 2024
0765af4
Fix tests
gguillemas May 9, 2024
f1662eb
Support custom issuer in signing operations
gguillemas May 10, 2024
f151356
Inherit duration and key for symmetric algorithms
gguillemas May 10, 2024
8cf9506
Fix test
gguillemas May 10, 2024
6f26cbd
Fix Clippy and tests
gguillemas May 10, 2024
aaf700e
Remove irrelevant TODOs
gguillemas May 10, 2024
9e7603e
Fix Clippy again
gguillemas May 10, 2024
bd2a0bf
`cargo fmt`
gguillemas May 10, 2024
1b0b47a
Fix tests
gguillemas May 10, 2024
0d2b49a
Fix typo
gguillemas May 10, 2024
5d329e4
Improve testing and assume less about issuer
gguillemas May 10, 2024
76ad90c
`cargo fmt`
gguillemas May 10, 2024
6ec794c
Remove unused code and fix tests
gguillemas May 10, 2024
a3373c0
Fix tests
gguillemas May 10, 2024
010eff6
Add missing data in test
gguillemas May 10, 2024
1b35c70
Merge branch 'main' into gerard/consolidate-auth
gguillemas May 13, 2024
d94bc39
Correctly deal with implicit and explicit issuers
gguillemas May 13, 2024
575975a
Address failing tests
gguillemas May 13, 2024
87fc016
Export updated JS functions
gguillemas May 13, 2024
0360629
Fix Clippy and correctly pop processed token
gguillemas May 13, 2024
c4356f7
Add additional tests
gguillemas May 13, 2024
f915aff
Add more tests and ensure backward compatibility
gguillemas May 13, 2024
064cb31
Avoid duration resulting in always adding issuer
gguillemas May 13, 2024
0f2a866
Merge branch 'main' into gerard/consolidate-auth
gguillemas May 13, 2024
c6d0d06
Rename signin/signup database access function
gguillemas May 14, 2024
fd7b691
Merge branch 'main' into gerard/consolidate-auth
gguillemas May 14, 2024
db64a8b
Update tests after function renaming
gguillemas May 14, 2024
2996ca4
Rename `sc` to `ac`
gguillemas May 14, 2024
c93b332
Correctly sort keys
gguillemas May 17, 2024
bb258cb
Add access parameter to session in LQ tests
gguillemas May 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions core/src/cnf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub static MAX_COMPUTATION_DEPTH: Lazy<u32> =
lazy_env_parse!("SURREAL_MAX_COMPUTATION_DEPTH", u32, 120);

/// Specifies the names of parameters which can not be specified in a query.
pub const PROTECTED_PARAM_NAMES: &[&str] = &["auth", "scope", "token", "session"];
pub const PROTECTED_PARAM_NAMES: &[&str] = &["access", "auth", "token", "session"];

/// The characters which are supported in server record IDs.
pub const ID_CHARS: [char; 36] = [
Expand All @@ -35,9 +35,9 @@ pub const SERVER_NAME: &str = "SurrealDB";
/// Datastore processor batch size for scan operations
pub const PROCESSOR_BATCH_SIZE: u32 = 50;

/// Forward all signup/signin query errors to a client trying authenticate to a scope. Do not use in production.
pub static INSECURE_FORWARD_SCOPE_ERRORS: Lazy<bool> =
lazy_env_parse!("SURREAL_INSECURE_FORWARD_SCOPE_ERRORS", bool, false);
/// Forward all signup/signin query errors to a client performing record access. Do not use in production.
pub static INSECURE_FORWARD_RECORD_ACCESS_ERRORS: Lazy<bool> =
lazy_env_parse!("SURREAL_INSECURE_FORWARD_RECORD_ACCESS_ERRORS", bool, false);

#[cfg(any(
feature = "kv-surrealkv",
Expand Down
7 changes: 4 additions & 3 deletions core/src/dbs/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,10 @@ impl Options {
self.valid_for_db()?;
res.on_db(self.ns(), self.db())
}
Base::Sc(sc) => {
self.valid_for_db()?;
res.on_scope(self.ns(), self.db(), sc)
// TODO(gguillemas): This variant is kept in 2.0.0 for backward compatibility. Drop in 3.0.0.
Base::Sc(_) => {
// We should not get here, the scope base is only used in parsing for backward compatibility.
return Err(Error::InvalidAuth);
}
};

Expand Down
42 changes: 21 additions & 21 deletions core/src/dbs/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ pub struct Session {
pub ns: Option<String>,
/// The currently selected database
pub db: Option<String>,
/// The currently selected authentication scope
pub sc: Option<String>,
/// The current scope authentication token
/// The current access method
pub ac: Option<String>,
/// The current authentication token
pub tk: Option<Value>,
/// The current scope authentication data
pub sd: Option<Value>,
/// The current record authentication data
pub rd: Option<Value>,
tobiemh marked this conversation as resolved.
Show resolved Hide resolved
/// The current expiration time of the session
pub exp: Option<i64>,
}
Expand All @@ -46,9 +46,9 @@ impl Session {
self
}

/// Set the selected database for the session
pub fn with_sc(mut self, sc: &str) -> Session {
self.sc = Some(sc.to_owned());
/// Set the selected access method for the session
pub fn with_ac(mut self, ac: &str) -> Session {
self.ac = Some(ac.to_owned());
self
}

Expand Down Expand Up @@ -84,26 +84,26 @@ impl Session {

/// Convert a session into a runtime
pub(crate) fn context<'a>(&self, mut ctx: Context<'a>) -> Context<'a> {
// Add scope auth data
let val: Value = self.sd.to_owned().into();
// Add access method data
let val: Value = self.ac.to_owned().into();
ctx.add_value("access", val);
// Add record access data
let val: Value = self.rd.to_owned().into();
ctx.add_value("auth", val);
// Add scope data
let val: Value = self.sc.to_owned().into();
ctx.add_value("scope", val);
// Add token data
let val: Value = self.tk.to_owned().into();
ctx.add_value("token", val);
// Add session value
let val: Value = Value::from(map! {
"ac".to_string() => self.ac.to_owned().into(),
"exp".to_string() => self.exp.to_owned().into(),
"db".to_string() => self.db.to_owned().into(),
"id".to_string() => self.id.to_owned().into(),
"ip".to_string() => self.ip.to_owned().into(),
"ns".to_string() => self.ns.to_owned().into(),
"or".to_string() => self.or.to_owned().into(),
"sc".to_string() => self.sc.to_owned().into(),
"sd".to_string() => self.sd.to_owned().into(),
"rd".to_string() => self.rd.to_owned().into(),
"tk".to_string() => self.tk.to_owned().into(),
"exp".to_string() => self.exp.to_owned().into(),
});
ctx.add_value("session", val);
// Output context
Expand Down Expand Up @@ -133,19 +133,19 @@ impl Session {
sess
}

/// Create a scoped session for a given NS and DB
pub fn for_scope(ns: &str, db: &str, sc: &str, rid: Value) -> Session {
/// Create a record user session for a given NS and DB
pub fn for_record(ns: &str, db: &str, ac: &str, rid: Value) -> Session {
Session {
au: Arc::new(Auth::for_sc(rid.to_string(), ns, db, sc)),
ac: Some(ac.to_owned()),
au: Arc::new(Auth::for_record(rid.to_string(), ns, db, ac)),
rt: false,
ip: None,
or: None,
id: None,
ns: Some(ns.to_owned()),
db: Some(db.to_owned()),
sc: Some(sc.to_owned()),
tk: None,
sd: Some(rid),
rd: Some(rid),
exp: None,
}
}
Expand Down
8 changes: 4 additions & 4 deletions core/src/doc/lives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use crate::doc::CursorDoc;
use crate::doc::Document;
use crate::err::Error;
use crate::fflags::FFLAGS;
use crate::sql::paths::AC;
use crate::sql::paths::META;
use crate::sql::paths::SC;
use crate::sql::paths::SD;
use crate::sql::paths::RD;
use crate::sql::paths::TK;
use crate::sql::permission::Permission;
use crate::sql::statements::LiveStatement;
Expand Down Expand Up @@ -161,8 +161,8 @@ impl<'a> Document<'a> {
// This ensures that we are using the session
// of the user who created the LIVE query.
let mut lqctx = Context::background();
lqctx.add_value("auth", sess.pick(SD.as_ref()));
lqctx.add_value("scope", sess.pick(SC.as_ref()));
lqctx.add_value("access", sess.pick(AC.as_ref()));
lqctx.add_value("auth", sess.pick(RD.as_ref()));
lqctx.add_value("token", sess.pick(TK.as_ref()));
lqctx.add_value("session", sess);
// We need to create a new options which we will
Expand Down
117 changes: 70 additions & 47 deletions core/src/err/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,9 @@ pub enum Error {
value: String,
},

/// The requested namespace token does not exist
#[error("The namespace token '{value}' does not exist")]
NtNotFound {
/// The requested namespace access method does not exist
#[error("The namespace access method '{value}' does not exist")]
NaNotFound {
value: String,
},

Expand All @@ -317,9 +317,9 @@ pub enum Error {
value: String,
},

/// The requested database token does not exist
#[error("The database token '{value}' does not exist")]
DtNotFound {
/// The requested database access method does not exist
#[error("The database access method '{value}' does not exist")]
DaNotFound {
value: String,
},

Expand Down Expand Up @@ -353,12 +353,6 @@ pub enum Error {
value: String,
},

/// The requested scope does not exist
#[error("The scope '{value}' does not exist")]
ScNotFound {
tobiemh marked this conversation as resolved.
Show resolved Hide resolved
value: String,
},

// The cluster node already exists
#[error("The node '{value}' already exists")]
ClAlreadyExists {
Expand All @@ -371,12 +365,6 @@ pub enum Error {
value: String,
},

/// The requested scope token does not exist
#[error("The scope token '{value}' does not exist")]
StNotFound {
value: String,
},

/// The requested param does not exist
#[error("The param '${value}' does not exist")]
PaNotFound {
Expand Down Expand Up @@ -764,15 +752,6 @@ pub enum Error {
#[error("The signin query failed")]
SigninQueryFailed,

#[error("This scope does not allow signup")]
ScopeNoSignup,

#[error("This scope does not allow signin")]
ScopeNoSignin,

#[error("The scope does not exist")]
NoScopeFound,

#[error("Username or Password was not provided")]
MissingUserOrPass,

Expand Down Expand Up @@ -864,12 +843,6 @@ pub enum Error {
value: String,
},

/// The requested scope already exists
#[error("The scope '{value}' already exists")]
ScAlreadyExists {
value: String,
},

/// The requested table already exists
#[error("The table '{value}' already exists")]
TbAlreadyExists {
Expand All @@ -888,12 +861,6 @@ pub enum Error {
value: String,
},

/// The requested scope token already exists
#[error("The scope token '{value}' already exists")]
StAlreadyExists {
value: String,
},

/// The requested user already exists
#[error("The user '{value}' already exists")]
UserRootAlreadyExists {
Expand Down Expand Up @@ -921,14 +888,6 @@ pub enum Error {
#[error("The session has expired")]
ExpiredSession,

/// The session has an invalid duration
#[error("The session has an invalid duration")]
InvalidSessionDuration,

/// The session has an invalid expiration
#[error("The session has an invalid expiration")]
InvalidSessionExpiration,

/// A node task has failed
#[error("A node task has failed: {0}")]
NodeAgent(&'static str),
Expand All @@ -940,6 +899,70 @@ pub enum Error {
/// The supplied type could not be serialiazed into `sql::Value`
#[error("Serialization error: {0}")]
Serialization(String),

/// The requested root access method already exists
#[error("The root access method '{value}' already exists")]
AccessRootAlreadyExists {
value: String,
},

/// The requested namespace access method already exists
#[error("The namespace access method '{value}' already exists")]
AccessNsAlreadyExists {
value: String,
},

/// The requested database access method already exists
#[error("The database access method '{value}' already exists")]
AccessDbAlreadyExists {
value: String,
},

/// The requested root access method does not exist
#[error("The root access method '{value}' does not exist")]
AccessRootNotFound {
value: String,
},

/// The requested namespace access method does not exist
#[error("The namespace access method '{value}' does not exist")]
AccessNsNotFound {
value: String,
},

/// The requested database access method does not exist
#[error("The database access method '{value}' does not exist")]
AccessDbNotFound {
value: String,
},

/// The access method cannot be defined on the requested level
#[error("The access method cannot be defined on the requested level")]
AccessLevelMismatch,

#[error("The access method cannot be used in the requested operation")]
AccessMethodMismatch,

#[error("The access method does not exist")]
AccessNotFound,

#[error("This access method has an invalid duration")]
AccessInvalidDuration,

#[error("This access method results in an invalid expiration")]
AccessInvalidExpiration,

#[error("The record access signup query failed")]
AccessRecordSignupQueryFailed,

#[error("The record access signin query failed")]
AccessRecordSigninQueryFailed,

#[error("This record access method does not allow signup")]
AccessRecordNoSignup,

#[error("This record access method does not allow signin")]
AccessRecordNoSignin,
}

impl From<Error> for String {
Expand Down
4 changes: 2 additions & 2 deletions core/src/fnc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,13 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
"rand::uuid::v7" => rand::uuid::v7,
"rand::uuid" => rand::uuid,
//
"session::ac" => session::ac(ctx),
"session::db" => session::db(ctx),
"session::id" => session::id(ctx),
"session::ip" => session::ip(ctx),
"session::ns" => session::ns(ctx),
"session::origin" => session::origin(ctx),
"session::sc" => session::sc(ctx),
"session::sd" => session::sd(ctx),
"session::rd" => session::rd(ctx),
tobiemh marked this conversation as resolved.
Show resolved Hide resolved
"session::token" => session::token(ctx),
//
"string::concat" => string::concat,
Expand Down
4 changes: 2 additions & 2 deletions core/src/fnc/script/modules/surrealdb/functions/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl_module_def!(
"ip" => run,
"ns" => run,
"origin" => run,
"sc" => run,
"sd" => run,
"ac" => run,
"rd" => run,
tobiemh marked this conversation as resolved.
Show resolved Hide resolved
"token" => run
);
16 changes: 8 additions & 8 deletions core/src/fnc/session.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
use crate::ctx::Context;
use crate::err::Error;
use crate::sql::paths::AC;
use crate::sql::paths::DB;
use crate::sql::paths::ID;
use crate::sql::paths::IP;
use crate::sql::paths::NS;
use crate::sql::paths::OR;
use crate::sql::paths::SC;
use crate::sql::paths::SD;
use crate::sql::paths::RD;
use crate::sql::paths::TK;
use crate::sql::value::Value;

pub fn ac(ctx: &Context, _: ()) -> Result<Value, Error> {
ctx.value("session").unwrap_or(&Value::None).pick(AC.as_ref()).ok()
}

pub fn db(ctx: &Context, _: ()) -> Result<Value, Error> {
ctx.value("session").unwrap_or(&Value::None).pick(DB.as_ref()).ok()
}
Expand All @@ -30,12 +34,8 @@ pub fn origin(ctx: &Context, _: ()) -> Result<Value, Error> {
ctx.value("session").unwrap_or(&Value::None).pick(OR.as_ref()).ok()
}

pub fn sc(ctx: &Context, _: ()) -> Result<Value, Error> {
ctx.value("session").unwrap_or(&Value::None).pick(SC.as_ref()).ok()
}

pub fn sd(ctx: &Context, _: ()) -> Result<Value, Error> {
ctx.value("session").unwrap_or(&Value::None).pick(SD.as_ref()).ok()
pub fn rd(ctx: &Context, _: ()) -> Result<Value, Error> {
ctx.value("session").unwrap_or(&Value::None).pick(RD.as_ref()).ok()
}

pub fn token(ctx: &Context, _: ()) -> Result<Value, Error> {
Expand Down