Newer
Older
using System.Security.Cryptography;
using Microsoft.Extensions.Logging;
namespace FitConnect;
public class FitConnectEnvironments {
/// <summary>
/// Default constructor.
/// </summary>
/// <param name="tokenUrl">URL for receiving the OAuth token</param>
/// <param name="submissionApi">URL for the submission API</param>
/// <param name="routingApi">URL for the routing API</param>
public FitConnectEnvironments(string tokenUrl, string[] submissionApi, string routingApi) {
TokenUrl = tokenUrl;
SubmissionApi = submissionApi;
RoutingApi = routingApi;
}
/// <summary>
/// URL for receiving the OAuth token.
/// </summary>
public string TokenUrl { get; }
/// <summary>
/// URL for the submission API.
/// </summary>
public string[] SubmissionApi { get; }
/// <summary>
/// URL for the routing API.
/// </summary>
public enum EndpointType {
Development,
Testing,
Production
}
/// <summary>
/// Creates the endpoints for the given environment.
/// </summary>
/// <param name="endpointType">Environment to get endpoints for</param>
/// <returns></returns>
/// <exception cref="ArgumentException">Not all environments are ready to use</exception>
public static FitConnectEnvironments Create(EndpointType endpointType) {
EndpointType.Development => DevEnvironments,
EndpointType.Testing => throw new ArgumentException("Not approved for online testing"),
EndpointType.Production => throw new ArgumentException("NOT PRODUCTION READY"),
_ => throw new ArgumentOutOfRangeException(nameof(endpointType), endpointType, null)
};
}
private static readonly FitConnectEnvironments DevEnvironments = new(
"https://auth-testing.fit-connect.fitko.dev/token",
new []{"https://submission-api-testing.fit-connect.fitko.dev"},
"https://routing-api-testing.fit-connect.fitko.dev"
private static readonly FitConnectEnvironments TestEnvironments = new(
"https://auth-testing.fit-connect.fitko.dev/token",
new []{"https://submission-api-testing.fit-connect.fitko.dev"},
"https://routing-api-testing.fit-connect.fitko.dev"
);
private static readonly FitConnectEnvironments ProductionEnvironments = new(
"https://auth-testing.fit-connect.fitko.dev/token",
new []{"https://submission-api-testing.fit-connect.fitko.dev"},
"https://routing-api-testing.fit-connect.fitko.dev"
);
}
public abstract class FunctionalBaseClass {
protected readonly ILogger? logger;
private RSA _rsa;
public FitConnectEnvironments Environments { get; }
protected FunctionalBaseClass(ILogger? logger, FitConnectEnvironments? endpoints) {
Environments = endpoints ??
FitConnectEnvironments.Create(FitConnectEnvironments.EndpointType.Development);
/// <summary>
/// Requesting an OAuth token from the FitConnect API.
///
/// You can get the Client ID and Client Secret from the FitConnect Self Service portal
/// under https://portal.auth-testing.fit-connect.fitko.dev
/// </summary>
/// <param name="clientId">Your client Id</param>
/// <param name="clientSecret">Your client Secret</param>
/// <param name="scope">Scope if needed</param>
/// <returns></returns>
public async Task<OAuthAccessToken?> GetTokenAsync(string clientId, string clientSecret,
string? scope = null) {
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(
MediaTypeWithQualityHeaderValue.Parse("application/json"));
var requestContent = new Dictionary<string, string> {
{ "grant_type", "client_credentials" },
{ "client_id", clientId },
{ "client_secret", clientSecret }
};
if (scope != null)
requestContent["scope"] = scope;
var content = new FormUrlEncodedContent(requestContent);
var request = new HttpRequestMessage(HttpMethod.Post, Environments.TokenUrl) {
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
Content = content,
Method = HttpMethod.Post
};
var response = await client.SendAsync(request);
return await response.Content.ReadFromJsonAsync<OAuthAccessToken>();
}
public Task<SecurityEventToken> GetSetDataAsync() {
throw new NotImplementedException();
}
public byte[] EncryptDataAsync(byte[] data,
byte[]? publicKey,
string? password,
int numberOfIterations) {
_rsa = RSA.Create(2048);
// _rsa.ImportRSAPublicKey(publicKey, out var read);
logger?.LogInformation(
"Encrypting data with public key: {}",
Convert.ToBase64String(_rsa.ExportRSAPublicKey()));
// var keyParams = new PbeParameters(
// PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, numberOfIterations);
//
// var privateKey =
// rsa.ExportEncryptedPkcs8PrivateKey(Encoding.UTF8.GetBytes(password), keyParams);
//
// logger?.LogInformation(
// "Private key: {}", privateKey);
return _rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
}
public byte[] DecryptDataAsync(byte[] data, byte[] privateKey) {
return _rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA256);
}
private async Task<T?> RestCall<T>(Uri uri, HttpMethod method, string body) {
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Content-Type", "application/json");
var request = new HttpRequestMessage();
request.Method = method;
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
request.RequestUri = uri;
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
return (await response.Content.ReadFromJsonAsync<T>());
throw new HttpRequestException("Error calling FitConnect API");
}
}