parent
4c98717f1d
commit
a7444a7c8e
7 changed files with 91 additions and 13 deletions
|
@ -22,6 +22,8 @@ pub struct Session {
|
||||||
pub db: Option<String>,
|
pub db: Option<String>,
|
||||||
/// The currently selected authentication scope
|
/// The currently selected authentication scope
|
||||||
pub sc: Option<String>,
|
pub sc: Option<String>,
|
||||||
|
/// The current scope authentication token
|
||||||
|
pub tk: Option<Value>,
|
||||||
/// The current scope authentication data
|
/// The current scope authentication data
|
||||||
pub sd: Option<Value>,
|
pub sd: Option<Value>,
|
||||||
}
|
}
|
||||||
|
@ -101,13 +103,14 @@ impl Session {
|
||||||
// Add session value
|
// Add session value
|
||||||
let key = String::from("session");
|
let key = String::from("session");
|
||||||
let val: Value = Value::from(map! {
|
let val: Value = Value::from(map! {
|
||||||
"ip".to_string() => self.ip.to_owned().into(),
|
|
||||||
"or".to_string() => self.or.to_owned().into(),
|
|
||||||
"id".to_string() => self.id.to_owned().into(),
|
|
||||||
"ns".to_string() => self.ns.to_owned().into(),
|
|
||||||
"db".to_string() => self.db.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(),
|
"sc".to_string() => self.sc.to_owned().into(),
|
||||||
"sd".to_string() => self.sd.to_owned().into(),
|
"sd".to_string() => self.sd.to_owned().into(),
|
||||||
|
"tk".to_string() => self.tk.to_owned().into(),
|
||||||
});
|
});
|
||||||
ctx.add_value(key, val);
|
ctx.add_value(key, val);
|
||||||
// Output context
|
// Output context
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod clear;
|
pub mod clear;
|
||||||
|
pub mod parse;
|
||||||
pub mod signin;
|
pub mod signin;
|
||||||
pub mod signup;
|
pub mod signup;
|
||||||
pub mod token;
|
pub mod token;
|
||||||
|
|
15
src/iam/parse.rs
Normal file
15
src/iam/parse.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use crate::err::Error;
|
||||||
|
use std::str;
|
||||||
|
use surrealdb::sql::json;
|
||||||
|
use surrealdb::sql::Value;
|
||||||
|
|
||||||
|
pub fn parse(value: &str) -> Result<Value, Error> {
|
||||||
|
// Extract the middle part of the token
|
||||||
|
let value = value.splitn(3, '.').skip(1).take(1).next().ok_or(Error::InvalidAuth)?;
|
||||||
|
// Decode the base64 token data content
|
||||||
|
let value = base64::decode(value).map_err(|_| Error::InvalidAuth)?;
|
||||||
|
// Convert the decoded data to a string
|
||||||
|
let value = str::from_utf8(&value).map_err(|_| Error::InvalidAuth)?;
|
||||||
|
// Parse the token data into SurrealQL
|
||||||
|
json(value).map_err(|_| Error::InvalidAuth)
|
||||||
|
}
|
|
@ -144,14 +144,17 @@ pub async fn sc(
|
||||||
id: Some(rid.to_raw()),
|
id: Some(rid.to_raw()),
|
||||||
..Claims::default()
|
..Claims::default()
|
||||||
};
|
};
|
||||||
|
// Create the authentication token
|
||||||
|
let enc = encode(&*HEADER, &val, &key);
|
||||||
// Set the authentication on the session
|
// Set the authentication on the session
|
||||||
|
session.tk = Some(val.into());
|
||||||
session.ns = Some(ns.to_owned());
|
session.ns = Some(ns.to_owned());
|
||||||
session.db = Some(db.to_owned());
|
session.db = Some(db.to_owned());
|
||||||
session.sc = Some(sc.to_owned());
|
session.sc = Some(sc.to_owned());
|
||||||
session.sd = Some(Value::from(rid));
|
session.sd = Some(Value::from(rid));
|
||||||
session.au = Arc::new(Auth::Sc(ns, db, sc));
|
session.au = Arc::new(Auth::Sc(ns, db, sc));
|
||||||
// Create the authentication token
|
// Check the authentication token
|
||||||
match encode(&*HEADER, &val, &key) {
|
match enc {
|
||||||
// The auth token was created successfully
|
// The auth token was created successfully
|
||||||
Ok(tk) => Ok(tk),
|
Ok(tk) => Ok(tk),
|
||||||
// There was an error creating the token
|
// There was an error creating the token
|
||||||
|
@ -206,10 +209,15 @@ pub async fn db(
|
||||||
id: Some(user),
|
id: Some(user),
|
||||||
..Claims::default()
|
..Claims::default()
|
||||||
};
|
};
|
||||||
// Set the authentication on the session
|
|
||||||
session.au = Arc::new(Auth::Db(ns, db));
|
|
||||||
// Create the authentication token
|
// Create the authentication token
|
||||||
match encode(&*HEADER, &val, &key) {
|
let enc = encode(&*HEADER, &val, &key);
|
||||||
|
// Set the authentication on the session
|
||||||
|
session.tk = Some(val.into());
|
||||||
|
session.ns = Some(ns.to_owned());
|
||||||
|
session.db = Some(db.to_owned());
|
||||||
|
session.au = Arc::new(Auth::Db(ns, db));
|
||||||
|
// Check the authentication token
|
||||||
|
match enc {
|
||||||
// The auth token was created successfully
|
// The auth token was created successfully
|
||||||
Ok(tk) => Ok(tk),
|
Ok(tk) => Ok(tk),
|
||||||
// There was an error creating the token
|
// There was an error creating the token
|
||||||
|
@ -255,10 +263,14 @@ pub async fn ns(
|
||||||
id: Some(user),
|
id: Some(user),
|
||||||
..Claims::default()
|
..Claims::default()
|
||||||
};
|
};
|
||||||
// Set the authentication on the session
|
|
||||||
session.au = Arc::new(Auth::Ns(ns));
|
|
||||||
// Create the authentication token
|
// Create the authentication token
|
||||||
match encode(&*HEADER, &val, &key) {
|
let enc = encode(&*HEADER, &val, &key);
|
||||||
|
// Set the authentication on the session
|
||||||
|
session.tk = Some(val.into());
|
||||||
|
session.ns = Some(ns.to_owned());
|
||||||
|
session.au = Arc::new(Auth::Ns(ns));
|
||||||
|
// Check the authentication token
|
||||||
|
match enc {
|
||||||
// The auth token was created successfully
|
// The auth token was created successfully
|
||||||
Ok(tk) => Ok(tk),
|
Ok(tk) => Ok(tk),
|
||||||
// There was an error creating the token
|
// There was an error creating the token
|
||||||
|
|
|
@ -79,14 +79,17 @@ pub async fn sc(
|
||||||
id: Some(rid.to_raw()),
|
id: Some(rid.to_raw()),
|
||||||
..Claims::default()
|
..Claims::default()
|
||||||
};
|
};
|
||||||
|
// Create the authentication token
|
||||||
|
let enc = encode(&*HEADER, &val, &key);
|
||||||
// Set the authentication on the session
|
// Set the authentication on the session
|
||||||
|
session.tk = Some(val.into());
|
||||||
session.ns = Some(ns.to_owned());
|
session.ns = Some(ns.to_owned());
|
||||||
session.db = Some(db.to_owned());
|
session.db = Some(db.to_owned());
|
||||||
session.sc = Some(sc.to_owned());
|
session.sc = Some(sc.to_owned());
|
||||||
session.sd = Some(Value::from(rid));
|
session.sd = Some(Value::from(rid));
|
||||||
session.au = Arc::new(Auth::Sc(ns, db, sc));
|
session.au = Arc::new(Auth::Sc(ns, db, sc));
|
||||||
// Create the authentication token
|
// Create the authentication token
|
||||||
match encode(&*HEADER, &val, &key) {
|
match enc {
|
||||||
// The auth token was created successfully
|
// The auth token was created successfully
|
||||||
Ok(tk) => Ok(tk),
|
Ok(tk) => Ok(tk),
|
||||||
// There was an error creating the token
|
// There was an error creating the token
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use jsonwebtoken::{Algorithm, Header};
|
use jsonwebtoken::{Algorithm, Header};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use surrealdb::sql::Object;
|
||||||
|
use surrealdb::sql::Value;
|
||||||
|
|
||||||
pub static HEADER: Lazy<Header> = Lazy::new(|| Header::new(Algorithm::HS512));
|
pub static HEADER: Lazy<Header> = Lazy::new(|| Header::new(Algorithm::HS512));
|
||||||
|
|
||||||
|
@ -36,3 +38,37 @@ pub struct Claims {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Claims> for Value {
|
||||||
|
fn from(v: Claims) -> Value {
|
||||||
|
// Set default value
|
||||||
|
let mut out = Object::default();
|
||||||
|
// Add default fields
|
||||||
|
out.insert("iat".to_string(), v.iat.into());
|
||||||
|
out.insert("nbf".to_string(), v.nbf.into());
|
||||||
|
out.insert("exp".to_string(), v.exp.into());
|
||||||
|
out.insert("iss".to_string(), v.iss.into());
|
||||||
|
// Add NS field if set
|
||||||
|
if let Some(ns) = v.ns {
|
||||||
|
out.insert("NS".to_string(), ns.into());
|
||||||
|
}
|
||||||
|
// Add DB field if set
|
||||||
|
if let Some(db) = v.db {
|
||||||
|
out.insert("DB".to_string(), db.into());
|
||||||
|
}
|
||||||
|
// Add SC field if set
|
||||||
|
if let Some(sc) = v.sc {
|
||||||
|
out.insert("SC".to_string(), sc.into());
|
||||||
|
}
|
||||||
|
// Add TK field if set
|
||||||
|
if let Some(tk) = v.tk {
|
||||||
|
out.insert("TK".to_string(), tk.into());
|
||||||
|
}
|
||||||
|
// Add NS field if set
|
||||||
|
if let Some(id) = v.id {
|
||||||
|
out.insert("ID".to_string(), id.into());
|
||||||
|
}
|
||||||
|
// Return value
|
||||||
|
out.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -156,6 +156,8 @@ pub async fn token(session: &mut Session, auth: String) -> Result<(), Error> {
|
||||||
let kvs = DB.get().unwrap();
|
let kvs = DB.get().unwrap();
|
||||||
// Decode the token without verifying
|
// Decode the token without verifying
|
||||||
let token = decode::<Claims>(auth, &KEY, &DUD)?;
|
let token = decode::<Claims>(auth, &KEY, &DUD)?;
|
||||||
|
// Parse the token and catch any errors
|
||||||
|
let value = super::parse::parse(auth)?;
|
||||||
// Check the token authentication claims
|
// Check the token authentication claims
|
||||||
match token.claims {
|
match token.claims {
|
||||||
// Check if this is scope token authentication
|
// Check if this is scope token authentication
|
||||||
|
@ -181,6 +183,7 @@ pub async fn token(session: &mut Session, auth: String) -> Result<(), Error> {
|
||||||
// Log the success
|
// Log the success
|
||||||
debug!(target: LOG, "Authenticated to scope `{}` with token `{}`", sc, tk);
|
debug!(target: LOG, "Authenticated to scope `{}` with token `{}`", sc, tk);
|
||||||
// Set the session
|
// Set the session
|
||||||
|
session.tk = Some(value);
|
||||||
session.ns = Some(ns.to_owned());
|
session.ns = Some(ns.to_owned());
|
||||||
session.db = Some(db.to_owned());
|
session.db = Some(db.to_owned());
|
||||||
session.sc = Some(sc.to_owned());
|
session.sc = Some(sc.to_owned());
|
||||||
|
@ -210,6 +213,7 @@ pub async fn token(session: &mut Session, auth: String) -> Result<(), Error> {
|
||||||
// Log the success
|
// Log the success
|
||||||
debug!(target: LOG, "Authenticated to scope `{}`", sc);
|
debug!(target: LOG, "Authenticated to scope `{}`", sc);
|
||||||
// Set the session
|
// Set the session
|
||||||
|
session.tk = Some(value);
|
||||||
session.ns = Some(ns.to_owned());
|
session.ns = Some(ns.to_owned());
|
||||||
session.db = Some(db.to_owned());
|
session.db = Some(db.to_owned());
|
||||||
session.sc = Some(sc.to_owned());
|
session.sc = Some(sc.to_owned());
|
||||||
|
@ -236,6 +240,7 @@ pub async fn token(session: &mut Session, auth: String) -> Result<(), Error> {
|
||||||
// Log the success
|
// Log the success
|
||||||
debug!(target: LOG, "Authenticated to database `{}` with token `{}`", db, tk);
|
debug!(target: LOG, "Authenticated to database `{}` with token `{}`", db, tk);
|
||||||
// Set the session
|
// Set the session
|
||||||
|
session.tk = Some(value);
|
||||||
session.ns = Some(ns.to_owned());
|
session.ns = Some(ns.to_owned());
|
||||||
session.db = Some(db.to_owned());
|
session.db = Some(db.to_owned());
|
||||||
session.au = Arc::new(Auth::Db(ns, db));
|
session.au = Arc::new(Auth::Db(ns, db));
|
||||||
|
@ -260,6 +265,7 @@ pub async fn token(session: &mut Session, auth: String) -> Result<(), Error> {
|
||||||
// Log the success
|
// Log the success
|
||||||
debug!(target: LOG, "Authenticated to database `{}` with login `{}`", db, id);
|
debug!(target: LOG, "Authenticated to database `{}` with login `{}`", db, id);
|
||||||
// Set the session
|
// Set the session
|
||||||
|
session.tk = Some(value);
|
||||||
session.ns = Some(ns.to_owned());
|
session.ns = Some(ns.to_owned());
|
||||||
session.db = Some(db.to_owned());
|
session.db = Some(db.to_owned());
|
||||||
session.au = Arc::new(Auth::Db(ns, db));
|
session.au = Arc::new(Auth::Db(ns, db));
|
||||||
|
@ -283,6 +289,7 @@ pub async fn token(session: &mut Session, auth: String) -> Result<(), Error> {
|
||||||
// Log the success
|
// Log the success
|
||||||
trace!(target: LOG, "Authenticated to namespace `{}` with token `{}`", ns, tk);
|
trace!(target: LOG, "Authenticated to namespace `{}` with token `{}`", ns, tk);
|
||||||
// Set the session
|
// Set the session
|
||||||
|
session.tk = Some(value);
|
||||||
session.ns = Some(ns.to_owned());
|
session.ns = Some(ns.to_owned());
|
||||||
session.au = Arc::new(Auth::Ns(ns));
|
session.au = Arc::new(Auth::Ns(ns));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -305,6 +312,7 @@ pub async fn token(session: &mut Session, auth: String) -> Result<(), Error> {
|
||||||
// Log the success
|
// Log the success
|
||||||
trace!(target: LOG, "Authenticated to namespace `{}` with login `{}`", ns, id);
|
trace!(target: LOG, "Authenticated to namespace `{}` with login `{}`", ns, id);
|
||||||
// Set the session
|
// Set the session
|
||||||
|
session.tk = Some(value);
|
||||||
session.ns = Some(ns.to_owned());
|
session.ns = Some(ns.to_owned());
|
||||||
session.au = Arc::new(Auth::Ns(ns));
|
session.au = Arc::new(Auth::Ns(ns));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
Loading…
Reference in a new issue