Skip to content

Commit

Permalink
add config for new providers (#737)
Browse files Browse the repository at this point in the history
* feat: add new providers to zklogin

* updates
  • Loading branch information
joyqvq committed May 20, 2024
1 parent 6748c18 commit 1e7d704
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 31 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions fastcrypto-zkp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ ff = { version = "0.13.0", features = ["derive"] }
typenum = "1.13.0"
lazy_static = "1.4.0"
itertools = "0.12.0"
regex = "1.7.1"

[dev-dependencies]
ark-bls12-377 = "0.4.0"
Expand Down
86 changes: 69 additions & 17 deletions fastcrypto-zkp/src/bn254/unit_tests/zk_login_e2e_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ use crate::bn254::{
zk_login_api::{verify_zk_login, ZkLoginEnv},
};
use ark_std::rand::{rngs::StdRng, SeedableRng};
use fastcrypto::{ed25519::Ed25519KeyPair, jwt_utils::parse_and_validate_jwt, traits::KeyPair};
use fastcrypto::jwt_utils::parse_and_validate_jwt;
use fastcrypto::{ed25519::Ed25519KeyPair, traits::KeyPair};
use im::HashMap as ImHashMap;
use num_bigint::BigUint;
use serde::{Deserialize, Serialize};
use test_strategy::proptest;
use test_strategy::Arbitrary;

const PROVER_DEV_SERVER_URL: &str = "https://prover-dev.mystenlabs.com/v1";

#[tokio::test]
Expand All @@ -28,16 +31,12 @@ async fn test_end_to_end_twitch() {
// Make a map of jwk ids to jwks just for Twitch.
let mut map = ImHashMap::new();
map.insert(
JwkId::new(
OIDCProvider::Twitch.get_config().iss,
"1".to_string(),
),
JwkId::new(zk_login_inputs.get_iss().to_string(),"1".to_string()),
JWK {
kty: "RSA".to_string(),
e: "AQAB".to_string(),
n: "6lq9MQ-q6hcxr7kOUp-tHlHtdcDsVLwVIw13iXUCvuDOeCi0VSuxCCUY6UmMjy53dX00ih2E4Y4UvlrmmurK0eG26b-HMNNAvCGsVXHU3RcRhVoHDaOwHwU72j7bpHn9XbP3Q3jebX6KIfNbei2MiR0Wyb8RZHE-aZhRYO8_-k9G2GycTpvc-2GBsP8VHLUKKfAs2B6sW3q3ymU6M0L-cFXkZ9fHkn9ejs-sqZPhMJxtBPBxoUIUQFTgv4VXTSv914f_YkNw-EjuwbgwXMvpyr06EyfImxHoxsZkFYB-qBYHtaMxTnFsZBr6fn8Ha2JqT1hoP7Z5r5wxDu3GQhKkHw".to_string(),
alg: "RS256".to_string(),
},
alg: "RS256".to_string(),},
);

// Verify it against test vk ok.
Expand Down Expand Up @@ -72,15 +71,14 @@ async fn test_end_to_end_kakao() {
let mut map = ImHashMap::new();
map.insert(
JwkId::new(
OIDCProvider::Kakao.get_config().iss,
zk_login_inputs.get_iss().to_string(),
"9f252dadd5f233f93d2fa528d12fea".to_string(),
),
JWK {
kty: "RSA".to_string(),
e: "AQAB".to_string(),
n: "qGWf6RVzV2pM8YqJ6by5exoixIlTvdXDfYj2v7E6xkoYmesAjp_1IYL7rzhpUYqIkWX0P4wOwAsg-Ud8PcMHggfwUNPOcqgSk1hAIHr63zSlG8xatQb17q9LrWny2HWkUVEU30PxxHsLcuzmfhbRx8kOrNfJEirIuqSyWF_OBHeEgBgYjydd_c8vPo7IiH-pijZn4ZouPsEg7wtdIX3-0ZcXXDbFkaDaqClfqmVCLNBhg3DKYDQOoyWXrpFKUXUFuk2FTCqWaQJ0GniO4p_ppkYIf4zhlwUYfXZEhm8cBo6H2EgukntDbTgnoha8kNunTPekxWTDhE5wGAt6YpT4Yw".to_string(),
alg: "RS256".to_string(),
},
alg: "RS256".to_string(),},
);

// Verify it against test vk ok.
Expand Down Expand Up @@ -114,15 +112,14 @@ async fn test_end_to_end_apple() {
let mut map = ImHashMap::new();
map.insert(
JwkId::new(
OIDCProvider::Apple.get_config().iss,
zk_login_inputs.get_iss().to_string(),
"W6WcOKB".to_string(),
),
JWK {
kty: "RSA".to_string(),
e: "AQAB".to_string(),
n: "2Zc5d0-zkZ5AKmtYTvxHc3vRc41YfbklflxG9SWsg5qXUxvfgpktGAcxXLFAd9Uglzow9ezvmTGce5d3DhAYKwHAEPT9hbaMDj7DfmEwuNO8UahfnBkBXsCoUaL3QITF5_DAPsZroTqs7tkQQZ7qPkQXCSu2aosgOJmaoKQgwcOdjD0D49ne2B_dkxBcNCcJT9pTSWJ8NfGycjWAQsvC8CGstH8oKwhC5raDcc2IGXMOQC7Qr75d6J5Q24CePHj_JD7zjbwYy9KNH8wyr829eO_G4OEUW50FAN6HKtvjhJIguMl_1BLZ93z2KJyxExiNTZBUBQbbgCNBfzTv7JrxMw".to_string(),
alg: "RS256".to_string(),
},
alg: "RS256".to_string(),},
);

// Verify it against test vk ok.
Expand Down Expand Up @@ -156,15 +153,14 @@ async fn test_end_to_end_slack() {
let mut map = ImHashMap::new();
map.insert(
JwkId::new(
OIDCProvider::Slack.get_config().iss,
zk_login_inputs.get_iss().to_string(),
"mB2MAyKSn555isd0EbdhKx6nkyAi9xLq8rvCEb_nOyY".to_string(),
),
JWK {
kty: "RSA".to_string(),
e: "AQAB".to_string(),
n: "zQqzXfb677bpMKw0idKC5WkVLyqk04PWMsWYJDKqMUUuu_PmzdsvXBfHU7tcZiNoHDuVvGDqjqnkLPEzjXnaZY0DDDHvJKS0JI8fkxIfV1kNy3DkpQMMhgAwnftUiSXgb5clypOmotAEm59gHPYjK9JHBWoHS14NYEYZv9NVy0EkjauyYDSTz589aiKU5lA-cePG93JnqLw8A82kfTlrJ1IIJo2isyBGANr0YzR-d3b_5EvP7ivU7Ph2v5JcEUHeiLSRzIzP3PuyVFrPH659Deh-UAsDFOyJbIcimg9ITnk5_45sb_Xcd_UN6h5I7TGOAFaJN4oi4aaGD4elNi_K1Q".to_string(),
alg: "RS256".to_string(),
},
alg: "RS256".to_string(),},
);

// Verify it against test vk ok.
Expand All @@ -188,6 +184,57 @@ async fn test_end_to_end_slack() {
assert!(res_prod.is_err());
}

#[derive(Deserialize)]
struct TestData {
jwt: String,
kid: String,
n: String,
provider: String,
}

#[tokio::test]
async fn test_end_to_end_all_providers() {
// All JWT generated against nonce hTPpgF7XAKbW37rEUS6pEVZqmoI. This is derived based on max_epoch = 10, kp generated from seed = [0; 32], and jwt_randomness 100681567828351849884072155819400689117.
let file =
std::fs::File::open("src/bn254/zklogin_test_vectors.json").expect("Unable to open file");
let test_datum: Vec<TestData> = serde_json::from_reader(file).unwrap();
for test_data in test_datum {
println!("Testing provider: {:?}", test_data.provider);
// Make a map of jwk ids to jwks just for Apple.
let (max_epoch, eph_pubkey, zk_login_inputs) = get_test_inputs(&test_data.jwt).await;
let mut map = ImHashMap::new();
map.insert(
JwkId::new(zk_login_inputs.get_iss().to_string(), test_data.kid),
JWK {
kty: "RSA".to_string(),
e: "AQAB".to_string(),
n: test_data.n,
alg: "RS256".to_string(),
},
);

// Verify it against test vk ok.
let res = verify_zk_login(
&zk_login_inputs,
max_epoch,
&eph_pubkey,
&map,
&ZkLoginEnv::Test,
);
assert!(res.is_ok());

// Verify it against prod vk fails.
let res_prod = verify_zk_login(
&zk_login_inputs,
max_epoch,
&eph_pubkey,
&map,
&ZkLoginEnv::Prod,
);
assert!(res_prod.is_err());
}
}

async fn get_test_inputs(parsed_token: &str) -> (u64, Vec<u8>, ZkLoginInputs) {
let max_epoch = 10;
let jwt_randomness = "100681567828351849884072155819400689117";
Expand Down Expand Up @@ -216,10 +263,15 @@ async fn get_test_inputs(parsed_token: &str) -> (u64, Vec<u8>, ZkLoginInputs) {
let (sub, aud) = parse_and_validate_jwt(parsed_token).unwrap();
// Get the address seed.
let address_seed = gen_address_seed(user_salt, "sub", &sub, &aud).unwrap();
let zk_login_inputs = ZkLoginInputs::from_reader(reader, &address_seed.to_string()).unwrap();
let zk_login_inputs = ZkLoginInputs::from_reader(reader, &address_seed).unwrap();
(max_epoch, eph_pubkey, zk_login_inputs)
}

#[derive(Debug, Serialize, Deserialize)]
struct TestIssuerJWTResponse {
jwt: String,
}

#[derive(Arbitrary, Debug)]
struct TestInputStruct {
// the epoch that last till 10000 years assuming epoch duration is ~24 hours.
Expand Down
21 changes: 14 additions & 7 deletions fastcrypto-zkp/src/bn254/unit_tests/zk_login_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ async fn test_verify_zk_login_google() {
kty: "RSA".to_string(),
e: "AQAB".to_string(),
n: "oUriU8GqbRw-avcMn95DGW1cpZR1IoM6L7krfrWvLSSCcSX6Ig117o25Yk7QWBiJpaPV0FbP7Y5-DmThZ3SaF0AXW-3BsKPEXfFfeKVc6vBqk3t5mKlNEowjdvNTSzoOXO5UIHwsXaxiJlbMRalaFEUm-2CKgmXl1ss_yGh1OHkfnBiGsfQUndKoHiZuDzBMGw8Sf67am_Ok-4FShK0NuR3-q33aB_3Z7obC71dejSLWFOEcKUVCaw6DGVuLog3x506h1QQ1r0FXKOQxnmqrRgpoHqGSouuG35oZve1vgCU4vLZ6EAgBAbC0KL35I7_0wUDSMpiAvf7iZxzJVbspkQ".to_string(),
alg: "RS256".to_string(),
};
alg: "RS256".to_string(),};

map.insert(
JwkId::new(
Expand Down Expand Up @@ -439,12 +438,15 @@ async fn test_get_jwks() {
OIDCProvider::Slack,
OIDCProvider::Kakao,
OIDCProvider::Apple,
OIDCProvider::Microsoft,
OIDCProvider::AwsTenant(("us-east-1".to_string(), "us-east-1_LPSLCkC3A".to_string())),
OIDCProvider::KarrierOne,
OIDCProvider::Credenza3,
] {
let res = fetch_jwks(&p, &client).await;
assert!(res.is_ok());
res.unwrap().iter().for_each(|e| {
assert_eq!(e.0.iss, p.get_config().iss);
assert_eq!(e.1.alg, "RS256".to_string());
});
}
}
Expand All @@ -459,19 +461,25 @@ fn test_get_nonce() {
}

#[test]
fn test_get_provider() {
fn test_get_provider_to_from_iss_to_from_str() {
for p in [
OIDCProvider::Google,
OIDCProvider::Twitch,
OIDCProvider::Facebook,
OIDCProvider::Slack,
OIDCProvider::Kakao,
OIDCProvider::Apple,
OIDCProvider::Microsoft,
OIDCProvider::AwsTenant(("us-east-1".to_string(), "us-east-1_LPSLCkC3A".to_string())),
OIDCProvider::TestIssuer,
] {
// to/from iss
assert_eq!(p, OIDCProvider::from_iss(&p.get_config().iss).unwrap());
// to/from string
assert_eq!(p, OIDCProvider::from_str(&p.to_string()).unwrap());
}
assert!(OIDCProvider::from_iss("Amazon").is_err());
assert!(OIDCProvider::from_iss("random").is_err());
assert!(OIDCProvider::from_str("random").is_err());
}

#[test]
Expand Down Expand Up @@ -611,8 +619,7 @@ fn test_alternative_iss_for_google() {
kty: "RSA".to_string(),
e: "AQAB".to_string(),
n: "whYOFK2Ocbbpb_zVypi9SeKiNUqKQH0zTKN1-6fpCTu6ZalGI82s7XK3tan4dJt90ptUPKD2zvxqTzFNfx4HHHsrYCf2-FMLn1VTJfQazA2BvJqAwcpW1bqRUEty8tS_Yv4hRvWfQPcc2Gc3-_fQOOW57zVy-rNoJc744kb30NjQxdGp03J2S3GLQu7oKtSDDPooQHD38PEMNnITf0pj-KgDPjymkMGoJlO3aKppsjfbt_AH6GGdRghYRLOUwQU-h-ofWHR3lbYiKtXPn5dN24kiHy61e3VAQ9_YAZlwXC_99GGtw_NpghFAuM4P1JDn0DppJldy3PGFC0GfBCZASw".to_string(),
alg: "RS256".to_string(),
},
alg: "RS256".to_string(),},
);

let res = verify_zk_login(
Expand Down
6 changes: 5 additions & 1 deletion fastcrypto-zkp/src/bn254/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ pub fn get_oidc_url(
OIDCProvider::Kakao => format!("https://kauth.kakao.com/oauth/authorize?response_type=code&client_id={}&redirect_uri={}&nonce={}", client_id, redirect_url, nonce),
OIDCProvider::Apple => format!("https://appleid.apple.com/auth/authorize?client_id={}&redirect_uri={}&scope=email&response_mode=form_post&response_type=code%20id_token&nonce={}", client_id, redirect_url, nonce),
OIDCProvider::Slack => format!("https://slack.com/openid/connect/authorize?response_type=code&client_id={}&redirect_uri={}&nonce={}&scope=openid", client_id, redirect_url, nonce),
OIDCProvider::TestIssuer => return Err(FastCryptoError::InvalidInput)
OIDCProvider::Microsoft => format!("https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={}&scope=openid&response_type=id_token&redirect_uri={}&nonce={}", client_id, redirect_url, nonce),
OIDCProvider::KarrierOne => format!("https://openid.karrier.one/Account/PhoneLogin?ReturnUrl=/connect/authorize?nonce={}&redirect_uri={}&response_type=id_token&scope=openid&client_id={}", nonce, redirect_url, client_id),
OIDCProvider::Credenza3 => format!("https://accounts.credenza3.com/oauth2/authorize?client_id={}&response_type=token&scope=openid+profile+email+phone&redirect_uri={}&nonce={}&state=state", client_id, redirect_url, nonce),
OIDCProvider::AwsTenant((region, tenant_id)) => format!("https://{}.auth.{}.amazoncognito.com/login?response_type=token&client_id={}&redirect_uri={}&nonce={}", tenant_id, region, client_id, redirect_url, nonce),
OIDCProvider::TestIssuer => return Err(FastCryptoError::InvalidInput), // Test issuer does not issue JWTs interactively, this is not valid to call.
})
}

Expand Down
Loading

0 comments on commit 1e7d704

Please sign in to comment.