Add basic caching for authentication tokens
This commit is contained in:
parent
5f97bcfa71
commit
ccff9a40b5
13
ChaosBot/Services/ICache.cs
Normal file
13
ChaosBot/Services/ICache.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
ChaosBot/WebServer/AccessTokenCache.cs
Normal file
49
ChaosBot/WebServer/AccessTokenCache.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@ -15,6 +16,7 @@ namespace ChaosBot.WebServer.App
|
|||||||
[Route("/api/discord")]
|
[Route("/api/discord")]
|
||||||
public class DiscordController : Controller
|
public class DiscordController : Controller
|
||||||
{
|
{
|
||||||
|
private static readonly AccessTokenCache Cache = WebServer.Cache;
|
||||||
private static readonly HttpClient client = new HttpClient();
|
private static readonly HttpClient client = new HttpClient();
|
||||||
private static readonly ILogger Logger = Program.Logger;
|
private static readonly ILogger Logger = Program.Logger;
|
||||||
|
|
||||||
@ -43,6 +45,9 @@ namespace ChaosBot.WebServer.App
|
|||||||
string responseString = await response.Content.ReadAsStringAsync();
|
string responseString = await response.Content.ReadAsStringAsync();
|
||||||
DiscordOauthResponse responseObject = JsonConvert.DeserializeObject<DiscordOauthResponse>(responseString);
|
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}");
|
return LocalRedirect($"/#/?access_token={responseObject.access_token}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,16 +57,7 @@ namespace ChaosBot.WebServer.App
|
|||||||
if (!Request.Cookies.TryGetValue("access_token", out string accessToken))
|
if (!Request.Cookies.TryGetValue("access_token", out string accessToken))
|
||||||
accessToken = null;
|
accessToken = null;
|
||||||
|
|
||||||
HttpResponseMessage response;
|
DiscordUserResponse userResponse = GetDiscordUser(accessToken);
|
||||||
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 Json(userResponse);
|
return Json(userResponse);
|
||||||
}
|
}
|
||||||
@ -85,6 +81,22 @@ namespace ChaosBot.WebServer.App
|
|||||||
|
|
||||||
return Json(userResponse);
|
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
|
internal class DiscordOauthResponse
|
||||||
|
|||||||
@ -30,6 +30,9 @@ namespace ChaosBot.WebServer
|
|||||||
options.ForwardedHeaders =
|
options.ForwardedHeaders =
|
||||||
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
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
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline
|
||||||
|
|||||||
@ -11,6 +11,8 @@ namespace ChaosBot.WebServer
|
|||||||
{
|
{
|
||||||
public static class WebServer
|
public static class WebServer
|
||||||
{
|
{
|
||||||
|
public static readonly AccessTokenCache Cache = new AccessTokenCache();
|
||||||
|
|
||||||
public static void Start(string[] args)
|
public static void Start(string[] args)
|
||||||
{
|
{
|
||||||
CreateHostBuilder(args).Build().Run();
|
CreateHostBuilder(args).Build().Run();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user