From 9447a8a09f87d6ea2cb62860021c595386668eec Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Wed, 20 Feb 2019 22:55:15 +0200 Subject: A lot of work !!! --- .../Web/CheckForUpdatesRequest.cs | 2 +- .../Web/DownloadLatestVersionRequest.cs | 2 +- .../Web/MachineStudioWebClient.cs | 9 +++++++-- .../Web/MachineStudioWebClientBase.cs | 14 ++++++++++++-- .../Web/UploadCompletedRequest.cs | 2 +- .../Tango.MachineStudio.Common/Web/UploadVersionRequest.cs | 2 +- .../MachineStudio/Tango.MachineStudio.Common/app.config | 2 +- 7 files changed, 24 insertions(+), 9 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/CheckForUpdatesRequest.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/CheckForUpdatesRequest.cs index 4f9576f50..84616c607 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/CheckForUpdatesRequest.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/CheckForUpdatesRequest.cs @@ -8,7 +8,7 @@ using Tango.Transport.Web; namespace Tango.MachineStudio.Common.Web { - public class CheckForUpdatesRequest : WebRequestSecureMessage + public class CheckForUpdatesRequest : WebRequestMessage { public String Version { get; set; } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestVersionRequest.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestVersionRequest.cs index d63654726..e0a47041c 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestVersionRequest.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/DownloadLatestVersionRequest.cs @@ -7,7 +7,7 @@ using Tango.Transport.Web; namespace Tango.MachineStudio.Common.Web { - public class DownloadLatestVersionRequest : WebRequestSecureMessage + public class DownloadLatestVersionRequest : WebRequestMessage { } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClient.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClient.cs index 02276d641..7938e1a17 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClient.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClient.cs @@ -15,12 +15,17 @@ namespace Tango.MachineStudio.Common.Web { } - public MachineStudioWebClient(DeploymentSlot environment, WebToken token) : base(environment, token) + public MachineStudioWebClient(DeploymentSlot environment, String token) : base(environment, token) { } - public MachineStudioWebClient(WebToken token) : this(SettingsManager.Default.GetOrCreate().DeploymentSlot, token) + public MachineStudioWebClient(String token) : this(SettingsManager.Default.GetOrCreate().DeploymentSlot, token) + { + + } + + public MachineStudioWebClient(string address, string token) : base(address, token) { } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs index dc5a14856..62a57ad93 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClientBase.cs @@ -1,7 +1,7 @@ +using System; using System.Threading.Tasks; using Tango.Web; -using Tango.Web.Authentication; namespace Tango.MachineStudio.Common.Web { @@ -16,7 +16,7 @@ namespace Tango.MachineStudio.Common.Web /// /// The environment. /// Existing token. - public MachineStudioWebClientBase(DeploymentSlot environment, WebToken token) : base(environment, "MachineStudio", token) + public MachineStudioWebClientBase(DeploymentSlot environment, String token) : base(environment, "MachineStudio", token) { } @@ -30,6 +30,16 @@ namespace Tango.MachineStudio.Common.Web } + /// + /// Initializes a new instance of the class. + /// + /// The service address. + /// Existing token. + public MachineStudioWebClientBase(String address, String token) : base(address, "MachineStudio", token) + { + + } + /// /// Executes the CheckForUpdates action and returns Tango.MachineStudio.Common.Web.CheckForUpdatesResponse. /// diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/UploadCompletedRequest.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/UploadCompletedRequest.cs index 48f5b2a6e..c85dd3ace 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/UploadCompletedRequest.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/UploadCompletedRequest.cs @@ -8,7 +8,7 @@ using Tango.Transport.Web; namespace Tango.MachineStudio.Common.Web { - public class UploadCompletedRequest : WebRequestSecureMessage + public class UploadCompletedRequest : WebRequestMessage { public String Token { get; set; } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/UploadVersionRequest.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/UploadVersionRequest.cs index 33577deb2..d27f48648 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/UploadVersionRequest.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/UploadVersionRequest.cs @@ -8,7 +8,7 @@ using Tango.Transport.Web; namespace Tango.MachineStudio.Common.Web { - public class UploadVersionRequest : WebRequestSecureMessage + public class UploadVersionRequest : WebRequestMessage { public String Version { get; set; } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/app.config b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/app.config index d9be669f7..fa31bbb95 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/app.config +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/app.config @@ -68,7 +68,7 @@ - + -- cgit v1.3.1 From 0adea9eb464a3f2d5d73b2c8c26d32e0d1a3874b Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sun, 24 Feb 2019 00:57:14 +0200 Subject: Working on refresh tokens... --- .../Tango.MachineStudio.Common.csproj | 2 +- .../Web/LoginResponse.cs | 2 +- .../Web/MachineStudioWebClient.cs | 2 +- .../PPC/Tango.PPC.Common/Web/LoginResponse.cs | 2 +- .../PPC/Tango.PPC.Common/Web/PPCWebClient.cs | 2 +- .../Tango.UnitTesting/Web/JWT_Tokens_TST.cs | 2 +- .../Tango.Web/Authentication/TokensManager.cs | 82 ---------- .../Tango.Web/Authentication/WebToken.cs | 159 ------------------ .../Tango.Web/Authentication/WebTokenResponse.cs | 14 -- .../Tango.Web/Controllers/TangoController.cs | 2 +- .../ExtensionMethods/CloudTableExtensions.cs | 69 ++++++++ .../Tango.Web/Security/RefreshTokenEntity.cs | 24 +++ .../Tango.Web/Security/RenewTokenRequest.cs | 14 ++ .../Tango.Web/Security/RenewTokenResponse.cs | 14 ++ .../Tango.Web/Security/TokensManager.cs | 82 ++++++++++ .../Visual_Studio/Tango.Web/Security/WebToken.cs | 178 +++++++++++++++++++++ .../Tango.Web/Security/WebTokenResponse.cs | 15 ++ .../Tango.Web/Storage/BlobStorageManager.cs | 27 ++++ .../Tango.Web/Storage/StorageManager.cs | 27 ---- .../Tango.Web/Storage/TableStorageManager.cs | 26 +++ Software/Visual_Studio/Tango.Web/Tango.Web.csproj | 13 +- Software/Visual_Studio/Tango.Web/TangoWebClient.cs | 23 ++- .../Utilities/Tango.WebClientGenerator/Program.cs | 2 +- .../Controllers/MachineStudioController.cs | 36 ++++- .../Controllers/PPCController.cs | 8 +- .../Tango.MachineService/Filters/JwtTokenFilter.cs | 19 ++- .../Tango.MachineService/MachineServiceConfig.cs | 2 + .../Security/RefreshTokenEncoder.cs | 26 +++ .../Security/RefreshTokensManager.cs | 31 ++++ .../Tango.MachineService.csproj | 4 +- .../Web/Tango.MachineService/Web.config | 4 +- 31 files changed, 604 insertions(+), 309 deletions(-) delete mode 100644 Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs delete mode 100644 Software/Visual_Studio/Tango.Web/Authentication/WebToken.cs delete mode 100644 Software/Visual_Studio/Tango.Web/Authentication/WebTokenResponse.cs create mode 100644 Software/Visual_Studio/Tango.Web/ExtensionMethods/CloudTableExtensions.cs create mode 100644 Software/Visual_Studio/Tango.Web/Security/RefreshTokenEntity.cs create mode 100644 Software/Visual_Studio/Tango.Web/Security/RenewTokenRequest.cs create mode 100644 Software/Visual_Studio/Tango.Web/Security/RenewTokenResponse.cs create mode 100644 Software/Visual_Studio/Tango.Web/Security/TokensManager.cs create mode 100644 Software/Visual_Studio/Tango.Web/Security/WebToken.cs create mode 100644 Software/Visual_Studio/Tango.Web/Security/WebTokenResponse.cs create mode 100644 Software/Visual_Studio/Tango.Web/Storage/BlobStorageManager.cs delete mode 100644 Software/Visual_Studio/Tango.Web/Storage/StorageManager.cs create mode 100644 Software/Visual_Studio/Tango.Web/Storage/TableStorageManager.cs create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEncoder.cs create mode 100644 Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokensManager.cs (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj index 48c78e865..3f9133d43 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Tango.MachineStudio.Common.csproj @@ -326,7 +326,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginResponse.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginResponse.cs index 78c7bc560..4ae22fa93 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginResponse.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/LoginResponse.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Tango.Core; using Tango.Transport.Web; -using Tango.Web.Authentication; +using Tango.Web.Security; namespace Tango.MachineStudio.Common.Web { diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClient.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClient.cs index 7938e1a17..a03f94c78 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClient.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Web/MachineStudioWebClient.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Tango.Settings; using Tango.Web; -using Tango.Web.Authentication; +using Tango.Web.Security; namespace Tango.MachineStudio.Common.Web { diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LoginResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LoginResponse.cs index 5d97c6470..73da9ce8f 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LoginResponse.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/LoginResponse.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Transport.Web; -using Tango.Web.Authentication; +using Tango.Web.Security; namespace Tango.PPC.Common.Web { diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs index 4897efc90..52c9fdef3 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Tango.Settings; using Tango.Web; -using Tango.Web.Authentication; +using Tango.Web.Security; namespace Tango.PPC.Common.Web { diff --git a/Software/Visual_Studio/Tango.UnitTesting/Web/JWT_Tokens_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/Web/JWT_Tokens_TST.cs index ff698f18f..d696a627c 100644 --- a/Software/Visual_Studio/Tango.UnitTesting/Web/JWT_Tokens_TST.cs +++ b/Software/Visual_Studio/Tango.UnitTesting/Web/JWT_Tokens_TST.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; -using Tango.Web.Authentication; +using Tango.Web.Security; namespace Tango.UnitTesting.Web { diff --git a/Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs b/Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs deleted file mode 100644 index 5829bfca3..000000000 --- a/Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs +++ /dev/null @@ -1,82 +0,0 @@ -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.Authentication -{ - public class TokensManager where T : IEquatable - { - private Dictionary _tokens; - - private class TokenWrapper : IEquatable - { - 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(); - 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/Authentication/WebToken.cs b/Software/Visual_Studio/Tango.Web/Authentication/WebToken.cs deleted file mode 100644 index 14fc49942..000000000 --- a/Software/Visual_Studio/Tango.Web/Authentication/WebToken.cs +++ /dev/null @@ -1,159 +0,0 @@ -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.Authentication -{ - public class WebToken - { - public DateTime Issued { get; protected set; } - public DateTime? Expiration { get; protected set; } - public String AccessToken { 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(), - 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 static WebToken FromToken(String token) - { - WebToken webToken = new WebToken(); - - var payload = new JwtBuilder() - .WithValidator(null) - .Decode>(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 : WebToken where T : class - { - public T Object { get; protected set; } - - private WebToken() - { - - } - - public static WebToken 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() - { - AccessToken = builder.Build(), - Expiration = expiration, - Issued = issued, - Object = obj, - }; - } - - public static new WebToken FromToken(String token) - { - WebToken webToken = new WebToken(); - - var payload = new JwtBuilder() - .WithValidator(null) - .Decode>(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(payload["object"].ToString()); - - return webToken; - } - } -} diff --git a/Software/Visual_Studio/Tango.Web/Authentication/WebTokenResponse.cs b/Software/Visual_Studio/Tango.Web/Authentication/WebTokenResponse.cs deleted file mode 100644 index 190a47cc2..000000000 --- a/Software/Visual_Studio/Tango.Web/Authentication/WebTokenResponse.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Transport.Web; - -namespace Tango.Web.Authentication -{ - public class WebTokenResponse : WebResponseMessage - { - public String AccessToken { get; set; } - } -} diff --git a/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs b/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs index 854d1cf96..32cc3f83c 100644 --- a/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs +++ b/Software/Visual_Studio/Tango.Web/Controllers/TangoController.cs @@ -11,7 +11,7 @@ using System.Web.Http; using System.Web.Http.Controllers; using Tango.Logging; using Tango.Transport.Web; -using Tango.Web.Authentication; +using Tango.Web.Security; namespace Tango.Web.Controllers { diff --git a/Software/Visual_Studio/Tango.Web/ExtensionMethods/CloudTableExtensions.cs b/Software/Visual_Studio/Tango.Web/ExtensionMethods/CloudTableExtensions.cs new file mode 100644 index 000000000..43c4804d3 --- /dev/null +++ b/Software/Visual_Studio/Tango.Web/ExtensionMethods/CloudTableExtensions.cs @@ -0,0 +1,69 @@ +using Microsoft.WindowsAzure.Storage.Table; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + + +public static class CloudTableExtensions +{ + /// + /// Demonstrate the most efficient storage query - the point query - where both partition key and row key are specified. + /// + /// Sample table name + /// Partition key - i.e., last name + /// Row key - i.e., first name + /// A Task object + public static async Task GetEntityAsync(this CloudTable table, string partitionKey, string rowKey) where T : class, ITableEntity + { + TableOperation retrieveOperation = TableOperation.Retrieve(partitionKey, rowKey); + TableResult result = await table.ExecuteAsync(retrieveOperation); + T customer = result.Result as T; + return customer; + } + + /// + /// The Table Service supports two main types of insert operations. + /// 1. Insert - insert a new entity. If an entity already exists with the same PK + RK an exception will be thrown. + /// 2. Replace - replace an existing entity. Replace an existing entity with a new entity. + /// 3. Insert or Replace - insert the entity if the entity does not exist, or if the entity exists, replace the existing one. + /// 4. Insert or Merge - insert the entity if the entity does not exist or, if the entity exists, merges the provided entity properties with the already existing ones. + /// + /// The sample table name + /// The entity to insert or merge + /// A Task object + public static async Task InsertOrUpdateEntityAsync(this CloudTable table, T entity) where T : class, ITableEntity + { + if (entity == null) + { + throw new ArgumentNullException("Specified entity is null."); + } + + // Create the InsertOrReplace table operation + TableOperation insertOrMergeOperation = TableOperation.InsertOrMerge(entity); + + // Execute the operation. + TableResult result = await table.ExecuteAsync(insertOrMergeOperation); + T insertedCustomer = result.Result as T; + + return insertedCustomer; + } + + /// + /// Delete an entity + /// + /// Sample table name + /// Entity to delete + /// A Task object + public static async Task DeleteEntityAsync(this CloudTable table, T deleteEntity) where T : class, ITableEntity + { + if (deleteEntity == null) + { + throw new ArgumentNullException("Specified entity was null."); + } + + TableOperation deleteOperation = TableOperation.Delete(deleteEntity); + await table.ExecuteAsync(deleteOperation); + } +} 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 + { + /// + /// Initializes a new instance of the class. + /// + 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 where T : IEquatable + { + private Dictionary _tokens; + + private class TokenWrapper : IEquatable + { + 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(); + 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>(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 : WebToken where T : class + { + public T Object { get; protected set; } + + private WebToken() + { + + } + + public static WebToken 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() + { + AccessToken = builder.Build(), + RefreshToken = Guid.NewGuid().ToString(), + Expiration = expiration, + Issued = issued, + Object = obj, + }; + } + + public static new WebToken FromToken(String token) + { + WebToken webToken = new WebToken(); + + var payload = new JwtBuilder() + .WithValidator(null) + .Decode>(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(payload["object"].ToString()); + + return webToken; + } + + public new WebToken Renew(String secret, String token) + { + WebToken webToken = WebToken.FromToken(token); + var newToken = WebToken.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; } + } +} diff --git a/Software/Visual_Studio/Tango.Web/Storage/BlobStorageManager.cs b/Software/Visual_Studio/Tango.Web/Storage/BlobStorageManager.cs new file mode 100644 index 000000000..d3f8b1dc4 --- /dev/null +++ b/Software/Visual_Studio/Tango.Web/Storage/BlobStorageManager.cs @@ -0,0 +1,27 @@ +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Blob; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Web.Storage +{ + public class BlobStorageManager + { + private CloudBlobClient _client; + + public BlobStorageManager() + { + CloudStorageAccount storageAccount = CloudStorageAccount.Parse(WebConfig.STORAGE_ACCOUNT); + _client = storageAccount.CreateCloudBlobClient(); + } + + public CloudBlobContainer GetContainer(String name) + { + var container = _client.GetContainerReference(name); + return container; + } + } +} diff --git a/Software/Visual_Studio/Tango.Web/Storage/StorageManager.cs b/Software/Visual_Studio/Tango.Web/Storage/StorageManager.cs deleted file mode 100644 index 17b01d1e2..000000000 --- a/Software/Visual_Studio/Tango.Web/Storage/StorageManager.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Blob; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.Web.Storage -{ - public class StorageManager - { - private CloudBlobClient _client; - - public StorageManager() - { - CloudStorageAccount storageAccount = CloudStorageAccount.Parse(WebConfig.STORAGE_ACCOUNT); - _client = storageAccount.CreateCloudBlobClient(); - } - - public CloudBlobContainer GetContainer(String name) - { - var container = _client.GetContainerReference(name); - return container; - } - } -} diff --git a/Software/Visual_Studio/Tango.Web/Storage/TableStorageManager.cs b/Software/Visual_Studio/Tango.Web/Storage/TableStorageManager.cs new file mode 100644 index 000000000..7b3a3d513 --- /dev/null +++ b/Software/Visual_Studio/Tango.Web/Storage/TableStorageManager.cs @@ -0,0 +1,26 @@ +using Microsoft.WindowsAzure.Storage; +using Microsoft.WindowsAzure.Storage.Table; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Web.Storage +{ + public class TableStorageManager + { + private CloudTableClient _client; + + public TableStorageManager() + { + CloudStorageAccount storageAccount = CloudStorageAccount.Parse(WebConfig.STORAGE_ACCOUNT); + _client = storageAccount.CreateCloudTableClient(); + } + + public CloudTable GetTable(String name) + { + return _client.GetTableReference(name); + } + } +} diff --git a/Software/Visual_Studio/Tango.Web/Tango.Web.csproj b/Software/Visual_Studio/Tango.Web/Tango.Web.csproj index 961ec04e8..621014496 100644 --- a/Software/Visual_Studio/Tango.Web/Tango.Web.csproj +++ b/Software/Visual_Studio/Tango.Web/Tango.Web.csproj @@ -248,16 +248,21 @@ GlobalVersionInfo.cs - - - + + + + + + + - + + diff --git a/Software/Visual_Studio/Tango.Web/TangoWebClient.cs b/Software/Visual_Studio/Tango.Web/TangoWebClient.cs index 42a9d801c..08fc19099 100644 --- a/Software/Visual_Studio/Tango.Web/TangoWebClient.cs +++ b/Software/Visual_Studio/Tango.Web/TangoWebClient.cs @@ -5,7 +5,7 @@ using System.Security.Authentication; using System.Text; using System.Threading.Tasks; using Tango.Transport.Web; -using Tango.Web.Authentication; +using Tango.Web.Security; namespace Tango.Web { @@ -70,13 +70,29 @@ namespace Tango.Web return response; } + private async Task Renew() + { + var response = await _client.PostJson(GetActionAddress("Renew"), new RenewTokenRequest() + { + RefreshToken = WebToken.RefreshToken, + }); + + Token = response.AccessToken; + _client.AuthenticationToken = Token; + + WebToken = WebToken.FromToken(Token); + + IsAuthenticated = true; + } + protected virtual async Task Post(String action, TRequest request) where TRequest : class, IWebRequestMessage where TResponse : class, IWebResponseMessage { if (IsAuthenticated) { if (DateTime.UtcNow >= WebToken.Expiration) { - await Login(_lastLoginRequest); + await Renew(); + //await Login(_lastLoginRequest); } } @@ -89,7 +105,8 @@ namespace Tango.Web { try { - await Login(_lastLoginRequest); + //await Login(_lastLoginRequest); + await Renew(); var response = await _client.PostJson(GetActionAddress(action), request); return response; } diff --git a/Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs b/Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs index d645f0e5e..6bbcd1884 100644 --- a/Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs +++ b/Software/Visual_Studio/Utilities/Tango.WebClientGenerator/Program.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Tango.CodeGeneration; using Tango.Core.Helpers; using Tango.Transport.Web; -using Tango.Web.Authentication; +using Tango.Web.Security; using Tango.Web.Controllers; namespace Tango.WebClientGenerator diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs index 467b6ae28..324878f25 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs @@ -18,9 +18,10 @@ using Tango.MachineStudio.Common.Web; using Tango.Web.Controllers; using Tango.Web.Helpers; using Tango.Web.Storage; -using Tango.Web.Authentication; +using Tango.Web.Security; using Tango.Web.ActiveDirectory; using Tango.MachineService.Filters; +using Tango.MachineService.Security; namespace Tango.MachineService.Controllers { @@ -34,6 +35,12 @@ namespace Tango.MachineService.Controllers public String UserGuid { get; set; } } + public class RefreshTokenObject + { + public String Email { get; set; } + public String Password { get; set; } + } + #region Constructors /// @@ -85,7 +92,7 @@ namespace Tango.MachineService.Controllers if (latestVersion != null && Version.Parse(latestVersion.Version) > currentVersion) { - var manager = new StorageManager(); + var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.MACHINE_STUDIO_VERSIONS_CONTAINER); var blob = container.GetBlockBlobReference(latestVersion.BlobName); @@ -121,7 +128,7 @@ namespace Tango.MachineService.Controllers if (latestVersion != null) { - var manager = new StorageManager(); + var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.MACHINE_STUDIO_VERSIONS_CONTAINER); var blob = container.GetBlockBlobReference(latestVersion.BlobName); @@ -161,7 +168,7 @@ namespace Tango.MachineService.Controllers { String newVersionFileName = "Machine Studio Version" + " " + currentVersion.ToString() + ".zip"; - var manager = new StorageManager(); + var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.MACHINE_STUDIO_VERSIONS_CONTAINER); var blob = container.CreateEmptyBlob(newVersionFileName); @@ -359,6 +366,27 @@ namespace Tango.MachineService.Controllers }; } + [HttpPost] + [JwtTokenFilter(allowExpired: true)] + public RenewTokenResponse Renew(RenewTokenRequest request) + { + RefreshTokensManager manager = new RefreshTokensManager(); + var entity = manager.GetToken(request.RefreshToken); + + if (entity.AccessToken != RequestToken.AccessToken) + { + throw new AuthenticationException("Invalid access token and refresh token combination."); + } + + var newToken = RequestToken.Renew(MachineServiceConfig.JWT_TOKEN_SECRET, entity.AccessToken); + + return new RenewTokenResponse() + { + AccessToken = entity.AccessToken, + RefreshToken = entity.RefreshToken, + }; + } + #endregion } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index edbab8cbe..0f36fa040 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -19,7 +19,7 @@ using Tango.Web.Helpers; using Tango.Web.SMO; using Tango.Web.Storage; using System.Data.Entity; -using Tango.Web.Authentication; +using Tango.Web.Security; using Tango.Web.ActiveDirectory; using Tango.Core.Cryptography; using Tango.MachineService.Filters; @@ -86,7 +86,7 @@ namespace Tango.MachineService.Controllers response.Version = latest_machine_version.Version; - var manager = new StorageManager(); + var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); var blob = container.GetBlockBlobReference(latest_machine_version.BlobName); @@ -153,7 +153,7 @@ namespace Tango.MachineService.Controllers response.Version = latest_machine_version.Version; - var manager = new StorageManager(); + var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); var blob = container.GetBlockBlobReference(latest_machine_version.BlobName); @@ -331,7 +331,7 @@ namespace Tango.MachineService.Controllers { String newVersionFileName = $"{machine_version.Name} - Tango Version {currentVersion.ToString()}.tup"; - var manager = new StorageManager(); + var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); var blob = container.CreateEmptyBlob(newVersionFileName); diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Filters/JwtTokenFilter.cs b/Software/Visual_Studio/Web/Tango.MachineService/Filters/JwtTokenFilter.cs index 4cf22cc43..d4b87f1d5 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Filters/JwtTokenFilter.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Filters/JwtTokenFilter.cs @@ -10,12 +10,24 @@ using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters; using Tango.Transport.Web; -using Tango.Web.Authentication; +using Tango.Web.Security; namespace Tango.MachineService.Filters { public class JwtTokenFilter : ActionFilterAttribute { + public bool AllowExpired { get; private set; } + + public JwtTokenFilter() + { + + } + + public JwtTokenFilter(bool allowExpired) + { + AllowExpired = allowExpired; + } + public override void OnActionExecuting(HttpActionContext actionContext) { var authorizationHeader = actionContext.Request.Headers.Authorization; @@ -28,7 +40,10 @@ namespace Tango.MachineService.Filters } catch (JWT.TokenExpiredException) { - throw new TokenExpiredException("Token expired."); + if (!AllowExpired) + { + throw new TokenExpiredException("Token expired."); + } } catch (JWT.SignatureVerificationException) { diff --git a/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs b/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs index a6aa71944..0e6d18ddf 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs @@ -13,5 +13,7 @@ namespace Tango.MachineService public static String MACHINE_STUDIO_VERSIONS_CONTAINER => ConfigurationManager.AppSettings[nameof(MACHINE_STUDIO_VERSIONS_CONTAINER)].ToString(); public static bool ENFORCE_MACHINE_STUDIO_VERSION => bool.Parse(ConfigurationManager.AppSettings[nameof(ENFORCE_MACHINE_STUDIO_VERSION)].ToString()); public static String JWT_TOKEN_SECRET => ConfigurationManager.AppSettings[nameof(JWT_TOKEN_SECRET)].ToString(); + public static String REFRESH_TOKENS_TABLE_NAME => ConfigurationManager.AppSettings[nameof(REFRESH_TOKENS_TABLE_NAME)].ToString(); + public static String REFRESH_TOKENS_TABLE_PARTITION => ConfigurationManager.AppSettings[nameof(REFRESH_TOKENS_TABLE_PARTITION)].ToString(); } } \ No newline at end of file diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEncoder.cs b/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEncoder.cs new file mode 100644 index 000000000..3948ae1c4 --- /dev/null +++ b/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEncoder.cs @@ -0,0 +1,26 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using Tango.Core.Cryptography; + +namespace Tango.MachineService.Security +{ + public class RefreshTokenEncoder + { + public String Encode(T obj) + { + String str = obj.ToJsonString(); + Rfc2898Cryptographer crypt = new Rfc2898Cryptographer(); + return crypt.Encrypt(str); + } + + public T Decode(String token) + { + Rfc2898Cryptographer crypt = new Rfc2898Cryptographer(); + String str = crypt.Decrypt(token); + return JsonConvert.DeserializeObject(str); + } + } +} \ No newline at end of file diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokensManager.cs b/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokensManager.cs new file mode 100644 index 000000000..5cc206c63 --- /dev/null +++ b/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokensManager.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using Tango.Web.Security; +using Tango.Web.Storage; + +namespace Tango.MachineService.Security +{ + public class RefreshTokensManager + { + private TableStorageManager _manager; + + public RefreshTokensManager() + { + _manager = new TableStorageManager(); + } + + public RefreshTokenEntity GetToken(String refreshToken) + { + var table = _manager.GetTable(MachineServiceConfig.REFRESH_TOKENS_TABLE_NAME); + return table.GetEntityAsync(MachineServiceConfig.REFRESH_TOKENS_TABLE_PARTITION, refreshToken).Result; + } + + public RefreshTokenEntity InsertOrUpdate(RefreshTokenEntity refreshTokenEntity) + { + var table = _manager.GetTable(MachineServiceConfig.REFRESH_TOKENS_TABLE_NAME); + return table.InsertOrUpdateEntityAsync(refreshTokenEntity).Result; + } + } +} \ No newline at end of file diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj index 6dbbe49ab..22be33277 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj +++ b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj @@ -290,6 +290,8 @@ Global.asax + + @@ -381,7 +383,7 @@ False - + diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Web.config b/Software/Visual_Studio/Web/Tango.MachineService/Web.config index fb10e615e..d7413de62 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Web.config +++ b/Software/Visual_Studio/Web/Tango.MachineService/Web.config @@ -26,7 +26,9 @@ - + + +