aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Web/Security
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2019-02-24 00:57:14 +0200
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2019-02-24 00:57:14 +0200
commit0adea9eb464a3f2d5d73b2c8c26d32e0d1a3874b (patch)
treebb5e4055020aa4417e1f7703a611353ce44689d6 /Software/Visual_Studio/Tango.Web/Security
parent17612c08da93c75d4c941a643bc7602c18f351d8 (diff)
downloadTango-0adea9eb464a3f2d5d73b2c8c26d32e0d1a3874b.tar.gz
Tango-0adea9eb464a3f2d5d73b2c8c26d32e0d1a3874b.zip
Working on refresh tokens...
Diffstat (limited to 'Software/Visual_Studio/Tango.Web/Security')
-rw-r--r--Software/Visual_Studio/Tango.Web/Security/RefreshTokenEntity.cs24
-rw-r--r--Software/Visual_Studio/Tango.Web/Security/RenewTokenRequest.cs14
-rw-r--r--Software/Visual_Studio/Tango.Web/Security/RenewTokenResponse.cs14
-rw-r--r--Software/Visual_Studio/Tango.Web/Security/TokensManager.cs82
-rw-r--r--Software/Visual_Studio/Tango.Web/Security/WebToken.cs178
-rw-r--r--Software/Visual_Studio/Tango.Web/Security/WebTokenResponse.cs15
6 files changed, 327 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.Web/Security/RefreshTokenEntity.cs b/Software/Visual_Studio/Tango.Web/Security/RefreshTokenEntity.cs
new file mode 100644
index 000000000..839027ca1
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Web/Security/RefreshTokenEntity.cs
@@ -0,0 +1,24 @@
+using Microsoft.WindowsAzure.Storage.Table;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Web.Security
+{
+ public class RefreshTokenEntity : TableEntity
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RefreshTokenEntity"/> class.
+ /// </summary>
+ public RefreshTokenEntity()
+ {
+
+ }
+
+ public String RefreshToken { get; set; }
+ public String AccessToken { get; set; }
+ public DateTime Expiration { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Web/Security/RenewTokenRequest.cs b/Software/Visual_Studio/Tango.Web/Security/RenewTokenRequest.cs
new file mode 100644
index 000000000..213cd3afd
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Web/Security/RenewTokenRequest.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Transport.Web;
+
+namespace Tango.Web.Security
+{
+ public class RenewTokenRequest : WebRequestMessage
+ {
+ public String RefreshToken { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Web/Security/RenewTokenResponse.cs b/Software/Visual_Studio/Tango.Web/Security/RenewTokenResponse.cs
new file mode 100644
index 000000000..76c381852
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Web/Security/RenewTokenResponse.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Transport.Web;
+
+namespace Tango.Web.Security
+{
+ public class RenewTokenResponse : WebTokenResponse
+ {
+
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Web/Security/TokensManager.cs b/Software/Visual_Studio/Tango.Web/Security/TokensManager.cs
new file mode 100644
index 000000000..bf5574766
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Web/Security/TokensManager.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Authentication;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Transport.Web;
+
+namespace Tango.Web.Security
+{
+ public class TokensManager<T> where T : IEquatable<T>
+ {
+ private Dictionary<String, TokenWrapper> _tokens;
+
+ private class TokenWrapper : IEquatable<TokenWrapper>
+ {
+ public WebToken WebToken { get; set; }
+
+ public T Value { get; set; }
+
+ public bool Equals(TokenWrapper other)
+ {
+ return Value.Equals(other.Value);
+ }
+ }
+
+ public TokensManager()
+ {
+ _tokens = new Dictionary<string, TokenWrapper>();
+ ExpirationTime = TimeSpan.FromHours(1);
+ }
+
+ public TimeSpan ExpirationTime { get; set; }
+
+ public WebToken GetOrCreate(T tokenObject)
+ {
+ var existing_token = _tokens.FirstOrDefault(x => x.Value.Value.Equals(tokenObject));
+
+ if (existing_token.Key != null)
+ {
+ return existing_token.Value.WebToken;
+ }
+ else
+ {
+ String token = Guid.NewGuid().ToString();
+ TokenWrapper wrapper = new TokenWrapper()
+ {
+ Value = tokenObject,
+ WebToken = new WebToken()
+ {
+ //AccessToken = token,
+ //Expiration = DateTime.UtcNow.Add(ExpirationTime)
+ },
+ };
+
+ _tokens.Add(token, wrapper);
+ return wrapper.WebToken;
+ }
+ }
+
+ public void Validate(String token)
+ {
+ GetTokenObject(token);
+ }
+
+ public T GetTokenObject(String token)
+ {
+ if (!_tokens.ContainsKey(token))
+ {
+ throw new AuthenticationException("Invalid token.");
+ }
+
+ if (DateTime.UtcNow > _tokens[token].WebToken.Expiration)
+ {
+ _tokens.Remove(token);
+ throw new TokenExpiredException("Session Expired.");
+ }
+
+ return _tokens[token].Value;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Web/Security/WebToken.cs b/Software/Visual_Studio/Tango.Web/Security/WebToken.cs
new file mode 100644
index 000000000..006ed9de7
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Web/Security/WebToken.cs
@@ -0,0 +1,178 @@
+using JWT;
+using JWT.Algorithms;
+using JWT.Builder;
+using JWT.Serializers;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Web.Security
+{
+ public class WebToken
+ {
+ public DateTime Issued { get; protected set; }
+ public DateTime? Expiration { get; protected set; }
+ public String AccessToken { get; protected set; }
+ public String RefreshToken { get; protected set; }
+
+ public WebToken()
+ {
+
+ }
+
+ public static WebToken CreateNew(String secret, DateTime? expiration = null)
+ {
+ DateTime issued = DateTime.UtcNow;
+
+ var builder = new JwtBuilder()
+ .WithAlgorithm(new HMACSHA256Algorithm())
+ .WithSecret(secret)
+ .IssuedAt(issued);
+
+ if (expiration != null)
+ {
+ builder = builder.ExpirationTime(expiration.Value);
+ }
+
+ builder = builder.AddClaim("object", null);
+
+ return new WebToken()
+ {
+ AccessToken = builder.Build(),
+ RefreshToken = Guid.NewGuid().ToString(),
+ Expiration = expiration,
+ Issued = issued,
+ };
+ }
+
+ public static void Validate(String secret, String token)
+ {
+ var json = new JwtBuilder()
+ .WithSecret(secret)
+ .MustVerifySignature()
+ .Decode(token);
+ }
+
+ public void Validate(String secret)
+ {
+ var json = new JwtBuilder()
+ .WithSecret(secret)
+ .MustVerifySignature()
+ .Decode(AccessToken);
+ }
+
+ public WebToken Renew(String secret, String token)
+ {
+ WebToken webToken = WebToken.FromToken(token);
+ var newToken = CreateNew(secret, DateTime.UtcNow.Add(webToken.Expiration.Value - webToken.Issued));
+ newToken.RefreshToken = webToken.RefreshToken;
+ return newToken;
+ }
+
+ public static WebToken FromToken(String token)
+ {
+ WebToken webToken = new WebToken();
+
+ var payload = new JwtBuilder()
+ .WithValidator(null)
+ .Decode<IDictionary<string, object>>(token);
+
+ webToken.AccessToken = token;
+
+ if (payload.ContainsKey("exp"))
+ {
+ long exp = long.Parse(payload["exp"].ToString());
+ webToken.Expiration = ConvertEpochToDateTime(exp);
+ }
+
+ if (payload.ContainsKey("iat"))
+ {
+ long iat = long.Parse(payload["iat"].ToString());
+ webToken.Issued = ConvertEpochToDateTime(iat);
+ }
+
+ return webToken;
+ }
+
+ protected static DateTime ConvertEpochToDateTime(long seconds)
+ {
+ var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ return epoch.AddSeconds(seconds);
+ }
+ }
+
+ public class WebToken<T> : WebToken where T : class
+ {
+ public T Object { get; protected set; }
+
+ private WebToken()
+ {
+
+ }
+
+ public static WebToken<T> CreateNew(String secret, T obj = null, DateTime? expiration = null)
+ {
+ DateTime issued = DateTime.UtcNow;
+
+ var builder = new JwtBuilder()
+ .WithAlgorithm(new HMACSHA256Algorithm())
+ .WithSecret(secret)
+ .IssuedAt(issued);
+
+ if (expiration != null)
+ {
+ builder = builder.ExpirationTime(expiration.Value);
+ }
+
+ builder = builder.AddClaim("object", obj);
+
+ return new WebToken<T>()
+ {
+ AccessToken = builder.Build(),
+ RefreshToken = Guid.NewGuid().ToString(),
+ Expiration = expiration,
+ Issued = issued,
+ Object = obj,
+ };
+ }
+
+ public static new WebToken<T> FromToken(String token)
+ {
+ WebToken<T> webToken = new WebToken<T>();
+
+ var payload = new JwtBuilder()
+ .WithValidator(null)
+ .Decode<IDictionary<string, object>>(token);
+
+ webToken.AccessToken = token;
+
+ if (payload.ContainsKey("exp"))
+ {
+ long exp = long.Parse(payload["exp"].ToString());
+ webToken.Expiration = ConvertEpochToDateTime(exp);
+ }
+
+ if (payload.ContainsKey("iat"))
+ {
+ long iat = long.Parse(payload["iat"].ToString());
+ webToken.Issued = ConvertEpochToDateTime(iat);
+ }
+
+ webToken.Object = JsonConvert.DeserializeObject<T>(payload["object"].ToString());
+
+ return webToken;
+ }
+
+ public new WebToken<T> Renew(String secret, String token)
+ {
+ WebToken<T> webToken = WebToken<T>.FromToken(token);
+ var newToken = WebToken<T>.CreateNew(secret, webToken.Object, DateTime.UtcNow.Add(webToken.Expiration.Value - webToken.Issued));
+ newToken.RefreshToken = webToken.RefreshToken;
+ return newToken;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Web/Security/WebTokenResponse.cs b/Software/Visual_Studio/Tango.Web/Security/WebTokenResponse.cs
new file mode 100644
index 000000000..8c8f2f096
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Web/Security/WebTokenResponse.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Transport.Web;
+
+namespace Tango.Web.Security
+{
+ public class WebTokenResponse : WebResponseMessage
+ {
+ public String AccessToken { get; set; }
+ public String RefreshToken { get; set; }
+ }
+}