Skip to content

Commit 06f0c71

Browse files
authored
Adding support for oauth2 trusted call authentication (#3189)
1 parent d68ffef commit 06f0c71

File tree

18 files changed

+549
-92
lines changed

18 files changed

+549
-92
lines changed

common/primitives/core/src/identity.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,36 @@ impl Identity {
524524
self.using_encoded(blake2_256).into()
525525
}
526526

527-
pub fn from_email(email: &str) -> Self {
528-
Identity::Email(IdentityString::new(email.as_bytes().to_vec()))
527+
pub fn from_web2_account(handle: &str, identity_type: Web2IdentityType) -> Self {
528+
match identity_type {
529+
Web2IdentityType::Twitter => {
530+
Identity::Twitter(IdentityString::new(handle.as_bytes().to_vec()))
531+
}
532+
Web2IdentityType::Discord => {
533+
Identity::Discord(IdentityString::new(handle.as_bytes().to_vec()))
534+
}
535+
Web2IdentityType::Github => {
536+
Identity::Github(IdentityString::new(handle.as_bytes().to_vec()))
537+
}
538+
Web2IdentityType::Email => {
539+
Identity::Email(IdentityString::new(handle.as_bytes().to_vec()))
540+
}
541+
Web2IdentityType::Google => {
542+
Identity::Google(IdentityString::new(handle.as_bytes().to_vec()))
543+
}
544+
}
529545
}
530546
}
531547

548+
#[derive(Clone, Debug, PartialEq, Eq)]
549+
pub enum Web2IdentityType {
550+
Twitter,
551+
Discord,
552+
Github,
553+
Email,
554+
Google,
555+
}
556+
532557
impl From<ed25519::Public> for Identity {
533558
fn from(value: ed25519::Public) -> Self {
534559
Identity::Substrate(value.into())

local-setup/.env.dev

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ NODE_ENV=local
2121
## -----------------------------------
2222

2323
# The following key/token are MANDATORY to give when running worker.
24-
# Otherwise request-vc might suffering from data provider error.
24+
# Otherwise request-vc might suffering from data provider error and OAuth2 verification will not work.
2525
TWITTER_AUTH_TOKEN_V2=
2626
TWITTER_CLIENT_ID=
2727
TWITTER_CLIENT_SECRET=
@@ -34,6 +34,8 @@ NODEREAL_API_KEY=
3434
GENIIDATA_API_KEY=
3535
MORALIS_API_KEY=
3636
MAGIC_CRAFT_API_KEY=
37+
GOOGLE_CLIENT_ID=
38+
GOOGLE_CLIENT_SECRET=
3739

3840
# The followings are default value.
3941
# Can be skipped; or overwrite within non-production mode.

tee-worker/Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tee-worker/identity/enclave-runtime/Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tee-worker/identity/enclave-runtime/src/rpc/common_api.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,12 @@ use jsonrpc_core::{serde_json::json, IoHandler, Params, Value};
3333
use lc_data_providers::DataProviderConfig;
3434
use lc_identity_verification::{
3535
generate_verification_code,
36-
web2::{email, twitter},
37-
VerificationCodeStore,
36+
web2::{email, google, twitter},
3837
};
3938
use litentry_macros::{if_development, if_development_or};
40-
use litentry_primitives::{aes_decrypt, AesRequest, DecryptableRequest, Identity};
39+
use litentry_primitives::{
40+
aes_decrypt, AesRequest, DecryptableRequest, Identity, Web2IdentityType,
41+
};
4142
use log::debug;
4243
use sgx_crypto_helper::rsa3072::Rsa3072PubKey;
4344
use sp_core::Pair;
@@ -466,6 +467,39 @@ pub fn add_common_api<Author, GetterExecutor, AccessShieldingKey, OcallApi, Stat
466467
}
467468
});
468469

470+
let google_client_id = data_provider_config.google_client_id.clone();
471+
472+
io_handler.add_sync_method("omni_getOAuth2GoogleAuthorizationUrl", move |params: Params| {
473+
match params.parse::<(String, String, String)>() {
474+
Ok((encoded_omni_account, google_account, redirect_uri)) => {
475+
let omni_account = match AccountId::from_hex(encoded_omni_account.as_str()) {
476+
Ok(account_id) => account_id,
477+
Err(_) =>
478+
return Ok(json!(compute_hex_encoded_return_error(
479+
"Could not parse omni account"
480+
))),
481+
};
482+
let google_identity =
483+
Identity::from_web2_account(&google_account, Web2IdentityType::Google);
484+
let state = generate_verification_code();
485+
let authorize_data = google::get_authorize_data(&google_client_id, &redirect_uri);
486+
487+
match google::OAuthStateStore::insert(omni_account, google_identity.hash(), state) {
488+
Ok(_) => {
489+
let json_value = RpcReturnValue::new(
490+
authorize_data.authorize_url.encode(),
491+
false,
492+
DirectRequestStatus::Ok,
493+
);
494+
Ok(json!(json_value.to_hex()))
495+
},
496+
Err(_) => Ok(json!(compute_hex_encoded_return_error("Could not save state"))),
497+
}
498+
},
499+
Err(_) => Ok(json!(compute_hex_encoded_return_error("Could not parse params"))),
500+
}
501+
});
502+
469503
io_handler.add_sync_method("omni_requestEmailVerificationCode", move |params: Params| {
470504
match params.parse::<(String, String)>() {
471505
Ok((encoded_omni_account, email)) => {
@@ -481,9 +515,9 @@ pub fn add_common_api<Author, GetterExecutor, AccessShieldingKey, OcallApi, Stat
481515
data_provider_config.sendgrid_from_email.clone(),
482516
);
483517
let verification_code = generate_verification_code();
484-
let email_identity = Identity::from_email(&email);
518+
let email_identity = Identity::from_web2_account(&email, Web2IdentityType::Email);
485519

486-
match VerificationCodeStore::insert(
520+
match email::VerificationCodeStore::insert(
487521
omni_account,
488522
email_identity.hash(),
489523
verification_code.clone(),
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2020-2024 Trust Computing GmbH.
2+
// This file is part of Litentry.
3+
//
4+
// Litentry is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Litentry is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Litentry. If not, see <https://www.gnu.org/licenses/>.
16+
17+
use crate::{build_client_with_cert, format, Error, Headers, HttpError, String, ToString};
18+
use itc_rest_client::{
19+
http_client::{HttpClient, SendWithCertificateVerification},
20+
rest_client::RestClient,
21+
RestPath,
22+
};
23+
use serde::{Deserialize, Serialize};
24+
use std::collections::HashMap;
25+
26+
const OAUTH2_BASE_URL: &str = "https://oauth2.googleapis.com";
27+
28+
#[derive(Debug, Serialize, Deserialize, Clone)]
29+
pub struct GoogleOAuth2TokenResponse {
30+
access_token: String,
31+
expires_in: u64,
32+
id_token: String,
33+
scope: String,
34+
token_type: String,
35+
}
36+
37+
impl RestPath<String> for GoogleOAuth2TokenResponse {
38+
fn get_path(path: String) -> Result<String, HttpError> {
39+
Ok(path)
40+
}
41+
}
42+
43+
pub struct GoogleOAuth2Client {
44+
client: RestClient<HttpClient<SendWithCertificateVerification>>,
45+
client_id: String,
46+
client_secret: String,
47+
}
48+
49+
impl GoogleOAuth2Client {
50+
pub fn new(client_id: String, client_secret: String) -> Self {
51+
let client = build_client_with_cert(OAUTH2_BASE_URL, Headers::new());
52+
Self { client, client_id, client_secret }
53+
}
54+
55+
pub fn exchange_code_for_token(
56+
&mut self,
57+
code: String,
58+
redirect_uri: String,
59+
) -> Result<String, Error> {
60+
let path = String::from("/token");
61+
62+
let mut body = HashMap::new();
63+
body.insert("code".to_string(), code);
64+
body.insert("client_id".to_string(), self.client_id.clone());
65+
body.insert("client_secret".to_string(), self.client_secret.clone());
66+
body.insert("redirect_uri".to_string(), redirect_uri);
67+
body.insert("grant_type".to_string(), "authorization_code".to_string());
68+
69+
let response = self
70+
.client
71+
.post_form_urlencoded_capture::<String, GoogleOAuth2TokenResponse>(path, body)
72+
.map_err(|e| Error::RequestError(format!("{:?}", e)))?;
73+
74+
Ok(response.id_token)
75+
}
76+
}

tee-worker/identity/litentry/core/data-providers/src/lib.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#![allow(clippy::large_enum_variant)]
1919
#![allow(clippy::result_large_err)]
2020

21+
extern crate alloc;
2122
extern crate core;
2223
#[cfg(all(not(feature = "std"), feature = "sgx"))]
2324
extern crate sgx_tstd as std;
@@ -34,6 +35,12 @@ pub mod sgx_reexport_prelude {
3435
#[cfg(all(not(feature = "std"), feature = "sgx"))]
3536
use crate::sgx_reexport_prelude::*;
3637

38+
use alloc::{
39+
format,
40+
string::{String, ToString},
41+
vec,
42+
vec::Vec,
43+
};
3744
use codec::{Decode, Encode};
3845
use core::time::Duration;
3946
use http_req::response::Headers;
@@ -43,19 +50,13 @@ use itc_rest_client::{
4350
rest_client::RestClient,
4451
Query, RestGet, RestPath, RestPost,
4552
};
46-
use log::debug;
47-
use serde::{Deserialize, Serialize};
48-
use std::{thread, vec};
49-
5053
use litentry_primitives::{
5154
AchainableParams, Assertion, ErrorDetail, ErrorString, IntoErrorDetail, ParameterString,
5255
VCMPError,
5356
};
54-
use std::{
55-
env, format,
56-
string::{String, ToString},
57-
vec::Vec,
58-
};
57+
use log::debug;
58+
use serde::{Deserialize, Serialize};
59+
use std::{env, thread};
5960
use url::Url;
6061

6162
#[cfg(all(feature = "std", feature = "sgx"))]
@@ -68,6 +69,7 @@ pub mod daren_market;
6869
pub mod discord_litentry;
6970
pub mod discord_official;
7071
pub mod geniidata;
72+
pub mod google;
7173
pub mod karat_dao;
7274
pub mod magic_craft;
7375
pub mod moralis;
@@ -174,6 +176,8 @@ pub struct DataProviderConfig {
174176
pub discord_official_url: String,
175177
pub discord_client_id: String,
176178
pub discord_client_secret: String,
179+
pub google_client_id: String,
180+
pub google_client_secret: String,
177181
pub litentry_discord_microservice_url: String,
178182
pub discord_auth_token: String,
179183
pub achainable_url: String,
@@ -230,6 +234,8 @@ impl DataProviderConfig {
230234
discord_official_url: "https://discordapp.com".to_string(),
231235
discord_client_id: "".to_string(),
232236
discord_client_secret: "".to_string(),
237+
google_client_id: "".to_string(),
238+
google_client_secret: "".to_string(),
233239
litentry_discord_microservice_url: "https://tee-microservice.litentry.io:9528"
234240
.to_string(),
235241
discord_auth_token: "".to_string(),
@@ -399,6 +405,12 @@ impl DataProviderConfig {
399405
if let Ok(v) = env::var("DISCORD_CLIENT_SECRET") {
400406
config.set_discord_client_secret(v);
401407
}
408+
if let Ok(v) = env::var("GOOGLE_CLIENT_ID") {
409+
config.set_google_client_id(v);
410+
}
411+
if let Ok(v) = env::var("GOOGLE_CLIENT_SECRET") {
412+
config.set_google_client_secret(v);
413+
}
402414
if let Ok(v) = env::var("ACHAINABLE_AUTH_KEY") {
403415
config.set_achainable_auth_key(v);
404416
}
@@ -458,6 +470,14 @@ impl DataProviderConfig {
458470
debug!("set_discord_client_secret: {:?}", v);
459471
self.discord_client_secret = v;
460472
}
473+
pub fn set_google_client_id(&mut self, v: String) {
474+
debug!("set_google_client_id: {:?}", v);
475+
self.google_client_id = v;
476+
}
477+
pub fn set_google_client_secret(&mut self, v: String) {
478+
debug!("set_google_client_secret: {:?}", v);
479+
self.google_client_secret = v;
480+
}
461481
pub fn set_litentry_discord_microservice_url(&mut self, v: String) -> Result<(), Error> {
462482
check_url(&v)?;
463483
debug!("set_litentry_discord_microservice_url: {:?}", v);

tee-worker/identity/litentry/core/identity-verification/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#![cfg_attr(not(feature = "std"), no_std)]
1818

19-
pub extern crate alloc;
19+
extern crate alloc;
2020

2121
#[cfg(all(not(feature = "std"), feature = "sgx"))]
2222
extern crate sgx_tstd as std;
@@ -35,9 +35,7 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam
3535

3636
mod error;
3737
mod helpers;
38-
mod verification_code_store;
3938
pub mod web2;
40-
pub use verification_code_store::VerificationCodeStore;
4139

4240
use alloc::string::String;
4341
use error::{Error, Result};

tee-worker/identity/litentry/core/identity-verification/src/web2/email/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
mod verification_code_store;
2+
pub use verification_code_store::*;
13
mod mailer;
24
pub use mailer::*;
35

0 commit comments

Comments
 (0)