Skip to content

Commit

Permalink
OAuth1: Allow empty customer secrets, according to the specifications. (
Browse files Browse the repository at this point in the history
#1596)

* OAuth1: Allow empty customer secrets, according to the specifications.

Signed-off-by: Jämes Ménétrey <james@menetrey.me>

* Enhance the unit test of the empty consumer secrets to account for the different OAuthTypes.
  • Loading branch information
JamesMenetrey committed Jul 15, 2021
1 parent cd0d83b commit ddcb137
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 27 deletions.
26 changes: 12 additions & 14 deletions src/RestSharp/Authenticators/OAuth/OAuth1Authenticator.cs
Expand Up @@ -12,15 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using JetBrains.Annotations;
using RestSharp.Authenticators.OAuth;
using RestSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using JetBrains.Annotations;
using RestSharp.Authenticators.OAuth;
using RestSharp.Authenticators.OAuth.Extensions;
using RestSharp.Extensions;

// ReSharper disable CheckNamespace

Expand All @@ -42,7 +40,7 @@ public class OAuth1Authenticator : IAuthenticator

internal virtual string ConsumerKey { get; set; }

internal virtual string ConsumerSecret { get; set; }
internal virtual string? ConsumerSecret { get; set; }

internal virtual string Token { get; set; }

Expand Down Expand Up @@ -84,7 +82,7 @@ public void Authenticate(IRestClient client, IRestRequest request)

public static OAuth1Authenticator ForRequestToken(
string consumerKey,
string consumerSecret,
string? consumerSecret,
OAuthSignatureMethod signatureMethod = OAuthSignatureMethod.HmacSha1
)
{
Expand All @@ -101,7 +99,7 @@ public void Authenticate(IRestClient client, IRestRequest request)
return authenticator;
}

public static OAuth1Authenticator ForRequestToken(string consumerKey, string consumerSecret, string callbackUrl)
public static OAuth1Authenticator ForRequestToken(string consumerKey, string? consumerSecret, string callbackUrl)
{
var authenticator = ForRequestToken(consumerKey, consumerSecret);

Expand All @@ -112,7 +110,7 @@ public static OAuth1Authenticator ForRequestToken(string consumerKey, string con

public static OAuth1Authenticator ForAccessToken(
string consumerKey,
string consumerSecret,
string? consumerSecret,
string token,
string tokenSecret,
OAuthSignatureMethod signatureMethod = OAuthSignatureMethod.HmacSha1
Expand All @@ -131,7 +129,7 @@ public static OAuth1Authenticator ForRequestToken(string consumerKey, string con

public static OAuth1Authenticator ForAccessToken(
string consumerKey,
string consumerSecret,
string? consumerSecret,
string token,
string tokenSecret,
string verifier
Expand All @@ -155,7 +153,7 @@ string verifier
/// <returns></returns>
public static OAuth1Authenticator ForAccessTokenRefresh(
string consumerKey,
string consumerSecret,
string? consumerSecret,
string token,
string tokenSecret,
string sessionHandle
Expand All @@ -180,7 +178,7 @@ string sessionHandle
/// <returns></returns>
public static OAuth1Authenticator ForAccessTokenRefresh(
string consumerKey,
string consumerSecret,
string? consumerSecret,
string token,
string tokenSecret,
string verifier,
Expand All @@ -206,7 +204,7 @@ string sessionHandle
/// <returns></returns>
public static OAuth1Authenticator ForClientAuthentication(
string consumerKey,
string consumerSecret,
string? consumerSecret,
string username,
string password,
OAuthSignatureMethod signatureMethod = OAuthSignatureMethod.HmacSha1
Expand Down Expand Up @@ -234,7 +232,7 @@ string sessionHandle
/// <returns></returns>
public static OAuth1Authenticator ForProtectedResource(
string consumerKey,
string consumerSecret,
string? consumerSecret,
string accessToken,
string accessTokenSecret,
OAuthSignatureMethod signatureMethod = OAuthSignatureMethod.HmacSha1
Expand Down
14 changes: 7 additions & 7 deletions src/RestSharp/Authenticators/OAuth/OAuthTools.cs
Expand Up @@ -15,7 +15,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Text;
using RestSharp.Authenticators.OAuth.Extensions;
Expand Down Expand Up @@ -209,7 +208,7 @@ public static string ConcatenateRequestElements(string method, string url, WebPa
public static string GetSignature(
OAuthSignatureMethod signatureMethod,
string signatureBase,
string consumerSecret
string? consumerSecret
)
=> GetSignature(signatureMethod, OAuthSignatureTreatment.Escaped, signatureBase, consumerSecret, null);

Expand All @@ -226,7 +225,7 @@ string consumerSecret
OAuthSignatureMethod signatureMethod,
OAuthSignatureTreatment signatureTreatment,
string signatureBase,
string consumerSecret
string? consumerSecret
)
=> GetSignature(signatureMethod, signatureTreatment, signatureBase, consumerSecret, null);

Expand All @@ -243,14 +242,15 @@ string consumerSecret
OAuthSignatureMethod signatureMethod,
OAuthSignatureTreatment signatureTreatment,
string signatureBase,
string consumerSecret,
string? consumerSecret,
string? tokenSecret
)
{
if (tokenSecret.IsEmpty()) tokenSecret = string.Empty;
if (tokenSecret.IsEmpty()) tokenSecret = string.Empty;
if (consumerSecret.IsEmpty()) consumerSecret = string.Empty;

var unencodedConsumerSecret = consumerSecret;
consumerSecret = Uri.EscapeDataString(consumerSecret);
var unencodedConsumerSecret = consumerSecret!;
consumerSecret = Uri.EscapeDataString(consumerSecret!);
tokenSecret = Uri.EscapeDataString(tokenSecret!);

var signature = signatureMethod switch
Expand Down
7 changes: 1 addition & 6 deletions src/RestSharp/Authenticators/OAuth/OAuthWorkflow.cs
Expand Up @@ -13,7 +13,6 @@
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using RestSharp.Authenticators.OAuth.Extensions;
Expand All @@ -31,7 +30,7 @@ sealed class OAuthWorkflow

public string ConsumerKey { get; set; }

public string ConsumerSecret { get; set; }
public string? ConsumerSecret { get; set; }

public string Token { get; set; }

Expand Down Expand Up @@ -179,29 +178,25 @@ void ValidateTokenRequestState()
{
Ensure.NotEmpty(RequestTokenUrl, nameof(RequestTokenUrl));
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
}

void ValidateAccessRequestState()
{
Ensure.NotEmpty(AccessTokenUrl, nameof(AccessTokenUrl));
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
Ensure.NotEmpty(Token, nameof(Token));
}

void ValidateClientAuthAccessRequestState()
{
Ensure.NotEmpty(AccessTokenUrl, nameof(AccessTokenUrl));
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
Ensure.NotEmpty(ClientUsername, nameof(ClientUsername));
}

void ValidateProtectedResourceState()
{
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
}

WebPairCollection GenerateAuthParameters(string timestamp, string nonce)
Expand Down
31 changes: 31 additions & 0 deletions test/RestSharp.Tests/OAuth1AuthenticatorTests.cs
Expand Up @@ -166,5 +166,36 @@ public void Authenticate_ShouldEncodeOAuthTokenParameter(OAuthType type,string v
Assert.IsNotNull(authHeader);
Assert.IsTrue(authHeader.Contains($"oauth_token=\"{expected}\""));
}

/// <summary>
/// According the specifications of OAuth 1.0a, the customer secret is not required.
/// For more information, check the section 4 on https://oauth.net/core/1.0a/.
/// </summary>
[Test]
[TestCase(OAuthType.AccessToken)]
[TestCase(OAuthType.ProtectedResource)]
[TestCase(OAuthType.AccessToken)]
[TestCase(OAuthType.ProtectedResource)]
public void Authenticate_ShouldAllowEmptyConsumerSecret_OnHttpAuthorizationHeaderHandling(OAuthType type)
{
// Arrange
const string url = "https://no-query.string";

var client = new RestClient(url);
var request = new RestRequest();
_authenticator.Type = type;
_authenticator.ConsumerSecret = null;

// Act
_authenticator.Authenticate(client, request);

// Assert
var authParameter = request.Parameters.Single(x => x.Name == "Authorization");
var value = (string)authParameter.Value;

Assert.IsNotEmpty(value);
Assert.IsTrue(value!.Contains("OAuth"));
Assert.IsTrue(value.Contains("oauth_signature=\"" + OAuthTools.UrlEncodeStrict("&")));
}
}
}

0 comments on commit ddcb137

Please sign in to comment.