pub struct UserTokenBuilder { /* private fields */ }
Expand description
Builder for OAuth authorization code flow
See ImplicitUserTokenBuilder
for the OAuth implicit code flow (does not require Client Secret)
§Examples
See also the auth flow example
To generate a user token with this auth flow, you need to:
-
Initialize the
UserTokenBuilder
withUserTokenBuilder::new
, providing your client id, client secret, and a redirect URL. Useset_scopes(vec![])
to add any necessary scopes to the request. You can also useforce_verify(true)
to force the user to re-authorize your app’s access to their resources.Make sure you’ve added the redirect URL to the app settings on the Twitch Developer Console.
use twitch_oauth2::{id::TwitchTokenResponse, tokens::UserTokenBuilder, Scope}; use url::Url; // This is the URL the user will be redirected to after authorizing your application let redirect_url = Url::parse("http://localhost/twitch/register")?; let mut builder = UserTokenBuilder::new("myclientid", "myclientsecret", redirect_url); builder = builder.set_scopes(vec![Scope::ChatRead, Scope::ChatEdit]); builder = builder.force_verify(true); // Defaults to false
-
Generate a URL for the user to visit using
generate_url()
. This method also returns a CSRF token that you need to save for later validation.let (url, csrf_token) = builder.generate_url(); // Make your user navigate to this URL, for example println!("Visit this URL to authorize Twitch access: {}", url);
-
Have the user visit the generated URL. They will be asked to authorize your application if they haven’t previously done so or if you’ve set
force_verify
totrue
.You can do this by providing the link in a web page, have the user be directed, the console, or by opening it in a browser.
If this is a web server, you should store the UserTokenBuilder somewhere you can retrieve it later. A good place to store it is in a
Cache
or aHashMap
with the CSRF token as the key. -
When the user has been redirected to the redirect URL by twitch, extract the
state
andcode
query parameters from the URL.use std::borrow::Cow; use std::collections::BTreeMap; fn extract_pair<'a>( query: &BTreeMap<Cow<'a, str>, Cow<'a, str>>, key1: &str, key2: &str, ) -> Option<(Cow<'a, str>, Cow<'a, str>)> { Some((query.get(key1)?.clone(), query.get(key2)?.clone())) } /// Extract the state and code from the URL a user was redirected to after authorizing the application. fn extract_url<'a>( url: &'a url::Url, ) -> Result<(Cow<'a, str>, Cow<'a, str>), Option<(Cow<'a, str>, Cow<'a, str>)>> { let query: BTreeMap<_, _> = url.query_pairs().collect(); if let Some((error, error_description)) = extract_pair(&query, "error", "error_description") { Err(Some((error, error_description))) } else if let Some((state, code)) = extract_pair(&query, "state", "code") { Ok((state, code)) } else { Err(None) } }
-
Finally, call
get_user_token
with thestate
andcode
query parameters to get the user’s access token.let client = reqwest::Client::builder() .redirect(reqwest::redirect::Policy::none()) .build()?; let (state, code) = extract_url(&url)?; let token = builder.get_user_token(&client, state.as_ref(), code.as_ref()).await?; println!("User token: {:?}", token);
Implementations§
Source§impl UserTokenBuilder
impl UserTokenBuilder
Sourcepub fn new(
client_id: impl Into<ClientId>,
client_secret: impl Into<ClientSecret>,
redirect_url: Url,
) -> UserTokenBuilder
pub fn new( client_id: impl Into<ClientId>, client_secret: impl Into<ClientSecret>, redirect_url: Url, ) -> UserTokenBuilder
Create a UserTokenBuilder
§Notes
The redirect_url
must be present, verbatim, on the Twitch Developer Console.
The url
crate converts empty paths into “/” (such as https://example.com
into https://example.com/
),
which means that you’ll need to add https://example.com/
to your redirect URIs (note the “trailing” slash) if you want to use an empty path.
To avoid this, use a path such as https://example.com/twitch/register
or similar instead, where the url
crate would not add a trailing /
.
Sourcepub fn set_scopes(self, scopes: Vec<Scope>) -> Self
pub fn set_scopes(self, scopes: Vec<Scope>) -> Self
Add scopes to the request
Sourcepub fn force_verify(self, b: bool) -> Self
pub fn force_verify(self, b: bool) -> Self
Enable or disable function to make the user able to switch accounts if needed.
Sourcepub fn generate_url(&mut self) -> (Url, CsrfToken)
pub fn generate_url(&mut self) -> (Url, CsrfToken)
Generate the URL to request a code.
First step in the guide
Sourcepub fn csrf_is_valid(&self, csrf: &str) -> bool
pub fn csrf_is_valid(&self, csrf: &str) -> bool
Check if the CSRF is valid
Sourcepub fn get_user_token_request(&self, code: &str) -> Request<Vec<u8>>
pub fn get_user_token_request(&self, code: &str) -> Request<Vec<u8>>
Get the request for getting a TwitchTokenResponse, to be used in UserToken::from_response.
§Examples
use twitch_oauth2::{tokens::UserTokenBuilder, id::TwitchTokenResponse};
use url::Url;
let callback_url = Url::parse("http://localhost/twitch/register")?;
let mut builder = UserTokenBuilder::new("myclientid", "myclientsecret", callback_url);
let (url, _csrf_code) = builder.generate_url();
// Direct the user to this url.
// Later when your server gets a response on `callback_url` with `?code=xxxxxxx&state=xxxxxxx&scope=aa%3Aaa+bb%3Abb`
// validate the state
if !builder.csrf_is_valid(state_in_query) {
panic!("state mismatched")
}
// and then get your token
let request = builder.get_user_token_request(code_in_query);
// use your favorite http client
let response: http::Response<Vec<u8>> = client_req(request);
let twitch_response = TwitchTokenResponse::from_response(&response)?;
// you now have a access token, do what you want with it.
// You're recommended to convert it into a `UserToken` via `UserToken::from_response`
// You can validate the access_token like this
let validated_req = twitch_response.access_token.validate_token_request();
Sourcepub async fn get_user_token<'a, C>(
self,
http_client: &'a C,
state: &str,
code: &str,
) -> Result<UserToken, UserTokenExchangeError<<C as Client>::Error>>where
C: Client,
Available on crate feature client
only.
pub async fn get_user_token<'a, C>(
self,
http_client: &'a C,
state: &str,
code: &str,
) -> Result<UserToken, UserTokenExchangeError<<C as Client>::Error>>where
C: Client,
client
only.Generate the code with the help of the authorization code
Last step in the guide
On failure to authenticate due to wrong redirect url or other errors, twitch redirects the user to <redirect_url or first defined url in dev console>?error=<error type>&error_description=<description of error>