Skip to content

Commit ddcb137

Browse files
OAuth1: Allow empty customer secrets, according to the specifications. (restsharp#1596)
* OAuth1: Allow empty customer secrets, according to the specifications. Signed-off-by: Jämes Ménétrey <[email protected]> * Enhance the unit test of the empty consumer secrets to account for the different OAuthTypes.
1 parent cd0d83b commit ddcb137

File tree

4 files changed

+51
-27
lines changed

4 files changed

+51
-27
lines changed

src/RestSharp/Authenticators/OAuth/OAuth1Authenticator.cs

+12-14
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
using JetBrains.Annotations;
16+
using RestSharp.Authenticators.OAuth;
17+
using RestSharp.Extensions;
1518
using System;
1619
using System.Collections.Generic;
1720
using System.Linq;
18-
using System.Text;
1921
using System.Web;
20-
using JetBrains.Annotations;
21-
using RestSharp.Authenticators.OAuth;
22-
using RestSharp.Authenticators.OAuth.Extensions;
23-
using RestSharp.Extensions;
2422

2523
// ReSharper disable CheckNamespace
2624

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

4341
internal virtual string ConsumerKey { get; set; }
4442

45-
internal virtual string ConsumerSecret { get; set; }
43+
internal virtual string? ConsumerSecret { get; set; }
4644

4745
internal virtual string Token { get; set; }
4846

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

8583
public static OAuth1Authenticator ForRequestToken(
8684
string consumerKey,
87-
string consumerSecret,
85+
string? consumerSecret,
8886
OAuthSignatureMethod signatureMethod = OAuthSignatureMethod.HmacSha1
8987
)
9088
{
@@ -101,7 +99,7 @@ public static OAuth1Authenticator ForRequestToken(
10199
return authenticator;
102100
}
103101

104-
public static OAuth1Authenticator ForRequestToken(string consumerKey, string consumerSecret, string callbackUrl)
102+
public static OAuth1Authenticator ForRequestToken(string consumerKey, string? consumerSecret, string callbackUrl)
105103
{
106104
var authenticator = ForRequestToken(consumerKey, consumerSecret);
107105

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

113111
public static OAuth1Authenticator ForAccessToken(
114112
string consumerKey,
115-
string consumerSecret,
113+
string? consumerSecret,
116114
string token,
117115
string tokenSecret,
118116
OAuthSignatureMethod signatureMethod = OAuthSignatureMethod.HmacSha1
@@ -131,7 +129,7 @@ public static OAuth1Authenticator ForAccessToken(
131129

132130
public static OAuth1Authenticator ForAccessToken(
133131
string consumerKey,
134-
string consumerSecret,
132+
string? consumerSecret,
135133
string token,
136134
string tokenSecret,
137135
string verifier
@@ -155,7 +153,7 @@ string verifier
155153
/// <returns></returns>
156154
public static OAuth1Authenticator ForAccessTokenRefresh(
157155
string consumerKey,
158-
string consumerSecret,
156+
string? consumerSecret,
159157
string token,
160158
string tokenSecret,
161159
string sessionHandle
@@ -180,7 +178,7 @@ string sessionHandle
180178
/// <returns></returns>
181179
public static OAuth1Authenticator ForAccessTokenRefresh(
182180
string consumerKey,
183-
string consumerSecret,
181+
string? consumerSecret,
184182
string token,
185183
string tokenSecret,
186184
string verifier,
@@ -206,7 +204,7 @@ string sessionHandle
206204
/// <returns></returns>
207205
public static OAuth1Authenticator ForClientAuthentication(
208206
string consumerKey,
209-
string consumerSecret,
207+
string? consumerSecret,
210208
string username,
211209
string password,
212210
OAuthSignatureMethod signatureMethod = OAuthSignatureMethod.HmacSha1
@@ -234,7 +232,7 @@ public static OAuth1Authenticator ForClientAuthentication(
234232
/// <returns></returns>
235233
public static OAuth1Authenticator ForProtectedResource(
236234
string consumerKey,
237-
string consumerSecret,
235+
string? consumerSecret,
238236
string accessToken,
239237
string accessTokenSecret,
240238
OAuthSignatureMethod signatureMethod = OAuthSignatureMethod.HmacSha1

src/RestSharp/Authenticators/OAuth/OAuthTools.cs

+7-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
using System;
1616
using System.Collections.Generic;
1717
using System.Linq;
18-
using System.Runtime.Serialization;
1918
using System.Security.Cryptography;
2019
using System.Text;
2120
using RestSharp.Authenticators.OAuth.Extensions;
@@ -209,7 +208,7 @@ public static string ConcatenateRequestElements(string method, string url, WebPa
209208
public static string GetSignature(
210209
OAuthSignatureMethod signatureMethod,
211210
string signatureBase,
212-
string consumerSecret
211+
string? consumerSecret
213212
)
214213
=> GetSignature(signatureMethod, OAuthSignatureTreatment.Escaped, signatureBase, consumerSecret, null);
215214

@@ -226,7 +225,7 @@ public static string GetSignature(
226225
OAuthSignatureMethod signatureMethod,
227226
OAuthSignatureTreatment signatureTreatment,
228227
string signatureBase,
229-
string consumerSecret
228+
string? consumerSecret
230229
)
231230
=> GetSignature(signatureMethod, signatureTreatment, signatureBase, consumerSecret, null);
232231

@@ -243,14 +242,15 @@ public static string GetSignature(
243242
OAuthSignatureMethod signatureMethod,
244243
OAuthSignatureTreatment signatureTreatment,
245244
string signatureBase,
246-
string consumerSecret,
245+
string? consumerSecret,
247246
string? tokenSecret
248247
)
249248
{
250-
if (tokenSecret.IsEmpty()) tokenSecret = string.Empty;
249+
if (tokenSecret.IsEmpty()) tokenSecret = string.Empty;
250+
if (consumerSecret.IsEmpty()) consumerSecret = string.Empty;
251251

252-
var unencodedConsumerSecret = consumerSecret;
253-
consumerSecret = Uri.EscapeDataString(consumerSecret);
252+
var unencodedConsumerSecret = consumerSecret!;
253+
consumerSecret = Uri.EscapeDataString(consumerSecret!);
254254
tokenSecret = Uri.EscapeDataString(tokenSecret!);
255255

256256
var signature = signatureMethod switch

src/RestSharp/Authenticators/OAuth/OAuthWorkflow.cs

+1-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// limitations under the License.
1414

1515
using System;
16-
using System.Collections.Generic;
1716
using System.Linq;
1817
using System.Web;
1918
using RestSharp.Authenticators.OAuth.Extensions;
@@ -31,7 +30,7 @@ sealed class OAuthWorkflow
3130

3231
public string ConsumerKey { get; set; }
3332

34-
public string ConsumerSecret { get; set; }
33+
public string? ConsumerSecret { get; set; }
3534

3635
public string Token { get; set; }
3736

@@ -179,29 +178,25 @@ void ValidateTokenRequestState()
179178
{
180179
Ensure.NotEmpty(RequestTokenUrl, nameof(RequestTokenUrl));
181180
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
182-
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
183181
}
184182

185183
void ValidateAccessRequestState()
186184
{
187185
Ensure.NotEmpty(AccessTokenUrl, nameof(AccessTokenUrl));
188186
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
189-
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
190187
Ensure.NotEmpty(Token, nameof(Token));
191188
}
192189

193190
void ValidateClientAuthAccessRequestState()
194191
{
195192
Ensure.NotEmpty(AccessTokenUrl, nameof(AccessTokenUrl));
196193
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
197-
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
198194
Ensure.NotEmpty(ClientUsername, nameof(ClientUsername));
199195
}
200196

201197
void ValidateProtectedResourceState()
202198
{
203199
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
204-
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
205200
}
206201

207202
WebPairCollection GenerateAuthParameters(string timestamp, string nonce)

test/RestSharp.Tests/OAuth1AuthenticatorTests.cs

+31
Original file line numberDiff line numberDiff line change
@@ -166,5 +166,36 @@ public void Authenticate_ShouldEncodeOAuthTokenParameter(OAuthType type,string v
166166
Assert.IsNotNull(authHeader);
167167
Assert.IsTrue(authHeader.Contains($"oauth_token=\"{expected}\""));
168168
}
169+
170+
/// <summary>
171+
/// According the specifications of OAuth 1.0a, the customer secret is not required.
172+
/// For more information, check the section 4 on https://oauth.net/core/1.0a/.
173+
/// </summary>
174+
[Test]
175+
[TestCase(OAuthType.AccessToken)]
176+
[TestCase(OAuthType.ProtectedResource)]
177+
[TestCase(OAuthType.AccessToken)]
178+
[TestCase(OAuthType.ProtectedResource)]
179+
public void Authenticate_ShouldAllowEmptyConsumerSecret_OnHttpAuthorizationHeaderHandling(OAuthType type)
180+
{
181+
// Arrange
182+
const string url = "https://no-query.string";
183+
184+
var client = new RestClient(url);
185+
var request = new RestRequest();
186+
_authenticator.Type = type;
187+
_authenticator.ConsumerSecret = null;
188+
189+
// Act
190+
_authenticator.Authenticate(client, request);
191+
192+
// Assert
193+
var authParameter = request.Parameters.Single(x => x.Name == "Authorization");
194+
var value = (string)authParameter.Value;
195+
196+
Assert.IsNotEmpty(value);
197+
Assert.IsTrue(value!.Contains("OAuth"));
198+
Assert.IsTrue(value.Contains("oauth_signature=\"" + OAuthTools.UrlEncodeStrict("&")));
199+
}
169200
}
170201
}

0 commit comments

Comments
 (0)