Skip to content

Commit

Permalink
Redact tokens in Debug output (#199)
Browse files Browse the repository at this point in the history
Co-authored-by: Ruben Anders <[email protected]>
  • Loading branch information
Nerixyz and RAnders00 authored Sep 17, 2023
1 parent 286e673 commit fe8b5fa
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Version numbers follow [Semantic Versioning](https://semver.org/).
They were previously deprecated in v4.1.0 (#197)
- Breaking: Fixed typo in RoomStateMessage's follower mode (was `follwers_only`, is now `followers_only`. (#200)
- Minor: Added support for reply-parent tags (#189)
- Minor: Tokens in `CredentialsPair` and `UserAccessToken` are now redacted in their `Debug` output. Same
applies to the `client_secret` in `RefreshingLoginCredentials`. (#199)

## v5.0.1

Expand Down
43 changes: 40 additions & 3 deletions src/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use {
use {serde::Deserialize, serde::Serialize};

/// A pair of login name and OAuth token.
#[derive(Debug, Clone)]
#[derive(Clone)]
#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
pub struct CredentialsPair {
/// Login name of the user that the library should log into chat as.
Expand All @@ -44,6 +44,16 @@ pub struct CredentialsPair {
pub token: Option<String>,
}

// Custom implementation to display [redacted] in place of the token
impl Debug for CredentialsPair {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CredentialsPair")
.field("login", &self.login)
.field("token", &self.token.as_ref().map(|_| "[redacted]"))
.finish()
}
}

/// Encapsulates logic for getting the credentials to log into chat, whenever
/// a new connection is made.
#[async_trait]
Expand Down Expand Up @@ -91,7 +101,7 @@ impl LoginCredentials for StaticLoginCredentials {
/// The necessary details about a Twitch OAuth Access Token. This information is provided
/// by Twitch's OAuth API after completing the user's authorization.
#[cfg(feature = "__refreshing-token")]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
pub struct UserAccessToken {
/// OAuth access token
pub access_token: String,
Expand All @@ -103,6 +113,19 @@ pub struct UserAccessToken {
pub expires_at: Option<DateTime<Utc>>,
}

// Custom implementation to display [redacted] in place of the token
#[cfg(feature = "__refreshing-token")]
impl Debug for UserAccessToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("UserAccessToken")
.field("access_token", &"[redacted]")
.field("refresh_token", &"[redacted]")
.field("created_at", &self.created_at)
.field("expires_at", &self.expires_at)
.finish()
}
}

/// Represents the Twitch API response to `POST /oauth2/token` API requests.
///
/// Provided as a convenience for your own implementations, as you will typically need
Expand Down Expand Up @@ -175,7 +198,7 @@ pub trait TokenStorage: Debug + Send + 'static {
/// These can also be cloned before being passed to a `Client` so you can use them in other places,
/// such as API calls.
#[cfg(feature = "__refreshing-token")]
#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct RefreshingLoginCredentials<S: TokenStorage> {
http_client: reqwest::Client,
user_login: Arc<Mutex<Option<String>>>,
Expand All @@ -184,6 +207,20 @@ pub struct RefreshingLoginCredentials<S: TokenStorage> {
token_storage: Arc<Mutex<S>>,
}

// Custom implementation to display [redacted] in place of the client secret
#[cfg(feature = "__refreshing-token")]
impl<S: TokenStorage> Debug for RefreshingLoginCredentials<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RefreshingLoginCredentials")
.field("http_client", &self.http_client)
.field("user_login", &self.user_login)
.field("client_id", &self.client_id)
.field("client_secret", &"[redacted]")
.field("token_storage", &self.token_storage)
.finish()
}
}

#[cfg(feature = "__refreshing-token")]
impl<S: TokenStorage> RefreshingLoginCredentials<S> {
/// Create new login credentials with a backing token storage. The username belonging to the
Expand Down

0 comments on commit fe8b5fa

Please sign in to comment.