From 5c1a358336bca4163dbe187883556aaa1223e63a Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 20 Dec 2024 18:08:01 +0100 Subject: [PATCH] Adding support for auth token authentication for trusted calls (#3192) --- local-setup/.env.dev | 4 + tee-worker/Cargo.lock | 16 ++ tee-worker/Cargo.toml | 2 + tee-worker/identity/app-libs/stf/Cargo.toml | 3 + .../identity/app-libs/stf/src/trusted_call.rs | 6 + .../identity/enclave-runtime/Cargo.lock | 16 ++ .../litentry/core/authentication/Cargo.toml | 28 +++ .../litentry/core/authentication/src/jwt.rs | 173 ++++++++++++++++++ .../litentry/core/authentication/src/lib.rs | 35 ++++ .../litentry/core/data-providers/src/lib.rs | 8 + .../core/native-task/receiver/Cargo.toml | 3 +- .../receiver/src/authentication_utils.rs | 17 +- .../core/native-task/receiver/src/lib.rs | 81 ++++++-- .../src/trusted_call_authenticated.rs | 1 + .../core/native-task/receiver/src/types.rs | 10 + 15 files changed, 386 insertions(+), 17 deletions(-) create mode 100644 tee-worker/identity/litentry/core/authentication/Cargo.toml create mode 100644 tee-worker/identity/litentry/core/authentication/src/jwt.rs create mode 100644 tee-worker/identity/litentry/core/authentication/src/lib.rs diff --git a/local-setup/.env.dev b/local-setup/.env.dev index 7d67abacd6..13cf4b7f8a 100644 --- a/local-setup/.env.dev +++ b/local-setup/.env.dev @@ -37,6 +37,10 @@ MAGIC_CRAFT_API_KEY= GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= +# The following key/token are MANDATORY to give when running worker. +# use a secure 256-bit key for JWT token generation. +JWT_SECRET= + # The followings are default value. # Can be skipped; or overwrite within non-production mode. TWITTER_OFFICIAL_URL=http://localhost:19527 diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index 41193f5a32..6dc20d7c7d 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -2752,6 +2752,7 @@ dependencies = [ "itp-storage", "itp-types", "itp-utils", + "lc-authentication", "lc-stf-task-sender", "litentry-hex-utils", "litentry-macros", @@ -4434,6 +4435,19 @@ dependencies = [ "thiserror 1.0.9", ] +[[package]] +name = "lc-authentication" +version = "0.1.0" +dependencies = [ + "base64 0.22.1", + "core-primitives", + "parity-scale-codec", + "ring 0.16.20", + "serde 1.0.210", + "serde_json 1.0.120", + "sgx_tstd", +] + [[package]] name = "lc-common" version = "0.1.0" @@ -4620,6 +4634,8 @@ dependencies = [ "itp-stf-state-handler", "itp-storage", "itp-types", + "itp-utils", + "lc-authentication", "lc-data-providers", "lc-dynamic-assertion", "lc-evm-dynamic-assertions", diff --git a/tee-worker/Cargo.toml b/tee-worker/Cargo.toml index 4ea108a167..a4e44c4ca2 100644 --- a/tee-worker/Cargo.toml +++ b/tee-worker/Cargo.toml @@ -53,6 +53,7 @@ members = [ "identity/litentry/core/data-providers", "identity/litentry/core/vc-task/sender", "identity/litentry/core/vc-task/receiver", + "identity/litentry/core/authentication", "identity/litentry/core/native-task/sender", "identity/litentry/core/native-task/receiver", "identity/litentry/core/identity-verification", @@ -284,6 +285,7 @@ lc-vc-task-receiver = { path = "identity/litentry/core/vc-task/receiver", defaul lc-omni-account = { path = "identity/litentry/core/omni-account", default-features = false } lc-native-task-sender = { path = "identity/litentry/core/native-task/sender", default-features = false } lc-native-task-receiver = { path = "identity/litentry/core/native-task/receiver", default-features = false } +lc-authentication = { path = "identity/litentry/core/authentication", default-features = false } itc-peer-top-broadcaster = { path = "identity/core/peer-top-broadcaster", default-features = false } itc-rpc-server = { path = "identity/core/rpc-server", default-features = false } diff --git a/tee-worker/identity/app-libs/stf/Cargo.toml b/tee-worker/identity/app-libs/stf/Cargo.toml index 02b7067a1b..7441efb61b 100644 --- a/tee-worker/identity/app-libs/stf/Cargo.toml +++ b/tee-worker/identity/app-libs/stf/Cargo.toml @@ -37,6 +37,7 @@ sp-std = { workspace = true } # litentry itp-node-api-metadata-provider = { workspace = true } +lc-authentication = { path = "../../litentry/core/authentication", default-features = false } lc-stf-task-sender = { path = "../../litentry/core/stf-task/sender", default-features = false } litentry-hex-utils = { workspace = true } litentry-macros = { workspace = true } @@ -56,6 +57,7 @@ sgx = [ "itp-node-api/sgx", "litentry-primitives/sgx", "lc-stf-task-sender/sgx", + "lc-authentication/sgx", "itp-node-api-metadata-provider/sgx", ] std = [ @@ -79,6 +81,7 @@ std = [ "sp-io/std", "litentry-primitives/std", "lc-stf-task-sender/std", + "lc-authentication/std", "itp-node-api-metadata-provider/std", ] test = [] diff --git a/tee-worker/identity/app-libs/stf/src/trusted_call.rs b/tee-worker/identity/app-libs/stf/src/trusted_call.rs index 0ec7a6b566..9a84fec27b 100644 --- a/tee-worker/identity/app-libs/stf/src/trusted_call.rs +++ b/tee-worker/identity/app-libs/stf/src/trusted_call.rs @@ -50,6 +50,7 @@ use itp_types::{ Moment, OpaqueCall, H256, }; use itp_utils::stringify::account_id_to_string; +use lc_authentication::AuthOptions; use litentry_hex_utils::hex_encode; pub use litentry_primitives::{ aes_encrypt_default, all_evm_web3networks, all_substrate_web3networks, AesOutput, Assertion, @@ -149,6 +150,8 @@ pub enum TrustedCall { remove_accounts(Identity, Vec), #[codec(index = 30)] publicize_account(Identity, Identity), + #[codec(index = 31)] + request_auth_token(Identity, AuthOptions), // original integritee trusted calls, starting from index 50 #[codec(index = 50)] @@ -244,6 +247,7 @@ impl TrustedCall { Self::add_account(sender_identity, ..) => sender_identity, Self::remove_accounts(sender_identity, ..) => sender_identity, Self::publicize_account(sender_identity, ..) => sender_identity, + Self::request_auth_token(sender_identity, ..) => sender_identity, } } @@ -262,6 +266,7 @@ impl TrustedCall { Self::add_account(..) => "add_account", Self::remove_accounts(..) => "remove_account", Self::publicize_account(..) => "publicize_account", + Self::request_auth_token(..) => "request_auth_token", _ => "unsupported_trusted_call", } } @@ -920,6 +925,7 @@ where | TrustedCall::create_account_store(..) | TrustedCall::add_account(..) | TrustedCall::remove_accounts(..) + | TrustedCall::request_auth_token(..) | TrustedCall::publicize_account(..) => { error!("please use author_submitNativeRequest instead"); Ok(TrustedCallResult::Empty) diff --git a/tee-worker/identity/enclave-runtime/Cargo.lock b/tee-worker/identity/enclave-runtime/Cargo.lock index c94e71cc70..ce0b886a15 100644 --- a/tee-worker/identity/enclave-runtime/Cargo.lock +++ b/tee-worker/identity/enclave-runtime/Cargo.lock @@ -1865,6 +1865,7 @@ dependencies = [ "itp-storage", "itp-types", "itp-utils", + "lc-authentication", "lc-stf-task-sender", "litentry-hex-utils", "litentry-macros", @@ -2992,6 +2993,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "lc-authentication" +version = "0.1.0" +dependencies = [ + "base64 0.22.1", + "core-primitives", + "parity-scale-codec", + "ring 0.16.20", + "serde 1.0.204", + "serde_json 1.0.120", + "sgx_tstd", +] + [[package]] name = "lc-common" version = "0.1.0" @@ -3142,6 +3156,8 @@ dependencies = [ "itp-stf-state-handler", "itp-storage", "itp-types", + "itp-utils", + "lc-authentication", "lc-data-providers", "lc-dynamic-assertion", "lc-evm-dynamic-assertions", diff --git a/tee-worker/identity/litentry/core/authentication/Cargo.toml b/tee-worker/identity/litentry/core/authentication/Cargo.toml new file mode 100644 index 0000000000..e5defc0f6e --- /dev/null +++ b/tee-worker/identity/litentry/core/authentication/Cargo.toml @@ -0,0 +1,28 @@ +[package] +authors = ["Trust Computing GmbH "] +edition = "2021" +name = "lc-authentication" +version = "0.1.0" + +[dependencies] +base64 = { version = "0.22", default-features = false, features = ["alloc"] } # a newer base64 +codec = { package = "parity-scale-codec", workspace = true } +parentchain-primitives = { workspace = true } +ring = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } + +sgx_tstd = { workspace = true, features = ["net", "thread"], optional = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "serde/std", + "serde_json/std", + "ring/std", + "parentchain-primitives/std", +] +sgx = [ + "sgx_tstd", +] diff --git a/tee-worker/identity/litentry/core/authentication/src/jwt.rs b/tee-worker/identity/litentry/core/authentication/src/jwt.rs new file mode 100644 index 0000000000..401c27e46f --- /dev/null +++ b/tee-worker/identity/litentry/core/authentication/src/jwt.rs @@ -0,0 +1,173 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{AuthOptions, BlockNumber}; +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD}; +use ring::hmac; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, PartialEq)] +pub enum Error { + InvalidToken, + InvalidSignature, + ExpiredToken, + InvalidSubject, + Base64DecodeError, + JsonError, +} + +impl From for Error { + fn from(_: base64::DecodeError) -> Self { + Error::Base64DecodeError + } +} + +#[derive(Serialize, Deserialize)] +pub struct Header { + alg: String, + typ: String, +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +pub struct Payload { + sub: String, + exp: BlockNumber, +} + +impl Payload { + pub fn new(sub: String, options: AuthOptions) -> Self { + Self { sub, exp: options.expires_at } + } +} + +pub struct Validation { + pub sub: String, + pub current_block: BlockNumber, +} + +impl Validation { + pub fn new(sub: String, current_block: BlockNumber) -> Self { + Self { sub, current_block } + } + + pub fn validate(&self, payload: &Payload) -> Result<(), Error> { + if self.sub != payload.sub { + return Err(Error::InvalidSubject) + } + + if self.current_block > payload.exp { + return Err(Error::ExpiredToken) + } + + Ok(()) + } +} + +fn base64_encode>(input: T) -> String { + BASE64_URL_SAFE_NO_PAD.encode(input) +} + +fn base64_decode>(input: T) -> Result, base64::DecodeError> { + BASE64_URL_SAFE_NO_PAD.decode(input) +} + +pub fn create(payload: &Payload, secret: &[u8]) -> Result { + let header = Header { alg: "HS256".to_string(), typ: "JWT".to_string() }; + let encoded_header = + base64_encode(&serde_json::to_string(&header).map_err(|_| Error::JsonError)?); + let encoded_payload = + base64_encode(&serde_json::to_string(&payload).map_err(|_| Error::JsonError)?); + let data = [encoded_header, encoded_payload].join("."); + let key = hmac::Key::new(hmac::HMAC_SHA256, secret); + let signature = hmac::sign(&key, data.as_bytes()); + let encoded_signature = base64_encode(signature); + + Ok([data, encoded_signature].join(".")) +} + +pub fn verify(jwt: &str, secret: &[u8], validation: Validation) -> Result<(), Error> { + let parts: Vec<&str> = jwt.split('.').collect(); + if parts.len() != 3 { + return Err(Error::InvalidToken) + } + + let data = [parts[0], parts[1]].join("."); + let key = hmac::Key::new(hmac::HMAC_SHA256, secret); + let decoded_signature = base64_decode(parts[2])?; + + hmac::verify(&key, data.as_bytes(), &decoded_signature).map_err(|_| Error::InvalidSignature)?; + let payload = base64_decode(parts[1])?; + let payload: Payload = serde_json::from_slice(&payload).map_err(|_| Error::JsonError)?; + + validation.validate(&payload) +} + +pub fn decode(jwt: &str) -> Result { + let parts: Vec<&str> = jwt.split('.').collect(); + if parts.len() != 3 { + return Err(Error::InvalidToken) + } + let payload = base64_decode(parts[1])?; + let payload: Payload = serde_json::from_slice(&payload).map_err(|_| Error::JsonError)?; + + Ok(payload) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_jwt() { + let secret = "secret".as_bytes(); + let payload = Payload::new("subject".to_string(), AuthOptions { expires_at: 10 }); + let jwt = create(&payload, secret).unwrap(); + + assert!(verify(&jwt, secret, Validation::new("subject".to_string(), 5)).is_ok()); + + let decoded_payload = decode(&jwt).unwrap(); + assert_eq!(decoded_payload, payload); + } + + #[test] + fn test_jwt_exp_validation() { + let secret = "secret".as_bytes(); + let payload = Payload::new("subject".to_string(), AuthOptions { expires_at: 10 }); + let jwt = create(&payload, secret).unwrap(); + + let current_block = 12; + let result = verify(&jwt, secret, Validation::new("subject".to_string(), current_block)); + + assert_eq!(result, Err(Error::ExpiredToken)); + } + + #[test] + fn test_jwt_sub_validation() { + let secret = "secret".as_bytes(); + let payload = Payload::new("subject".to_string(), AuthOptions { expires_at: 10 }); + let jwt = create(&payload, secret).unwrap(); + + let current_block = 5; + let result = + verify(&jwt, secret, Validation::new("other-subject".to_string(), current_block)); + + assert_eq!(result, Err(Error::InvalidSubject)); + } +} diff --git a/tee-worker/identity/litentry/core/authentication/src/lib.rs b/tee-worker/identity/litentry/core/authentication/src/lib.rs new file mode 100644 index 0000000000..7bc7f8b4ad --- /dev/null +++ b/tee-worker/identity/litentry/core/authentication/src/lib.rs @@ -0,0 +1,35 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +extern crate core; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +pub mod jwt; + +use codec::{Decode, Encode}; +use parentchain_primitives::BlockNumber; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct AuthOptions { + expires_at: BlockNumber, +} diff --git a/tee-worker/identity/litentry/core/data-providers/src/lib.rs b/tee-worker/identity/litentry/core/data-providers/src/lib.rs index b83bdeaf2e..0da216cc97 100644 --- a/tee-worker/identity/litentry/core/data-providers/src/lib.rs +++ b/tee-worker/identity/litentry/core/data-providers/src/lib.rs @@ -219,6 +219,7 @@ pub struct DataProviderConfig { pub blockchain_info_api_url: String, pub sendgrid_api_key: String, pub sendgrid_from_email: String, + pub jwt_secret: String, } impl DataProviderConfig { @@ -278,6 +279,7 @@ impl DataProviderConfig { blockchain_info_api_url: "https://blockchain.info/".to_string(), sendgrid_api_key: "".to_string(), sendgrid_from_email: "".to_string(), + jwt_secret: "".to_string(), }; // we allow to override following config properties for non prod dev @@ -435,6 +437,9 @@ impl DataProviderConfig { if let Ok(v) = env::var("SENDGRID_FROM_EMAIL") { config.set_sendgrid_from_email(v); } + if let Ok(v) = env::var("JWT_SECRET") { + config.set_jwt_secret(v); + } Ok(config) } @@ -670,6 +675,9 @@ impl DataProviderConfig { debug!("set_sendgrid_from_email: {:?}", v); self.sendgrid_from_email = v; } + pub fn set_jwt_secret(&mut self, v: String) { + self.jwt_secret = v; + } } fn check_url(v: &String) -> Result<(), Error> { diff --git a/tee-worker/identity/litentry/core/native-task/receiver/Cargo.toml b/tee-worker/identity/litentry/core/native-task/receiver/Cargo.toml index cc8b7fa5be..7342fcf09a 100644 --- a/tee-worker/identity/litentry/core/native-task/receiver/Cargo.toml +++ b/tee-worker/identity/litentry/core/native-task/receiver/Cargo.toml @@ -30,8 +30,10 @@ itp-stf-state-handler = { workspace = true } itp-storage = { workspace = true } itp-top-pool-author = { package = "id-itp-top-pool-author", path = "../../../../core-primitives/top-pool-author", default-features = false } itp-types = { workspace = true } +itp-utils = { workspace = true } frame-support = { workspace = true } +lc-authentication = { workspace = true } lc-data-providers = { workspace = true } lc-dynamic-assertion = { workspace = true } lc-evm-dynamic-assertions = { workspace = true } @@ -50,7 +52,6 @@ sgx = [ "sgx_tstd", "ita-stf/sgx", "itp-top-pool-author/sgx", - "sp-core/full_crypto", "litentry-primitives/sgx", "itp-node-api/sgx", "itp-extrinsics-factory/sgx", diff --git a/tee-worker/identity/litentry/core/native-task/receiver/src/authentication_utils.rs b/tee-worker/identity/litentry/core/native-task/receiver/src/authentication_utils.rs index 5003214b9f..980b0a8bad 100644 --- a/tee-worker/identity/litentry/core/native-task/receiver/src/authentication_utils.rs +++ b/tee-worker/identity/litentry/core/native-task/receiver/src/authentication_utils.rs @@ -2,7 +2,9 @@ use crate::VerificationCode; use alloc::{format, string::String, sync::Arc}; use codec::{Decode, Encode}; use ita_stf::{LitentryMultiSignature, TrustedCall}; -use itp_types::parentchain::Index as ParentchainIndex; +use itp_types::{parentchain::Index as ParentchainIndex, BlockNumber}; +use itp_utils::stringify::account_id_to_string_without_prefix; +use lc_authentication::jwt; use lc_data_providers::{google::GoogleOAuth2Client, DataProviderConfig}; use lc_identity_verification::web2::{email::VerificationCodeStore, google}; use lc_omni_account::InMemoryStore as OmniAccountStore; @@ -29,6 +31,7 @@ pub enum AuthenticationError { EmailVerificationCodeNotFound, EmailInvalidVerificationCode, OAuth2Error(String), + AuthTokenError(String), } pub fn verify_tca_web3_authentication( @@ -76,6 +79,18 @@ pub fn verify_tca_email_authentication( } } +pub fn verify_tca_auth_token_authentication( + omni_account: &AccountId, + current_block: BlockNumber, + auth_token: String, + secret: &[u8], +) -> Result<(), AuthenticationError> { + let expected_subject = account_id_to_string_without_prefix(&omni_account); + let validation = jwt::Validation::new(expected_subject, current_block); + jwt::verify(&auth_token, secret, validation) + .map_err(|e| AuthenticationError::AuthTokenError(format!("{:?}", e))) +} + pub fn verify_tca_oauth2_authentication( data_providers_config: Arc, sender_identity_hash: H256, diff --git a/tee-worker/identity/litentry/core/native-task/receiver/src/lib.rs b/tee-worker/identity/litentry/core/native-task/receiver/src/lib.rs index 8b226f7164..914feba597 100644 --- a/tee-worker/identity/litentry/core/native-task/receiver/src/lib.rs +++ b/tee-worker/identity/litentry/core/native-task/receiver/src/lib.rs @@ -40,8 +40,8 @@ use std::sync::SgxMutex as Mutex; mod authentication_utils; use authentication_utils::{ - verify_tca_email_authentication, verify_tca_oauth2_authentication, - verify_tca_web3_authentication, + verify_tca_auth_token_authentication, verify_tca_email_authentication, + verify_tca_oauth2_authentication, verify_tca_web3_authentication, }; mod trusted_call_handlers; @@ -83,6 +83,8 @@ use itp_types::{ parentchain::{Address, ParachainHeader, ParentchainId}, AccountId, OpaqueCall, }; +use itp_utils::stringify::account_id_to_string_without_prefix; +use lc_authentication::jwt; use lc_dynamic_assertion::AssertionLogicRepository; use lc_evm_dynamic_assertions::AssertionRepositoryItem; use lc_identity_verification::web2::verify as verify_web2_identity; @@ -211,10 +213,11 @@ where ), TCAuthentication::Email(verification_code) => { let sender_identity = tca.call.sender_identity(); - let omni_account = match get_omni_account(context.ocall_api.clone(), sender_identity) { - Ok(account) => account, - _ => sender_identity.to_omni_account(), - }; + let omni_account = + match get_omni_account(context.ocall_api.clone(), sender_identity, None) { + Ok(account) => account, + _ => sender_identity.to_omni_account(), + }; verify_tca_email_authentication( sender_identity.hash(), &omni_account, @@ -223,10 +226,11 @@ where }, TCAuthentication::OAuth2(oauth2_data) => { let sender_identity = tca.call.sender_identity(); - let omni_account = match get_omni_account(context.ocall_api.clone(), sender_identity) { - Ok(account) => account, - _ => sender_identity.to_omni_account(), - }; + let omni_account = + match get_omni_account(context.ocall_api.clone(), sender_identity, None) { + Ok(account) => account, + _ => sender_identity.to_omni_account(), + }; verify_tca_oauth2_authentication( context.data_provider_config.clone(), sender_identity.hash(), @@ -234,6 +238,26 @@ where oauth2_data, ) }, + TCAuthentication::AuthToken(auth_token) => { + let Ok(header)= context.ocall_api.get_header::() else { + let res: Result<(), TrustedCallError> = Err(TrustedCallError::ParentchainHeaderRetrievalFailed); + context.author_api.send_rpc_response(connection_hash, res.encode(), false); + return Err("Failed to get parachain header") + }; + let current_block = header.number; + let sender_identity = tca.call.sender_identity(); + let omni_account = + match get_omni_account(context.ocall_api.clone(), sender_identity, Some(header)) { + Ok(account) => account, + _ => sender_identity.to_omni_account(), + }; + verify_tca_auth_token_authentication( + &omni_account, + current_block, + auth_token, + context.data_provider_config.jwt_secret.as_bytes(), + ) + }, }; match authentication_result { @@ -324,7 +348,7 @@ fn handle_trusted_call { - let omni_account = match get_omni_account(context.ocall_api.clone(), &who) { + let omni_account = match get_omni_account(context.ocall_api.clone(), &who, None) { Ok(account) => account, Err(e) => { log::error!("Failed to get omni account: {:?}", e); @@ -530,6 +554,29 @@ fn handle_trusted_call { + let omni_account = match get_omni_account(context.ocall_api.clone(), &who, None) { + Ok(account) => account, + Err(e) => { + log::error!("Failed to get omni account: {:?}", e); + let result: TrustedCallResult = Err(TrustedCallError::UnauthorizedSigner); + context.author_api.send_rpc_response(connection_hash, result.encode(), false); + return + }, + }; + let subject = account_id_to_string_without_prefix(&omni_account); + let payload = jwt::Payload::new(subject, auth_options); + let Ok(auth_token) = jwt::create(&payload, context.data_provider_config.jwt_secret.as_bytes()) else { + log::error!("Failed to create jwt token"); + let result: TrustedCallResult = Err(TrustedCallError::AuthTokenCreationFailed); + context.author_api.send_rpc_response(connection_hash, result.encode(), false); + return + }; + + let result: TrustedCallResult = Ok(auth_token.into()); + context.author_api.send_rpc_response(connection_hash, result.encode(), false); + return + }, _ => { log::warn!("Received unsupported call: {:?}", call); let result: TrustedCallResult = @@ -608,15 +655,19 @@ where fn get_omni_account( ocall_api: Arc, who: &Identity, + header: Option, ) -> Result { let omni_account = match OmniAccountStore::get_omni_account(who.hash()) { Ok(Some(account)) => account, _ => { log::warn!("Failed to get omni account from the in-memory store"); - let header: ParachainHeader = ocall_api.get_header().map_err(|_| { - log::error!("Failed to get header"); - "Failed to get header" - })?; + let header = match header { + Some(h) => h, + None => ocall_api.get_header().map_err(|_| { + log::error!("Failed to get header"); + "Failed to get header" + })?, + }; OmniAccountRepository::new(ocall_api) .with_header(header) .get_account_by_member_hash(who.hash()) diff --git a/tee-worker/identity/litentry/core/native-task/receiver/src/trusted_call_authenticated.rs b/tee-worker/identity/litentry/core/native-task/receiver/src/trusted_call_authenticated.rs index 73a9fa0ac3..98e919dda5 100644 --- a/tee-worker/identity/litentry/core/native-task/receiver/src/trusted_call_authenticated.rs +++ b/tee-worker/identity/litentry/core/native-task/receiver/src/trusted_call_authenticated.rs @@ -33,6 +33,7 @@ pub enum TCAuthentication { Web3(LitentryMultiSignature), Email(VerificationCode), OAuth2(OAuth2Data), + AuthToken(String), } #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] diff --git a/tee-worker/identity/litentry/core/native-task/receiver/src/types.rs b/tee-worker/identity/litentry/core/native-task/receiver/src/types.rs index 75b3812f91..2e932429f0 100644 --- a/tee-worker/identity/litentry/core/native-task/receiver/src/types.rs +++ b/tee-worker/identity/litentry/core/native-task/receiver/src/types.rs @@ -129,6 +129,9 @@ pub enum TrustedCallError { ExtrinsicConstructionFailed(String), // Stringified itp_extrinsics_factory::Error ExtrinsicSendingFailed(String), // Stringified sgx_status_t InvalidRequest, + NativeRequestSendFailed, + AuthTokenCreationFailed, + ParentchainHeaderRetrievalFailed, } #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] @@ -148,6 +151,7 @@ pub enum TrustedCallOk { idx: u8, len: u8, }, + AuthToken(String), } impl From<&ExtrinsicReport> for TrustedCallOk { @@ -160,6 +164,12 @@ impl From<&ExtrinsicReport> for TrustedCallOk } } +impl From for TrustedCallOk { + fn from(auth_token: String) -> Self { + TrustedCallOk::AuthToken(auth_token) + } +} + impl From for TrustedCallOk { fn from(result: RequestVcResultOrError) -> Self { TrustedCallOk::RequestVcResult { result: result.result, idx: result.idx, len: result.len }