#oauth #http-request #http #request

reqwest-oauth1

Add OAuth1 signature to reqwest with oauth1-request

6 releases

0.3.0 Aug 28, 2024
0.2.4 Nov 19, 2023
0.2.3 Oct 30, 2022
0.2.2 Jul 26, 2022
0.1.0 Oct 9, 2020

#31 in Authentication

Download history 321/week @ 2024-07-31 173/week @ 2024-08-07 130/week @ 2024-08-14 99/week @ 2024-08-21 443/week @ 2024-08-28 341/week @ 2024-09-04 178/week @ 2024-09-11 329/week @ 2024-09-18 445/week @ 2024-09-25 236/week @ 2024-10-02 484/week @ 2024-10-09 327/week @ 2024-10-16 544/week @ 2024-10-23 390/week @ 2024-10-30 416/week @ 2024-11-06 326/week @ 2024-11-13

1,782 downloads per month
Used in 7 crates (6 directly)

MIT/Apache

79KB
1.5K SLoC

reqwest-oauth1: reqwest ♡ oauth1-request

Add OAuth1 signature to reqwest with oauth1-request.

This library provides partial compatible interface of reqwest.

You can use this almost same as reqwest, and signing with OAuth1 authorization protocol.

Note: this crate is currently supporting the asynchronous Client (reqwest::Client) only.

Installation

Add dependency of reqwest-oauth1 to your Cargo.toml as belows:

[dependencies]
reqwest-oauth1 = "*"

How to use

At a glance overview

  1. Add reference to crate reqwest_oauth1 in your code like use reqwest_oauth1;
  2. Prepare OAuth keys: consumer_key, consumer_secret, access_token, and token_secret.
  3. Add oauth1 method into your method chain of reqwest's.
use reqwest;
use reqwest::multipart;
use reqwest_oauth1::OAuthClientProvider;

// prepare authorization info
let consumer_key = "[CONSUMER_KEY]";
let consumer_secret = "[CONSUMER_SECRET]";
let access_token = "[ACCESS_TOKEN]";
let token_secret = "[TOKEN_SECRET]";

let secrets = reqwest_oauth1::Secrets::new(consumer_key, consumer_secret)
  .token(access_token, token_secret);

// sample: send new tweet to twitter
let endpoint = "https://api.twitter.com/1.1/statuses/update.json";

let content = multipart::Form::new()
    .text("status", "Hello, Twitter!");

let client = reqwest::Client::new();
let resp = client
    // enable OAuth1 request
    .oauth1(secrets)
    .post(endpoint)
    .multipart(content)
    .send()
    .await?;

OAuth key acquisition

This library also includes support for getting access_token and token_secret.

Please note there still needs the consumer_key and the consumer_secret and you have to get these keys somehow.

use std::io;
use reqwest;
use reqwest_oauth1::{OAuthClientProvider, TokenReaderFuture};

// prepare authorization info
let consumer_key = "[CONSUMER_KEY]";
let consumer_secret = "[CONSUMER_SECRET]";

let secrets = reqwest_oauth1::Secrets::new(consumer_key, consumer_secret);

// sample: request access token to twitter

// step 1: acquire request token & token secret
let endpoint_reqtoken = "https://api.twitter.com/oauth/request_token";

let client = reqwest::Client::new();
let resp = client
    .oauth1(secrets)
    .post(endpoint_reqtoken)
    .query(&[("oauth_callback", "oob")])
    .send()
    .parse_oauth_token()
    .await?;

// step 2. acquire user pin
let endpoint_authorize = "https://api.twitter.com/oauth/authorize?oauth_token=";
println!("please access to: {}{}", endpoint_authorize, resp.oauth_token);

println!("input pin: ");
let mut user_input = String::new();
io::stdin().read_line(&mut user_input)?;
let pin = user_input.trim();

// step 3. acquire access token
let secrets = reqwest_oauth1::Secrets::new(consumer_key, consumer_secret)
    .token(resp.oauth_token, resp.oauth_token_secret);
let endpoint_acctoken = "https://api.twitter.com/oauth/access_token";

let client = reqwest::Client::new();
let resp = client
    .oauth1(secrets)
    .get(endpoint_acctoken)
    .query(&[("oauth_verifier", pin)])
    .send()
    .parse_oauth_token()
    .await?;
println!(
    "your token and secret is: \n token: {}\n secret: {}",
    resp.oauth_token, resp.oauth_token_secret
);
println!("other attributes: {:#?}", resp.remain);

Another option

You can use sign method as follows instead of use oauth1 method.

// instantiate our wrapper Client directly
let client = reqwest::Client::new();
let resp = client
    .post(endpoint)
    .multipart(form)
    // ... and add secrets to generate signature
    .sign(secrets)
    .send()
    .await?;

Detailed behavior

You can specify oauth_* parameters both of in OAuthParameters or get/post query.

If you specify the parameter with both of them, the parameters specified as get/post query will supersede the parameters passed with OAuthParameters.

let params = reqwest_oauth1::OAuthParameters::new()
    .nonce("ThisNonceWillBeSuperseded");
let req = reqwest::Client::new()
    .oauth1_with_params(secrets, paras)
    .get(endpoint)
    .query(&[("nonce", "ThisNonceWillSupersedeTheOldOne")])
    ...

However, these parameter can not specify as the get/post query.

  • oauth_signature_method : Could be configured only with the OAuthParameters.
  • oauth_consumer_key, oauth_token : Could be configured as the Secrets.
  • oauth_timestamp with non-u64 values: the OAuth1 protocol is not allowed it.
  • oauth_version with neither of "1.0" or just "" : the OAuth1 protocol is not allowed it.
  • any oauth_* parameter that is not defined in OAuth1 protocol: currently not supported.

Customization of OAuth Autentication Method

When you calling oauth1 method in Client, or sign method in RequestBuilder, you can call *_with_params method with some parameters instead of original method.

License

Licensed under either of

at your option.

Note: This library contains derived artifacts from seanmonster's reqwest. It is distributed under the either of MIT License or Apache License. See LICENSE-REQWEST-MIT and LICENSE-REQWEST-APACHE for further information.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Known Issue

This library still depends on the older version 0.3.3 of oauth1-request. This depends on the raw implementation of the oauth1 signing method, however, the recent versions of oauth1-request hide their raw interface. Therefore, we can't migrate to a newer version of them.

Currently, severe vulnerabilities have not reported on those versions, so I think we can still use older versions, but your contributions are always welcome.

Dependencies

~5–17MB
~212K SLoC