Skip to content

Commit

Permalink
Merge branch 'main' into fix/spec-RTL12
Browse files Browse the repository at this point in the history
  • Loading branch information
sacOO7 authored Apr 18, 2024
2 parents d09ac0d + cb7fb4a commit 02171d9
Show file tree
Hide file tree
Showing 21 changed files with 296 additions and 239 deletions.
1 change: 1 addition & 0 deletions .ably/capabilities.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ compliance:
Connection:
Disconnected Retry Timeout:
Get Identifier:
Incremental Backoff:
Lifecycle Control:
Ping:
Recovery:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
dotnet-version: |
3.1.x
6.0.403
7.0.100
7.0.408
- name: Download fake-cli
run: dotnet tool restore
- name: Package
Expand All @@ -46,7 +46,7 @@ jobs:
dotnet-version: |
3.1.x
6.0.403
7.0.100
7.0.408
- name: Download fake-cli
run: dotnet tool install fake-cli --version 5.20.4 --tool-path .
- name: Restore packages
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-tests-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
with:
dotnet-version: |
6.0.403
7.0.100
7.0.408
- name: Download dotnet build-script tools
run: dotnet tool restore
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-tests-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
with:
dotnet-version: |
6.0.403
7.0.100
7.0.408
- name: Download dotnet build-script tools
run: dotnet tool restore
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-tests-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
with:
dotnet-version: |
6.0.403
7.0.100
7.0.408
- name: Download dotnet build-script tools
run: dotnet tool restore
Expand Down
267 changes: 142 additions & 125 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "6.0.300",
"rollForward": "latestMajor"
"version": "7.0.408",
"rollForward": "disable"
}
}
153 changes: 91 additions & 62 deletions src/IO.Ably.Shared/AblyAuth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,31 +302,33 @@ public virtual async Task<TokenDetails> RequestTokenAsync(TokenParams tokenParam
TokenRequest postData = null;
if (authOptions.AuthCallback != null)
{
var shouldCatch = true;
bool shouldCatch = true;
try
{
var callbackResult = await authOptions.AuthCallback(tokenParams);

switch (callbackResult)
if (callbackResult == null)
{
case null:
throw new AblyException("AuthCallback returned null", ErrorCodes.ClientAuthProviderRequestFailed);
case string token:
if (string.IsNullOrEmpty(token))
{
throw new AblyException("AuthCallback returned empty string", ErrorCodes.ClientAuthProviderRequestFailed);
}

return new TokenDetails(token);
case TokenDetails details:
return details;
case TokenRequest tokenRequest:
postData = tokenRequest;
request.Url = $"/keys/{tokenRequest.KeyName}/requestToken";
break;
default:
shouldCatch = false;
throw new AblyException($"AuthCallback returned an unsupported type ({callbackResult.GetType()}. Expected either TokenDetails or TokenRequest", ErrorCodes.ClientAuthProviderRequestFailed, HttpStatusCode.BadRequest);
throw new AblyException("AuthCallback returned null", ErrorCodes.ClientAuthProviderRequestFailed);
}

if (callbackResult is TokenDetails)
{
return callbackResult as TokenDetails;
}

if (callbackResult is TokenRequest || callbackResult is string)
{
postData = GetTokenRequest(callbackResult);
request.Url = $"/keys/{postData.KeyName}/requestToken";
}
else
{
shouldCatch = false;
throw new AblyException(
$"AuthCallback returned an unsupported type ({callbackResult.GetType()}. Expected either TokenDetails or TokenRequest",
ErrorCodes.ClientAuthProviderRequestFailed,
HttpStatusCode.BadRequest);
}
}
catch (Exception ex) when (shouldCatch)
Expand Down Expand Up @@ -453,6 +455,31 @@ private void NotifyClientIdIfChanged(string oldClientId)
}
}

#pragma warning disable SA1204 // Static elements should appear before instance elements
private static TokenRequest GetTokenRequest(object callbackResult)
#pragma warning restore SA1204 // Static elements should appear before instance elements
{
if (callbackResult is TokenRequest)
{
return callbackResult as TokenRequest;
}

try
{
var result = JsonHelper.Deserialize<TokenRequest>((string)callbackResult);
if (result == null)
{
throw new AblyException(new ErrorInfo($"AuthCallback returned a string which can't be converted to TokenRequest. ({callbackResult})."));
}

return result;
}
catch (Exception e)
{
throw new AblyException(new ErrorInfo($"AuthCallback returned a string which can't be converted to TokenRequest. ({callbackResult})."), e);
}
}

private async Task<AblyResponse> CallAuthUrl(AuthOptions mergedOptions, TokenParams @params)
{
var url = mergedOptions.AuthUrl;
Expand Down Expand Up @@ -530,13 +557,25 @@ public async Task<TokenDetails> AuthorizeAsync(TokenParams tokenParams = null, A
return CurrentToken;
}

public TokenDetails Authorize(TokenParams tokenParams = null, AuthOptions options = null)
{
return AsyncHelper.RunSync(() => AuthorizeAsync(tokenParams, options));
}

[Obsolete("This method will be removed in the future, please replace with a call to AuthorizeAsync")]
public async Task<TokenDetails> AuthoriseAsync(TokenParams tokenParams = null, AuthOptions options = null)
{
Logger.Warning("AuthoriseAsync is deprecated and will be removed in the future, please replace with a call to AuthorizeAsync");
return await AuthorizeAsync(tokenParams, options);
}

[Obsolete("This method will be removed in the future, please replace with a call to Authorize")]
public TokenDetails Authorise(TokenParams tokenParams = null, AuthOptions options = null)
{
Logger.Warning("Authorise is deprecated and will be removed in the future, please replace with a call to Authorize.");
return AsyncHelper.RunSync(() => AuthorizeAsync(tokenParams, options));
}

private void SetCurrentTokenParams(TokenParams authTokenParams)
{
CurrentTokenParams = authTokenParams.Clone();
Expand All @@ -551,30 +590,6 @@ private void SetCurrentAuthOptions(AuthOptions options)
}
}

/// <summary>
/// Create a signed token request based on known credentials
/// and the given token params. This would typically be used if creating
/// signed requests for submission by another client.
/// </summary>
/// <param name="tokenParams"><see cref="TokenParams"/>. If null a token request is generated from options passed when the client was created.</param>
/// <param name="authOptions"><see cref="AuthOptions"/>. If null the default AuthOptions are used.</param>
/// <returns>signed token request.</returns>
public async Task<TokenRequest> CreateTokenRequestObjectAsync(TokenParams tokenParams, AuthOptions authOptions)
{
authOptions = authOptions ?? CurrentAuthOptions ?? Options;
tokenParams = tokenParams ?? CurrentTokenParams ?? TokenParams.WithDefaultsApplied();

if (string.IsNullOrEmpty(authOptions.Key))
{
throw new AblyException("No key specified", ErrorCodes.InvalidCredentials, HttpStatusCode.Unauthorized);
}

await SetTokenParamsTimestamp(authOptions, tokenParams);

var apiKey = authOptions.ParseKey();
return new TokenRequest(Now).Populate(tokenParams, apiKey.KeyName, apiKey.KeySecret);
}

private TokenAuthMethod GetTokenAuthMethod()
{
if (Options.AuthCallback != null)
Expand Down Expand Up @@ -657,35 +672,49 @@ public TokenDetails RequestToken(TokenParams tokenParams = null, AuthOptions opt
return AsyncHelper.RunSync(() => RequestTokenAsync(tokenParams, options));
}

public TokenDetails Authorize(TokenParams tokenParams = null, AuthOptions options = null)
/// <summary>
/// Create a signed token request based on known credentials
/// and the given token params. This would typically be used if creating
/// signed requests for submission by another client.
/// </summary>
/// <param name="tokenParams"><see cref="TokenParams"/>. If null a token request is generated from options passed when the client was created.</param>
/// <param name="authOptions"><see cref="AuthOptions"/>. If null the default AuthOptions are used.</param>
/// <returns>signed token request.</returns>
public async Task<string> CreateTokenRequestAsync(TokenParams tokenParams, AuthOptions authOptions)
{
return AsyncHelper.RunSync(() => AuthorizeAsync(tokenParams, options));
}
authOptions = authOptions ?? CurrentAuthOptions ?? Options;
tokenParams = tokenParams ?? CurrentTokenParams ?? TokenParams.WithDefaultsApplied();

[Obsolete("This method will be removed in the future, please replace with a call to Authorize")]
public TokenDetails Authorise(TokenParams tokenParams = null, AuthOptions options = null)
{
Logger.Warning("Authorise is deprecated and will be removed in the future, please replace with a call to Authorize.");
return AsyncHelper.RunSync(() => AuthorizeAsync(tokenParams, options));
if (string.IsNullOrEmpty(authOptions.Key))
{
throw new AblyException("No key specified", ErrorCodes.InvalidCredentials, HttpStatusCode.Unauthorized);
}

await SetTokenParamsTimestamp(authOptions, tokenParams);

var apiKey = authOptions.ParseKey();
var tokenRequest = new TokenRequest(Now).Populate(tokenParams, apiKey.KeyName, apiKey.KeySecret);

return JsonHelper.Serialize(tokenRequest);
}

public TokenRequest CreateTokenRequestObject(TokenParams tokenParams = null, AuthOptions authOptions = null)
public string CreateTokenRequest(TokenParams tokenParams = null, AuthOptions authOptions = null)
{
return AsyncHelper.RunSync(() => CreateTokenRequestObjectAsync(tokenParams, authOptions));
return AsyncHelper.RunSync(() => CreateTokenRequestAsync(tokenParams, authOptions));
}

[Obsolete("This method will be removed in a future version, please use CreateTokenRequestObjectAsync instead")]
public async Task<string> CreateTokenRequestAsync(TokenParams tokenParams, AuthOptions authOptions)
[Obsolete("This method will be removed in a future version, please use CreateTokenRequestAsync instead")]
public async Task<TokenRequest> CreateTokenRequestObjectAsync(TokenParams tokenParams, AuthOptions authOptions)
{
Logger.Warning("CreateTokenRequest is deprecated and will be removed in the future, please use CreateTokenRequestObject instead");
var tokenRequest = await CreateTokenRequestObjectAsync(tokenParams, authOptions);
return JsonHelper.Serialize(tokenRequest);
Logger.Warning("CreateTokenRequestObject is deprecated and will be removed in the future, please use CreateTokenRequest instead");
var tokenRequest = await CreateTokenRequestAsync(tokenParams, authOptions);
return JsonHelper.Deserialize<TokenRequest>(tokenRequest);
}

[Obsolete("This method will be removed in a future version, please use CreateTokenRequestObject instead")]
public string CreateTokenRequest(TokenParams tokenParams = null, AuthOptions authOptions = null)
[Obsolete("This method will be removed in a future version, please use CreateTokenRequest instead")]
public TokenRequest CreateTokenRequestObject(TokenParams tokenParams = null, AuthOptions authOptions = null)
{
return AsyncHelper.RunSync(() => CreateTokenRequestAsync(tokenParams, authOptions));
return AsyncHelper.RunSync(() => CreateTokenRequestObjectAsync(tokenParams, authOptions));
}
}
}
4 changes: 2 additions & 2 deletions src/IO.Ably.Shared/IAblyAuth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ public interface IAblyAuth
/// <param name="tokenParams"><see cref="TokenParams"/>. If null a token request is generated from options passed when the client was created.</param>
/// <param name="authOptions"><see cref="AuthOptions"/>. If null the default AuthOptions are used.</param>
/// <returns>serialized signed token request.</returns>
[Obsolete("This method will be removed in a future version, please use CreateTokenRequestObjectAsync instead")]
Task<string> CreateTokenRequestAsync(TokenParams tokenParams = null, AuthOptions authOptions = null);

/// <summary>
Expand All @@ -68,6 +67,7 @@ public interface IAblyAuth
/// <param name="tokenParams"><see cref="TokenParams"/>. If null a token request is generated from options passed when the client was created.</param>
/// <param name="authOptions"><see cref="AuthOptions"/>. If null the default AuthOptions are used.</param>
/// <returns>signed token request.</returns>
[Obsolete("This method will be removed in a future version, please use CreateTokenRequestAsync instead")]
Task<TokenRequest> CreateTokenRequestObjectAsync(TokenParams tokenParams = null, AuthOptions authOptions = null);

/// <summary>
Expand Down Expand Up @@ -107,7 +107,6 @@ public interface IAblyAuth
/// <param name="tokenParams"><see cref="TokenParams"/>. If null a token request is generated from options passed when the client was created.</param>
/// <param name="authOptions"><see cref="AuthOptions"/>. If null the default AuthOptions are used.</param>
/// <returns>serialized signed token request.</returns>
[Obsolete("This method will be removed in a future version, please use CreateTokenRequestObject instead")]
string CreateTokenRequest(TokenParams tokenParams = null, AuthOptions authOptions = null);

/// <summary>
Expand All @@ -117,6 +116,7 @@ public interface IAblyAuth
/// <param name="tokenParams"><see cref="TokenParams"/>. If null a token request is generated from options passed when the client was created.</param>
/// <param name="authOptions"><see cref="AuthOptions"/>. If null the default AuthOptions are used.</param>
/// <returns>signed token request.</returns>
[Obsolete("This method will be removed in a future version, please use CreateTokenRequest instead")]
TokenRequest CreateTokenRequestObject(TokenParams tokenParams = null, AuthOptions authOptions = null);
}
}
12 changes: 6 additions & 6 deletions src/IO.Ably.Tests.Shared/AuthTests/AuthSandboxSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public async Task RealTimeWithAuthUrl_WhenTokenExpired_And_WithServerTime_Should
});
await Task.Delay(2000);
// This makes sure we get server time
_ = ((AblyAuth)mainClient.Auth).CreateTokenRequestObject();
_ = ((AblyAuth)mainClient.Auth).CreateTokenRequest();

await mainClient.StatsAsync();
((AblyAuth)mainClient.Auth).CurrentToken.Should().NotBeSameAs(token);
Expand Down Expand Up @@ -321,7 +321,7 @@ public async Task RealTimeWithAuthUrl_WhenTokenExpired_And_WithServerTime_And_No
};
await Task.Delay(2000);
// This makes sure we get server time
((AblyAuth)mainClient.Auth).SetServerTime();
await ((AblyAuth)mainClient.Auth).SetServerTime();

var ex = await Assert.ThrowsAsync<AblyException>(() => mainClient.StatsAsync());
ex.ErrorInfo.Should().BeSameAs(ErrorInfo.NonRenewableToken);
Expand All @@ -338,7 +338,7 @@ public async Task Auth_WithRealtimeClient_WhenAuthFails_ShouldTransitionToOrRema
{
async Task TestConnectingBecomesDisconnected(string context, Action<ClientOptions, TestEnvironmentSettings> optionsAction)
{
TaskCompletionAwaiter tca = new TaskCompletionAwaiter(5000);
TaskCompletionAwaiter tca = new TaskCompletionAwaiter();
var realtimeClient = await GetRealtimeClient(protocol, optionsAction);
realtimeClient.Connection.On(ConnectionEvent.Disconnected, change =>
{
Expand Down Expand Up @@ -373,7 +373,7 @@ static void AuthCallbackOptions(ClientOptions options, TestEnvironmentSettings s
static void InvalidTokenOptions(ClientOptions options, TestEnvironmentSettings settings)
{
options.AutoConnect = false;
options.AuthCallback = (tokenParams) => Task.FromResult<object>(string.Empty);
options.AuthCallback = (tokenParams) => Task.FromResult<object>("invalid:token");
}

await TestConnectingBecomesDisconnected("With invalid AuthUrl connection becomes Disconnected", AuthUrlOptions);
Expand All @@ -387,7 +387,7 @@ async Task<TokenDetails> GetToken()
var authRestClient = await GetRestClient(protocol);
var token = await authRestClient.Auth.RequestTokenAsync(new TokenParams
{
Ttl = TimeSpan.FromMilliseconds(2000)
Ttl = TimeSpan.FromMilliseconds(10000)
});
return token;
}
Expand Down Expand Up @@ -869,7 +869,7 @@ public async Task TokenAuthCallbackWithTokenRequestReturned_ShouldBeAbleToGetATo
var tokenClient = await GetRestClient(protocol);
var authCallbackClient = await GetRestClient(protocol, options =>
{
options.AuthCallback = async tokenParams => await tokenClient.Auth.CreateTokenRequestObjectAsync(new TokenParams { ClientId = "*" });
options.AuthCallback = async tokenParams => await tokenClient.Auth.CreateTokenRequestAsync(new TokenParams { ClientId = "*" });
options.Environment = settings.Environment;
options.UseBinaryProtocol = protocol == Defaults.Protocol;
});
Expand Down
Loading

0 comments on commit 02171d9

Please sign in to comment.