Skip to content

Commit a414093

Browse files
authored
Adding support for google oauth2 authentication in the omni-executor (#3244)
1 parent 60105a2 commit a414093

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+744
-116
lines changed

tee-worker/omni-executor/Cargo.lock

+342-39
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tee-worker/omni-executor/Cargo.toml

+7-3
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ members = [
33
"executor-crypto",
44
"executor-core",
55
"executor-worker",
6+
"executor-storage",
7+
"executor-primitives",
68
"ethereum/intent-executor",
79
"ethereum/intent-executor",
810
"heima/authentication",
911
"heima/identity-verification",
1012
"native-task-handler",
13+
"oauth-providers",
1114
"parentchain/listener",
1215
"parentchain/api-interface",
1316
"parentchain/rpc-client",
1417
"parentchain/signer",
15-
"primitives",
1618
"rpc-server",
17-
"executor-storage",
1819
"solana/intent-executor",
1920
]
2021

@@ -38,6 +39,7 @@ log = "0.4.22"
3839
parity-scale-codec = "3.6.12"
3940
rand = "0.8.5"
4041
regex = "1.7"
42+
reqwest = { version = "0.12", features = ["json"] }
4143
ring = "0.16.20"
4244
rsa = "0.9.7"
4345
scale-encode = "0.10.0"
@@ -53,21 +55,23 @@ subxt = "0.38.0"
5355
subxt-core = "0.38.0"
5456
subxt-signer = { version = "0.38.0", features = ["subxt"] }
5557
tokio = "1.43.0"
58+
url = "2.5.4"
5659

5760
# Local dependencies
5861
ethereum-intent-executor = { path = "ethereum/intent-executor" }
5962
executor-core = { path = "executor-core" }
6063
executor-crypto = { path = "executor-crypto" }
64+
executor-primitives = { path = "executor-primitives" }
6165
executor-storage = { path = "executor-storage" }
6266
heima-authentication = { path = "heima/authentication" }
6367
heima-identity-verification = { path = "heima/identity-verification" }
6468
heima-primitives = { package = "core-primitives", path = "../../common/primitives/core", default-features = false, features = ["std"] }
6569
native-task-handler = { path = "native-task-handler" }
70+
oauth-providers = { path = "oauth-providers" }
6671
parentchain-api-interface = { path = "parentchain/api-interface" }
6772
parentchain-listener = { path = "parentchain/listener" }
6873
parentchain-rpc-client = { path = "parentchain/rpc-client" }
6974
parentchain-signer = { path = "parentchain/signer" }
70-
primitives = { path = "primitives" }
7175
rpc-server = { path = "rpc-server" }
7276
solana-intent-executor = { path = "solana/intent-executor" }
7377

tee-worker/omni-executor/executor-core/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ regex = { workspace = true }
1212
tokio = { workspace = true }
1313

1414
# Local dependencies
15+
executor-primitives = { workspace = true }
1516
heima-authentication = { workspace = true }
16-
primitives = { workspace = true }
1717

1818
[lints]
1919
workspace = true

tee-worker/omni-executor/executor-core/src/fetcher.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// along with Litentry. If not, see <https://www.gnu.org/licenses/>.
1616

1717
use async_trait::async_trait;
18-
use primitives::GetEventId;
18+
use executor_primitives::GetEventId;
1919

2020
/// Returns the last finalized block number
2121
#[async_trait]

tee-worker/omni-executor/executor-core/src/listener.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use tokio::{runtime::Handle, sync::oneshot::Receiver};
2222
use crate::event_handler::{Error, EventHandler};
2323
use crate::fetcher::{EventsFetcher, LastFinalizedBlockNumFetcher};
2424
use crate::sync_checkpoint_repository::{Checkpoint, CheckpointRepository};
25-
use primitives::GetEventId;
25+
use executor_primitives::GetEventId;
2626

2727
/// Component, used to listen to chain and execute requested intents
2828
/// Requires specific implementations of:

tee-worker/omni-executor/executor-core/src/native_call.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
use executor_primitives::Identity;
12
use heima_authentication::auth_token::AuthOptions;
23
use parity_scale_codec::{Decode, Encode};
3-
use primitives::Identity;
44

55
#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)]
66
#[allow(non_camel_case_types)]

tee-worker/omni-executor/primitives/Cargo.toml tee-worker/omni-executor/executor-primitives/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "primitives"
2+
name = "executor-primitives"
33
version = "0.1.0"
44
authors = ['Trust Computing GmbH <[email protected]>']
55
edition.workspace = true

tee-worker/omni-executor/primitives/src/lib.rs tee-worker/omni-executor/executor-primitives/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ pub mod signature;
1818
pub mod utils;
1919
pub use heima_primitives::{
2020
omni_account::{MemberAccount, OmniAccountAuthType},
21-
BlockNumber, Hash, Identity, Nonce, ShardIdentifier, Web2IdentityType,
21+
AccountId, BlockNumber, Hash, Identity, Nonce, ShardIdentifier, Web2IdentityType,
2222
};
23-
pub use sp_core::crypto::AccountId32 as AccountId;
2423

2524
use parity_scale_codec::{Decode, Encode};
2625
use std::fmt::Debug;

tee-worker/omni-executor/executor-storage/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ sp-state-machine = { workspace = true, features = ["std"] }
1313
subxt-core = { workspace = true }
1414

1515
# Local dependencies
16+
executor-primitives = { workspace = true }
1617
parentchain-api-interface = { workspace = true }
1718
parentchain-rpc-client = { workspace = true }
18-
primitives = { workspace = true }
1919

2020
[dev-dependencies]
2121
env_logger = { workspace = true }

tee-worker/omni-executor/executor-storage/src/account_store.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::Storage;
2+
use executor_primitives::AccountId;
23
use parentchain_api_interface::omni_account::storage::types::account_store::AccountStore;
34
use parity_scale_codec::{Decode, Encode};
4-
use primitives::AccountId;
55
use rocksdb::DB;
66
use std::sync::Arc;
77

tee-worker/omni-executor/executor-storage/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ mod verification_code;
44
pub use verification_code::VerificationCodeStorage;
55
mod account_store;
66
pub use account_store::AccountStoreStorage;
7+
mod oauth2_state_verifier;
8+
pub use oauth2_state_verifier::OAuth2StateVerifierStorage;
79

10+
use executor_primitives::{AccountId, MemberAccount, TryFromSubxtType};
811
use frame_support::sp_runtime::traits::BlakeTwo256;
912
use frame_support::storage::storage_prefix;
1013
use parentchain_api_interface::omni_account::storage::types::account_store::AccountStore;
1114
use parentchain_rpc_client::{
1215
CustomConfig, SubstrateRpcClient, SubstrateRpcClientFactory, SubxtClient, SubxtClientFactory,
1316
};
1417
use parity_scale_codec::Decode;
15-
use primitives::{AccountId, MemberAccount, TryFromSubxtType};
1618
use rocksdb::DB;
1719
use sp_state_machine::{read_proof_check, StorageProof};
1820
use std::sync::Arc;

tee-worker/omni-executor/executor-storage/src/member_omni_account.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::Storage;
2+
use executor_primitives::{AccountId, Hash};
23
use parity_scale_codec::{Decode, Encode};
3-
use primitives::{AccountId, Hash};
44
use rocksdb::DB;
55
use std::sync::Arc;
66

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use crate::Storage;
2+
use executor_primitives::Hash;
3+
use parity_scale_codec::{Decode, Encode};
4+
use rocksdb::DB;
5+
use std::sync::Arc;
6+
7+
const STORAGE_NAME: &[u8; 20] = b"oauth2_state_storage";
8+
9+
pub struct OAuth2StateVerifierStorage {
10+
db: Arc<DB>,
11+
}
12+
13+
impl OAuth2StateVerifierStorage {
14+
pub fn new(db: Arc<DB>) -> Self {
15+
Self { db }
16+
}
17+
18+
fn storage_key(identity_hash: &Hash) -> Vec<u8> {
19+
(STORAGE_NAME, identity_hash).encode()
20+
}
21+
}
22+
23+
impl Storage<Hash, String> for OAuth2StateVerifierStorage {
24+
fn get(&self, identity_hash: &Hash) -> Option<String> {
25+
match self.db.get(Self::storage_key(identity_hash)) {
26+
Ok(Some(value)) => String::decode(&mut &value[..]).ok(),
27+
_ => {
28+
log::error!("Error getting oauth2_state from storage");
29+
None
30+
},
31+
}
32+
}
33+
34+
fn insert(&self, identity_hash: Hash, state_verifier: String) -> Result<(), ()> {
35+
self.db
36+
.put(Self::storage_key(&identity_hash), state_verifier.encode())
37+
.map_err(|e| {
38+
log::error!("Error inserting oauth2_state into storage: {:?}", e);
39+
})
40+
}
41+
42+
fn remove(&self, identity_hash: &Hash) -> Result<(), ()> {
43+
self.db.delete(Self::storage_key(identity_hash)).map_err(|e| {
44+
log::error!("Error removing oauth2_state from storage: {:?}", e);
45+
})
46+
}
47+
48+
fn contains_key(&self, identity_hash: &Hash) -> bool {
49+
self.db.key_may_exist(Self::storage_key(identity_hash))
50+
}
51+
}

tee-worker/omni-executor/executor-storage/src/verification_code.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::Storage;
2+
use executor_primitives::Hash;
23
use parity_scale_codec::{Decode, Encode};
3-
use primitives::Hash;
44
use rocksdb::DB;
55
use std::sync::Arc;
66

tee-worker/omni-executor/heima/authentication/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ parity-scale-codec = { workspace = true }
1010
serde = { workspace = true }
1111

1212
executor-crypto = { workspace = true }
13-
primitives = { workspace = true }
13+
executor-primitives = { workspace = true }
1414

1515
[lints]
1616
workspace = true

tee-worker/omni-executor/heima/authentication/src/auth_token.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use executor_crypto::jwt;
2+
use executor_primitives::BlockNumber;
23
use parity_scale_codec::{Decode, Encode};
3-
use primitives::BlockNumber;
44
use serde::{Deserialize, Serialize};
55

66
#[derive(Debug, PartialEq)]

tee-worker/omni-executor/heima/identity-verification/Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ edition.workspace = true
66

77
[dependencies]
88
async-trait = { workspace = true }
9+
base64 = { workspace = true }
910
log = { workspace = true }
1011
rand = { workspace = true }
1112
sendgrid = "0.23.0"
13+
serde = { workspace = true }
14+
serde_json = { workspace = true }
15+
url = { workspace = true }
1216

17+
# Local dependencies
18+
oauth-providers = { workspace = true }
1319

1420
[lints]
1521
workspace = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
use crate::helpers;
2+
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
3+
use serde::Deserialize;
4+
use url::Url;
5+
6+
const BASE_URL: &str = "https://accounts.google.com/o/oauth2/v2/auth";
7+
const SCOPES: &str = "openid email";
8+
9+
#[derive(Deserialize)]
10+
pub struct IdToken {
11+
pub iss: String,
12+
pub azp: String,
13+
pub email_verified: bool,
14+
pub at_hash: String,
15+
pub aud: String,
16+
pub exp: u64,
17+
pub iat: u64,
18+
pub sub: String,
19+
pub hd: String,
20+
pub email: String,
21+
}
22+
23+
pub struct AuthorizeData {
24+
pub authorize_url: String,
25+
pub state: String,
26+
}
27+
28+
pub fn get_authorize_data(client_id: &str, redirect_uri: &str) -> AuthorizeData {
29+
let state = helpers::generate_alphanumeric_otp(32);
30+
let mut authorize_url = Url::parse(BASE_URL).expect("Failed to parse URL");
31+
authorize_url.query_pairs_mut().extend_pairs(&[
32+
("response_type", "code"),
33+
("client_id", client_id),
34+
("redirect_uri", redirect_uri),
35+
("scope", SCOPES),
36+
("state", &state),
37+
]);
38+
39+
AuthorizeData { authorize_url: authorize_url.into(), state }
40+
}
41+
42+
pub fn decode_id_token(token: &str) -> Result<IdToken, &'static str> {
43+
let parts: Vec<&str> = token.split('.').collect();
44+
if parts.len() != 3 {
45+
return Err("Invalid token format");
46+
}
47+
let payload = base64_decode(parts[1])?;
48+
let claims: IdToken = serde_json::from_str(&payload).map_err(|_| "Failed to parse claims")?;
49+
Ok(claims)
50+
}
51+
52+
fn base64_decode(input: &str) -> Result<String, &'static str> {
53+
let decoded = &BASE64_URL_SAFE_NO_PAD.decode(input).map_err(|_| "Failed to decode base64")?;
54+
55+
Ok(String::from_utf8_lossy(decoded).to_string())
56+
}
57+
58+
#[cfg(test)]
59+
mod tests {
60+
use super::*;
61+
use std::format;
62+
use url::Url;
63+
64+
#[test]
65+
fn test_get_authorize_data() {
66+
let client_id = "client_id";
67+
let redirect_uri = "http://localhost:8080";
68+
let authorize_data = get_authorize_data(client_id, redirect_uri);
69+
70+
let authorize_url = Url::parse(&authorize_data.authorize_url).unwrap();
71+
std::println!("{:?}", authorize_url.as_str());
72+
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);
73+
74+
assert_eq!(authorize_url.as_str(), expected_url);
75+
}
76+
77+
#[test]
78+
fn decode_id_token_works() {
79+
let token = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjM2MjgyNTg2MDExMTNlNjU3NmE0NTMzNzM2NWZlOGI4OTczZDE2NzEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI2ODYyOTM4MTAwNjktbTBhNzVwYm9mMWVwbzJzZzkyYTU3cHRtazg1c2FnbGYuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI2ODYyOTM4MTAwNjktbTBhNzVwYm9mMWVwbzJzZzkyYTU3cHRtazg1c2FnbGYuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDE2NTk5MjE1MTM4NzY4MzIwNDgiLCJoZCI6Imthd2FnYXJiby10ZWNoLmlvIiwiZW1haWwiOiJmcmFuY2lzY29Aa2F3YWdhcmJvLXRlY2guaW8iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IlBuYndCRVIzTnVBa055dFplR2wzcGciLCJpYXQiOjE3MzMyMzU4NDcsImV4cCI6MTczMzIzOTQ0N30.n4gYeYhp2U1ud4bZNW02xMJadki_93CzlcsJnr8F6eIBXwu4-CbsqToNNn40Kq780Wwz44MqnrEIU8dkBLqBc6MBWkMqzQV-RteEXMiZSOAhkNl8dIzds4vDZUnXunom4y-RYcW7yFMu_Vzpdi9A1NmgMvKVf9wqgfTJrqmPwaUh1GfgV8e7SrqHJiI3XVTE_zIxQVdjybR-7dXGh2B9LaXtA1m8v47tNkvtifa7KUw-miSIVt0of0Dq3keETLyptf8HJ1HouwpACMnxSH-Foq3r5EVp3lfGmkmf5dWMxweagsi7-hMhSKsGY2q2g3gy8xxsCaS1Q3uiB1Htw1Dn7Q";
80+
let id_token = decode_id_token(token).unwrap();
81+
82+
assert_eq!(id_token.iss, "https://accounts.google.com");
83+
assert_eq!(
84+
id_token.azp,
85+
"686293810069-m0a75pbof1epo2sg92a57ptmk85saglf.apps.googleusercontent.com"
86+
);
87+
assert!(id_token.email_verified);
88+
assert_eq!(id_token.at_hash, "PnbwBER3NuAkNytZeGl3pg");
89+
assert_eq!(
90+
id_token.aud,
91+
"686293810069-m0a75pbof1epo2sg92a57ptmk85saglf.apps.googleusercontent.com"
92+
);
93+
assert_eq!(id_token.exp, 1733239447);
94+
assert_eq!(id_token.iat, 1733235847);
95+
assert_eq!(id_token.sub, "101659921513876832048");
96+
assert_eq!(id_token.hd, "kawagarbo-tech.io");
97+
assert_eq!(id_token.email, "[email protected]");
98+
}
99+
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod email;
2+
pub mod google;

tee-worker/omni-executor/native-task-handler/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ tokio = { workspace = true }
1212
# Local dependencies
1313
executor-core = { workspace = true }
1414
executor-crypto = { workspace = true }
15+
executor-primitives = { workspace = true }
1516
executor-storage = { workspace = true }
1617
heima-authentication = { workspace = true }
1718
parentchain-api-interface = { workspace = true }
1819
parentchain-rpc-client = { workspace = true }
1920
parentchain-signer = { workspace = true }
20-
primitives = { workspace = true }
2121

2222
[lints]
2323
workspace = true

0 commit comments

Comments
 (0)