Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from Jul 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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("&")));
}
}
}