Skip to content

Commit

Permalink
Adding support for google oauth2 authentication in the omni-executor (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
silva-fj authored Jan 29, 2025
1 parent 60105a2 commit a414093
Show file tree
Hide file tree
Showing 48 changed files with 744 additions and 116 deletions.
381 changes: 342 additions & 39 deletions tee-worker/omni-executor/Cargo.lock

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions tee-worker/omni-executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ members = [
"executor-crypto",
"executor-core",
"executor-worker",
"executor-storage",
"executor-primitives",
"ethereum/intent-executor",
"ethereum/intent-executor",
"heima/authentication",
"heima/identity-verification",
"native-task-handler",
"oauth-providers",
"parentchain/listener",
"parentchain/api-interface",
"parentchain/rpc-client",
"parentchain/signer",
"primitives",
"rpc-server",
"executor-storage",
"solana/intent-executor",
]

Expand All @@ -38,6 +39,7 @@ log = "0.4.22"
parity-scale-codec = "3.6.12"
rand = "0.8.5"
regex = "1.7"
reqwest = { version = "0.12", features = ["json"] }
ring = "0.16.20"
rsa = "0.9.7"
scale-encode = "0.10.0"
Expand All @@ -53,21 +55,23 @@ subxt = "0.38.0"
subxt-core = "0.38.0"
subxt-signer = { version = "0.38.0", features = ["subxt"] }
tokio = "1.43.0"
url = "2.5.4"

# Local dependencies
ethereum-intent-executor = { path = "ethereum/intent-executor" }
executor-core = { path = "executor-core" }
executor-crypto = { path = "executor-crypto" }
executor-primitives = { path = "executor-primitives" }
executor-storage = { path = "executor-storage" }
heima-authentication = { path = "heima/authentication" }
heima-identity-verification = { path = "heima/identity-verification" }
heima-primitives = { package = "core-primitives", path = "../../common/primitives/core", default-features = false, features = ["std"] }
native-task-handler = { path = "native-task-handler" }
oauth-providers = { path = "oauth-providers" }
parentchain-api-interface = { path = "parentchain/api-interface" }
parentchain-listener = { path = "parentchain/listener" }
parentchain-rpc-client = { path = "parentchain/rpc-client" }
parentchain-signer = { path = "parentchain/signer" }
primitives = { path = "primitives" }
rpc-server = { path = "rpc-server" }
solana-intent-executor = { path = "solana/intent-executor" }

Expand Down
2 changes: 1 addition & 1 deletion tee-worker/omni-executor/executor-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ regex = { workspace = true }
tokio = { workspace = true }

# Local dependencies
executor-primitives = { workspace = true }
heima-authentication = { workspace = true }
primitives = { workspace = true }

[lints]
workspace = true
2 changes: 1 addition & 1 deletion tee-worker/omni-executor/executor-core/src/fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// along with Litentry. If not, see <https://www.gnu.org/licenses/>.

use async_trait::async_trait;
use primitives::GetEventId;
use executor_primitives::GetEventId;

/// Returns the last finalized block number
#[async_trait]
Expand Down
2 changes: 1 addition & 1 deletion tee-worker/omni-executor/executor-core/src/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use tokio::{runtime::Handle, sync::oneshot::Receiver};
use crate::event_handler::{Error, EventHandler};
use crate::fetcher::{EventsFetcher, LastFinalizedBlockNumFetcher};
use crate::sync_checkpoint_repository::{Checkpoint, CheckpointRepository};
use primitives::GetEventId;
use executor_primitives::GetEventId;

/// Component, used to listen to chain and execute requested intents
/// Requires specific implementations of:
Expand Down
2 changes: 1 addition & 1 deletion tee-worker/omni-executor/executor-core/src/native_call.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use executor_primitives::Identity;
use heima_authentication::auth_token::AuthOptions;
use parity_scale_codec::{Decode, Encode};
use primitives::Identity;

#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)]
#[allow(non_camel_case_types)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "primitives"
name = "executor-primitives"
version = "0.1.0"
authors = ['Trust Computing GmbH <[email protected]>']
edition.workspace = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ pub mod signature;
pub mod utils;
pub use heima_primitives::{
omni_account::{MemberAccount, OmniAccountAuthType},
BlockNumber, Hash, Identity, Nonce, ShardIdentifier, Web2IdentityType,
AccountId, BlockNumber, Hash, Identity, Nonce, ShardIdentifier, Web2IdentityType,
};
pub use sp_core::crypto::AccountId32 as AccountId;

use parity_scale_codec::{Decode, Encode};
use std::fmt::Debug;
Expand Down
2 changes: 1 addition & 1 deletion tee-worker/omni-executor/executor-storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ sp-state-machine = { workspace = true, features = ["std"] }
subxt-core = { workspace = true }

# Local dependencies
executor-primitives = { workspace = true }
parentchain-api-interface = { workspace = true }
parentchain-rpc-client = { workspace = true }
primitives = { workspace = true }

[dev-dependencies]
env_logger = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::Storage;
use executor_primitives::AccountId;
use parentchain_api_interface::omni_account::storage::types::account_store::AccountStore;
use parity_scale_codec::{Decode, Encode};
use primitives::AccountId;
use rocksdb::DB;
use std::sync::Arc;

Expand Down
4 changes: 3 additions & 1 deletion tee-worker/omni-executor/executor-storage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ mod verification_code;
pub use verification_code::VerificationCodeStorage;
mod account_store;
pub use account_store::AccountStoreStorage;
mod oauth2_state_verifier;
pub use oauth2_state_verifier::OAuth2StateVerifierStorage;

use executor_primitives::{AccountId, MemberAccount, TryFromSubxtType};
use frame_support::sp_runtime::traits::BlakeTwo256;
use frame_support::storage::storage_prefix;
use parentchain_api_interface::omni_account::storage::types::account_store::AccountStore;
use parentchain_rpc_client::{
CustomConfig, SubstrateRpcClient, SubstrateRpcClientFactory, SubxtClient, SubxtClientFactory,
};
use parity_scale_codec::Decode;
use primitives::{AccountId, MemberAccount, TryFromSubxtType};
use rocksdb::DB;
use sp_state_machine::{read_proof_check, StorageProof};
use std::sync::Arc;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::Storage;
use executor_primitives::{AccountId, Hash};
use parity_scale_codec::{Decode, Encode};
use primitives::{AccountId, Hash};
use rocksdb::DB;
use std::sync::Arc;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::Storage;
use executor_primitives::Hash;
use parity_scale_codec::{Decode, Encode};
use rocksdb::DB;
use std::sync::Arc;

const STORAGE_NAME: &[u8; 20] = b"oauth2_state_storage";

pub struct OAuth2StateVerifierStorage {
db: Arc<DB>,
}

impl OAuth2StateVerifierStorage {
pub fn new(db: Arc<DB>) -> Self {
Self { db }
}

fn storage_key(identity_hash: &Hash) -> Vec<u8> {
(STORAGE_NAME, identity_hash).encode()
}
}

impl Storage<Hash, String> for OAuth2StateVerifierStorage {
fn get(&self, identity_hash: &Hash) -> Option<String> {
match self.db.get(Self::storage_key(identity_hash)) {
Ok(Some(value)) => String::decode(&mut &value[..]).ok(),
_ => {
log::error!("Error getting oauth2_state from storage");
None
},
}
}

fn insert(&self, identity_hash: Hash, state_verifier: String) -> Result<(), ()> {
self.db
.put(Self::storage_key(&identity_hash), state_verifier.encode())
.map_err(|e| {
log::error!("Error inserting oauth2_state into storage: {:?}", e);
})
}

fn remove(&self, identity_hash: &Hash) -> Result<(), ()> {
self.db.delete(Self::storage_key(identity_hash)).map_err(|e| {
log::error!("Error removing oauth2_state from storage: {:?}", e);
})
}

fn contains_key(&self, identity_hash: &Hash) -> bool {
self.db.key_may_exist(Self::storage_key(identity_hash))
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::Storage;
use executor_primitives::Hash;
use parity_scale_codec::{Decode, Encode};
use primitives::Hash;
use rocksdb::DB;
use std::sync::Arc;

Expand Down
2 changes: 1 addition & 1 deletion tee-worker/omni-executor/heima/authentication/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ parity-scale-codec = { workspace = true }
serde = { workspace = true }

executor-crypto = { workspace = true }
primitives = { workspace = true }
executor-primitives = { workspace = true }

[lints]
workspace = true
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use executor_crypto::jwt;
use executor_primitives::BlockNumber;
use parity_scale_codec::{Decode, Encode};
use primitives::BlockNumber;
use serde::{Deserialize, Serialize};

#[derive(Debug, PartialEq)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ edition.workspace = true

[dependencies]
async-trait = { workspace = true }
base64 = { workspace = true }
log = { workspace = true }
rand = { workspace = true }
sendgrid = "0.23.0"
serde = { workspace = true }
serde_json = { workspace = true }
url = { workspace = true }

# Local dependencies
oauth-providers = { workspace = true }

[lints]
workspace = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use crate::helpers;
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
use serde::Deserialize;
use url::Url;

const BASE_URL: &str = "https://accounts.google.com/o/oauth2/v2/auth";
const SCOPES: &str = "openid email";

#[derive(Deserialize)]
pub struct IdToken {
pub iss: String,
pub azp: String,
pub email_verified: bool,
pub at_hash: String,
pub aud: String,
pub exp: u64,
pub iat: u64,
pub sub: String,
pub hd: String,
pub email: String,
}

pub struct AuthorizeData {
pub authorize_url: String,
pub state: String,
}

pub fn get_authorize_data(client_id: &str, redirect_uri: &str) -> AuthorizeData {
let state = helpers::generate_alphanumeric_otp(32);
let mut authorize_url = Url::parse(BASE_URL).expect("Failed to parse URL");
authorize_url.query_pairs_mut().extend_pairs(&[
("response_type", "code"),
("client_id", client_id),
("redirect_uri", redirect_uri),
("scope", SCOPES),
("state", &state),
]);

AuthorizeData { authorize_url: authorize_url.into(), state }
}

pub fn decode_id_token(token: &str) -> Result<IdToken, &'static str> {
let parts: Vec<&str> = token.split('.').collect();
if parts.len() != 3 {
return Err("Invalid token format");
}
let payload = base64_decode(parts[1])?;
let claims: IdToken = serde_json::from_str(&payload).map_err(|_| "Failed to parse claims")?;
Ok(claims)
}

fn base64_decode(input: &str) -> Result<String, &'static str> {
let decoded = &BASE64_URL_SAFE_NO_PAD.decode(input).map_err(|_| "Failed to decode base64")?;

Ok(String::from_utf8_lossy(decoded).to_string())
}

#[cfg(test)]
mod tests {
use super::*;
use std::format;
use url::Url;

#[test]
fn test_get_authorize_data() {
let client_id = "client_id";
let redirect_uri = "http://localhost:8080";
let authorize_data = get_authorize_data(client_id, redirect_uri);

let authorize_url = Url::parse(&authorize_data.authorize_url).unwrap();
std::println!("{:?}", authorize_url.as_str());
let expected_url = format!("https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=client_id&redirect_uri=http%3A%2F%2Flocalhost%3A8080&scope=openid+email&state={}", authorize_data.state);

assert_eq!(authorize_url.as_str(), expected_url);
}

#[test]
fn decode_id_token_works() {
let token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjM2MjgyNTg2MDExMTNlNjU3NmE0NTMzNzM2NWZlOGI4OTczZDE2NzEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI2ODYyOTM4MTAwNjktbTBhNzVwYm9mMWVwbzJzZzkyYTU3cHRtazg1c2FnbGYuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI2ODYyOTM4MTAwNjktbTBhNzVwYm9mMWVwbzJzZzkyYTU3cHRtazg1c2FnbGYuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDE2NTk5MjE1MTM4NzY4MzIwNDgiLCJoZCI6Imthd2FnYXJiby10ZWNoLmlvIiwiZW1haWwiOiJmcmFuY2lzY29Aa2F3YWdhcmJvLXRlY2guaW8iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IlBuYndCRVIzTnVBa055dFplR2wzcGciLCJpYXQiOjE3MzMyMzU4NDcsImV4cCI6MTczMzIzOTQ0N30.n4gYeYhp2U1ud4bZNW02xMJadki_93CzlcsJnr8F6eIBXwu4-CbsqToNNn40Kq780Wwz44MqnrEIU8dkBLqBc6MBWkMqzQV-RteEXMiZSOAhkNl8dIzds4vDZUnXunom4y-RYcW7yFMu_Vzpdi9A1NmgMvKVf9wqgfTJrqmPwaUh1GfgV8e7SrqHJiI3XVTE_zIxQVdjybR-7dXGh2B9LaXtA1m8v47tNkvtifa7KUw-miSIVt0of0Dq3keETLyptf8HJ1HouwpACMnxSH-Foq3r5EVp3lfGmkmf5dWMxweagsi7-hMhSKsGY2q2g3gy8xxsCaS1Q3uiB1Htw1Dn7Q";
let id_token = decode_id_token(token).unwrap();

assert_eq!(id_token.iss, "https://accounts.google.com");
assert_eq!(
id_token.azp,
"686293810069-m0a75pbof1epo2sg92a57ptmk85saglf.apps.googleusercontent.com"
);
assert!(id_token.email_verified);
assert_eq!(id_token.at_hash, "PnbwBER3NuAkNytZeGl3pg");
assert_eq!(
id_token.aud,
"686293810069-m0a75pbof1epo2sg92a57ptmk85saglf.apps.googleusercontent.com"
);
assert_eq!(id_token.exp, 1733239447);
assert_eq!(id_token.iat, 1733235847);
assert_eq!(id_token.sub, "101659921513876832048");
assert_eq!(id_token.hd, "kawagarbo-tech.io");
assert_eq!(id_token.email, "[email protected]");
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod email;
pub mod google;
2 changes: 1 addition & 1 deletion tee-worker/omni-executor/native-task-handler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ tokio = { workspace = true }
# Local dependencies
executor-core = { workspace = true }
executor-crypto = { workspace = true }
executor-primitives = { workspace = true }
executor-storage = { workspace = true }
heima-authentication = { workspace = true }
parentchain-api-interface = { workspace = true }
parentchain-rpc-client = { workspace = true }
parentchain-signer = { workspace = true }
primitives = { workspace = true }

[lints]
workspace = true
Loading

0 comments on commit a414093

Please sign in to comment.