# reqwest-oauth1: reqwest ♡ oauth1-request
Add OAuth1 signature to [reqwest](https://crates.io/crates/reqwest) with [oauth1-request](https://crates.io/crates/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:
```Cargo.toml
[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.
```rust
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.
```rust
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.
```rust
// 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`.
```rust
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
- Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
Note: This library contains derived artifacts from seanmonster's [`reqwest`](https://crates.io/crates/reqwest).
It is distributed under the either of MIT License or Apache License.
See [LICENSE-REQWEST-MIT](./LICENSE-REQUEST-MIT) and [LICENSE-REQWEST-APACHE](./LICENSE-REQUEST-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.