Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vanderlei-dev/665d7cd7c90aee0bf3e38e83dad5c7d2 to your computer and use it in GitHub Desktop.
Save vanderlei-dev/665d7cd7c90aee0bf3e38e83dad5c7d2 to your computer and use it in GitHub Desktop.
using System.Text.Json.Serialization;
using RestSharp.Authenticators;
namespace RestSharp.Tests.External.Twitter;
public interface ITwitterClient
{
Task<TwitterUser> GetUser(string user);
}
public class TwitterClient : ITwitterClient, IDisposable
{
readonly RestClient _client;
public TwitterClient(string apiKey, string apiKeySecret)
{
var options = new RestClientOptions("https://api.twitter.com/2");
_client = new RestClient(options)
{
Authenticator = new TwitterAuthenticator("https://api.twitter.com", apiKey, apiKeySecret)
};
}
public async Task<TwitterUser> GetUser(string user)
{
var response = await _client.GetJsonAsync<TwitterSingleObject<TwitterUser>>(
"users/by/username/{user}",
new { user }
);
return response!.Data;
}
record TwitterSingleObject<T>(T Data);
public void Dispose()
{
_client?.Dispose();
GC.SuppressFinalize(this);
}
}
public class TwitterAuthenticator : AuthenticatorBase
{
readonly string _baseUrl;
readonly string _clientId;
readonly string _clientSecret;
protected DateTime Expiration { get; private set; } = DateTime.MinValue;
public TwitterAuthenticator(string baseUrl, string clientId, string clientSecret) : base("")
{
_baseUrl = baseUrl;
_clientId = clientId;
_clientSecret = clientSecret;
}
protected override async ValueTask<Parameter> GetAuthenticationParameter(string accessToken)
{
if (string.IsNullOrEmpty(Token) || DateTime.UtcNow >= Expiration)
{
var tokenResponse = await GetToken();
Token = $"{tokenResponse!.TokenType} {tokenResponse!.AccessToken}";
Expiration = tokenResponse.GetExpirationDate(DateTime.UtcNow);
}
return new HeaderParameter(KnownHeaders.Authorization, Token);
}
async Task<TokenResponse> GetToken()
{
var options = new RestClientOptions(_baseUrl);
using var client = new RestClient(options)
{
Authenticator = new HttpBasicAuthenticator(_clientId, _clientSecret),
};
var request = new RestRequest("oauth2/token")
.AddParameter("grant_type", "client_credentials");
return await client.PostAsync<TokenResponse>(request);
}
record TokenResponse
{
[JsonPropertyName("token_type")]
public string TokenType { get; init; }
[JsonPropertyName("access_token")]
public string AccessToken { get; init; }
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; init; }
public DateTime GetExpirationDate(DateTime baseDateTime, int toleranceInMinutes = 1)
{
return baseDateTime.AddSeconds(ExpiresIn).AddMinutes(-toleranceInMinutes);
}
}
}
public record TwitterUser(string Id, string Name, string Username);
@mavaddat
Copy link

mavaddat commented Oct 4, 2023

Very nice example. I have adapted it for getting my HashiCorp Cloud OAuth2. Thank you for sharing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment