Add basic caching for authentication tokens

This commit is contained in:
Daniel_I_Am 2020-08-25 20:34:41 +02:00
parent 5f97bcfa71
commit ccff9a40b5
No known key found for this signature in database
GPG Key ID: 80C428FCC9743E84
5 changed files with 89 additions and 10 deletions

View File

@ -0,0 +1,13 @@
using System;
namespace ChaosBot.Services
{
public interface ICache<T, TU>
{
void Invalidate();
void Add(T key, TU value, DateTime expires);
void Remove(T key);
TU Get(T key);
bool HasKey(T key);
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ChaosBot.Services;
namespace ChaosBot.WebServer
{
public class AccessTokenCache : ICache<string, string>
{
private Dictionary<string, Tuple<string, DateTime>> _cache = new Dictionary<string, Tuple<string, DateTime>>();
public void Invalidate()
{
DateTime now = DateTime.Now;
_cache = _cache
.Where(v => v.Value.Item2 > now)
.ToDictionary(x => x.Key, x => x.Value);
}
public void Add(string key, string value, DateTime expires)
{
_cache.Add(key, new Tuple<string, DateTime>(value, expires));
}
public void Remove(string key)
{
_cache.Remove(key);
}
public string Get(string key)
{
if (!_cache.TryGetValue(key, out Tuple<string, DateTime> data))
throw new KeyNotFoundException();
return data.Item1;
}
public bool HasKey(string key)
{
return _cache.ContainsKey(key);
}
public List<string> GetKeys()
{
return _cache.Keys.ToList();
}
}
}

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
@ -15,6 +16,7 @@ namespace ChaosBot.WebServer.App
[Route("/api/discord")]
public class DiscordController : Controller
{
private static readonly AccessTokenCache Cache = WebServer.Cache;
private static readonly HttpClient client = new HttpClient();
private static readonly ILogger Logger = Program.Logger;
@ -43,6 +45,9 @@ namespace ChaosBot.WebServer.App
string responseString = await response.Content.ReadAsStringAsync();
DiscordOauthResponse responseObject = JsonConvert.DeserializeObject<DiscordOauthResponse>(responseString);
DiscordUserResponse userResponse = GetDiscordUser(responseObject.access_token);
Cache.Add(responseObject.access_token, userResponse.id, DateTime.Now.AddSeconds(responseObject.expires_in));
return LocalRedirect($"/#/?access_token={responseObject.access_token}");
}
@ -52,16 +57,7 @@ namespace ChaosBot.WebServer.App
if (!Request.Cookies.TryGetValue("access_token", out string accessToken))
accessToken = null;
HttpResponseMessage response;
using (HttpRequestMessage requestMessage =
new HttpRequestMessage(HttpMethod.Get, "https://discord.com/api/v7/users/@me"))
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
response = client.SendAsync(requestMessage).GetAwaiter().GetResult();
}
string responseString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
DiscordUserResponse userResponse = JsonConvert.DeserializeObject<DiscordUserResponse>(responseString);
DiscordUserResponse userResponse = GetDiscordUser(accessToken);
return Json(userResponse);
}
@ -85,6 +81,22 @@ namespace ChaosBot.WebServer.App
return Json(userResponse);
}
private static DiscordUserResponse GetDiscordUser(string accessToken)
{
HttpResponseMessage response;
using (HttpRequestMessage requestMessage =
new HttpRequestMessage(HttpMethod.Get, "https://discord.com/api/v7/users/@me"))
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
response = client.SendAsync(requestMessage).GetAwaiter().GetResult();
}
string responseString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
DiscordUserResponse userResponse = JsonConvert.DeserializeObject<DiscordUserResponse>(responseString);
return userResponse;
}
}
internal class DiscordOauthResponse

View File

@ -30,6 +30,9 @@ namespace ChaosBot.WebServer
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
services
.AddSingleton(sp => new AccessTokenCache());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline

View File

@ -11,6 +11,8 @@ namespace ChaosBot.WebServer
{
public static class WebServer
{
public static readonly AccessTokenCache Cache = new AccessTokenCache();
public static void Start(string[] args)
{
CreateHostBuilder(args).Build().Run();