1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
use chrono::prelude::*; use crypto::hmac::Hmac; use crypto::mac::Mac; use crypto::sha1::Sha1; use rand::seq::SliceRandom; pub fn oauth1_authorization_header(bearer_token: &str) -> String { format!("Bearer {}", bearer_token) } pub fn oauth2_authorization_header( consumer_key: &str, consumer_secret: &str, access_token: &str, access_token_secret: &str, method: &str, uri: &str, options: &Vec<(&str, &str)>, ) -> String { let res = calc_oauth_header( &format!("{}&{}", consumer_secret, access_token_secret), consumer_key, &vec![("oauth_token", access_token)], method, uri, options, ); format!("OAuth {}", res) } pub fn calc_oauth_header( sign_key: &str, consumer_key: &str, header_options: &Vec<(&str, &str)>, method: &str, uri: &str, options: &Vec<(&str, &str)>, ) -> String { let mut param0: Vec<(&str, String)> = vec![ ("oauth_consumer_key", String::from(consumer_key)), ("oauth_nonce", nonce()), ("oauth_signature_method", String::from("HMAC-SHA1")), ("oauth_timestamp", timestamp()), ("oauth_version", String::from("1.0")), ]; for header_option in header_options { param0.push((header_option.0, encode(header_option.1))); } let mut param1 = param0.clone(); for option in options { param1.push((option.0, encode(option.1))); } param1.sort(); let parameter = make_query(¶m1, "&"); let base = format!("{}&{}&{}", method, encode(uri), encode(¶meter)); let mut param2 = param0.clone(); param2.push(("oauth_signature", encode(&sign(&base, sign_key)))); make_query(¶m2, ", ") } const BASE_STR: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; fn nonce() -> String { let mut rng = &mut rand::thread_rng(); String::from_utf8( BASE_STR .as_bytes() .choose_multiple(&mut rng, 32) .cloned() .collect(), ) .unwrap() } fn timestamp() -> String { format!("{}", Utc::now().timestamp()) } fn encode(s: &str) -> String { url::form_urlencoded::byte_serialize(s.as_bytes()).collect::<String>() } fn sign(base: &str, key: &str) -> String { let mut hmac = Hmac::new(Sha1::new(), key.as_bytes()); hmac.input(base.as_bytes()); base64::encode(hmac.result().code()) } fn make_query(list: &Vec<(&str, String)>, separator: &str) -> String { let mut result = String::from(""); for item in list { if "" != result { result.push_str(separator); } result.push_str(&format!("{}={}", item.0, item.1)); } result } #[cfg(test)] mod tests { #[test] fn it_oauth1_authorization_header() { assert_eq!("Bearer abc", crate::oauth1_authorization_header("abc")); println!( "{}", crate::oauth2_authorization_header( "a", "b", "c", "d", "GET", "http://localhost", &vec![] ) ); } }