square-dotnet-sdk icon indicating copy to clipboard operation
square-dotnet-sdk copied to clipboard

RevokeToken is not intuitive

Open jsgoupil opened this issue 4 years ago • 2 comments

I am aware that you have to match the API for other languages, but this RevokeToken API is everything but intuitive in C#. I had to go check your API explorer and even try it like this:

https://developer.squareup.com/explorer/square/o-auth-api/revoke-token

Because I was getting

{
  "message": "bad authorization header",
  "type": "bad_request.invalid_parameter"
}

All other API takes a SquareClient.Builder().AccessToken() but not this one. It has to go in the RevokeTokenRequest. Then, I need to pass in the ApplicationSecret which is called authorization on the method, rather than using the clientSecret like we can find on ObtainTokenRequest.

Then to put the cherry on top, I have to put the word Client , before my ApplicationSecret. Which makes even less sense as for the public API.

Here is a snippet of my code. The RevokeTokenAsync is so different than this ObtainTokenAsync that I had to spend extra time trying to figure out in your code what your API is really doing here.

public async Task<bool> DisconnectAsync(int contractorId, CancellationToken cancellationToken = default(CancellationToken))
{
    var accessToken = await GetAccessTokenAsync(contractorId);
    var request = new RevokeTokenRequest.Builder()
        .ClientId(paymentSquareOptions.ApplicationId)
        .AccessToken(accessToken)
        .RevokeOnlyAccessToken(false)
        .Build();

    var response = await GetSquareClient(null).OAuthApi.RevokeTokenAsync(request, $"Client {paymentSquareOptions.ApplicationSecret}", cancellationToken);
    return response.Success ?? false;
}

private async Task<(string AccessToken, string ExpiresAt, string RefreshToken)> GetAccessTokenFromAuthorizationCodeAsync(string authorizedCode, CancellationToken cancellationToken = default(CancellationToken))
{
    var request = new ObtainTokenRequest.Builder(
        paymentSquareOptions.ApplicationId,
        paymentSquareOptions.ApplicationSecret,
        AUTHORIZATION_CODE
    )
    .Code(authorizedCode)
    .Build();

    var response = await GetSquareClient(null).OAuthApi.ObtainTokenAsync(request, cancellationToken);
    return (response.AccessToken, response.ExpiresAt, response.RefreshToken);
}

protected virtual internal ISquareClient GetSquareClient(string accessToken)
{
    var builder = new SquareClient.Builder()
        .Environment(GetEnvironment());

    if (!string.IsNullOrEmpty(accessToken))
    {
        builder = builder
            .AccessToken(accessToken);
    }

    return builder
        .Build();
}

I would have expected the following:

var request = new RevokeTokenRequest.Builder(
    paymentSquareOptions.ApplicationId,
    paymentSquareOptions.ApplicationSecret
)
.AccessToken(accessToken)
.Build();

var response = await GetSquareClient(null).OAuthApi.RevokeTokenAsync(request, cancellationToken);

OR

var request = new RevokeTokenRequest.Builder(
    paymentSquareOptions.ApplicationId,
    paymentSquareOptions.ApplicationSecret
)
.Build();

var response = await GetSquareClient(accessToken).OAuthApi.RevokeTokenAsync(request, cancellationToken);

jsgoupil avatar May 27 '20 17:05 jsgoupil