diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2019-02-24 00:57:14 +0200 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2019-02-24 00:57:14 +0200 |
| commit | 0adea9eb464a3f2d5d73b2c8c26d32e0d1a3874b (patch) | |
| tree | bb5e4055020aa4417e1f7703a611353ce44689d6 /Software/Visual_Studio | |
| parent | 17612c08da93c75d4c941a643bc7602c18f351d8 (diff) | |
| download | Tango-0adea9eb464a3f2d5d73b2c8c26d32e0d1a3874b.tar.gz Tango-0adea9eb464a3f2d5d73b2c8c26d32e0d1a3874b.zip | |
Working on refresh tokens...
Diffstat (limited to 'Software/Visual_Studio')
27 files changed, 327 insertions, 32 deletions
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 @@ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <ProjectExtensions> <VisualStudio> - <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" /> + <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" /> </VisualStudio> </ProjectExtensions> </Project>
\ 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/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 +{ + /// <summary> + /// Demonstrate the most efficient storage query - the point query - where both partition key and row key are specified. + /// </summary> + /// <param name="table">Sample table name</param> + /// <param name="partitionKey">Partition key - i.e., last name</param> + /// <param name="rowKey">Row key - i.e., first name</param> + /// <returns>A Task object</returns> + public static async Task<T> GetEntityAsync<T>(this CloudTable table, string partitionKey, string rowKey) where T : class, ITableEntity + { + TableOperation retrieveOperation = TableOperation.Retrieve<T>(partitionKey, rowKey); + TableResult result = await table.ExecuteAsync(retrieveOperation); + T customer = result.Result as T; + return customer; + } + + /// <summary> + /// 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. + /// </summary> + /// <param name="table">The sample table name</param> + /// <param name="entity">The entity to insert or merge</param> + /// <returns>A Task object</returns> + public static async Task<T> InsertOrUpdateEntityAsync<T>(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; + } + + /// <summary> + /// Delete an entity + /// </summary> + /// <param name="table">Sample table name</param> + /// <param name="deleteEntity">Entity to delete</param> + /// <returns>A Task object</returns> + public static async Task DeleteEntityAsync<T>(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 + { + /// <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/Authentication/TokensManager.cs b/Software/Visual_Studio/Tango.Web/Security/TokensManager.cs index 5829bfca3..bf5574766 100644 --- a/Software/Visual_Studio/Tango.Web/Authentication/TokensManager.cs +++ b/Software/Visual_Studio/Tango.Web/Security/TokensManager.cs @@ -6,7 +6,7 @@ using System.Text; using System.Threading.Tasks; using Tango.Transport.Web; -namespace Tango.Web.Authentication +namespace Tango.Web.Security { public class TokensManager<T> where T : IEquatable<T> { diff --git a/Software/Visual_Studio/Tango.Web/Authentication/WebToken.cs b/Software/Visual_Studio/Tango.Web/Security/WebToken.cs index 14fc49942..006ed9de7 100644 --- a/Software/Visual_Studio/Tango.Web/Authentication/WebToken.cs +++ b/Software/Visual_Studio/Tango.Web/Security/WebToken.cs @@ -10,13 +10,14 @@ using System.Security.Claims; using System.Text; using System.Threading.Tasks; -namespace Tango.Web.Authentication +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() { @@ -42,6 +43,7 @@ namespace Tango.Web.Authentication return new WebToken() { AccessToken = builder.Build(), + RefreshToken = Guid.NewGuid().ToString(), Expiration = expiration, Issued = issued, }; @@ -63,6 +65,14 @@ namespace Tango.Web.Authentication .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(); @@ -123,6 +133,7 @@ namespace Tango.Web.Authentication return new WebToken<T>() { AccessToken = builder.Build(), + RefreshToken = Guid.NewGuid().ToString(), Expiration = expiration, Issued = issued, Object = obj, @@ -155,5 +166,13 @@ namespace Tango.Web.Authentication 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/Authentication/WebTokenResponse.cs b/Software/Visual_Studio/Tango.Web/Security/WebTokenResponse.cs index 190a47cc2..8c8f2f096 100644 --- a/Software/Visual_Studio/Tango.Web/Authentication/WebTokenResponse.cs +++ b/Software/Visual_Studio/Tango.Web/Security/WebTokenResponse.cs @@ -5,10 +5,11 @@ using System.Text; using System.Threading.Tasks; using Tango.Transport.Web; -namespace Tango.Web.Authentication +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/StorageManager.cs b/Software/Visual_Studio/Tango.Web/Storage/BlobStorageManager.cs index 17b01d1e2..d3f8b1dc4 100644 --- a/Software/Visual_Studio/Tango.Web/Storage/StorageManager.cs +++ b/Software/Visual_Studio/Tango.Web/Storage/BlobStorageManager.cs @@ -8,11 +8,11 @@ using System.Threading.Tasks; namespace Tango.Web.Storage { - public class StorageManager + public class BlobStorageManager { private CloudBlobClient _client; - public StorageManager() + public BlobStorageManager() { CloudStorageAccount storageAccount = CloudStorageAccount.Parse(WebConfig.STORAGE_ACCOUNT); _client = storageAccount.CreateCloudBlobClient(); 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 @@ <Link>GlobalVersionInfo.cs</Link> </Compile> <Compile Include="ActiveDirectory\ActiveDirectoryManager.cs" /> - <Compile Include="Authentication\WebTokenResponse.cs" /> - <Compile Include="Authentication\TokensManager.cs" /> - <Compile Include="Authentication\WebToken.cs" /> + <Compile Include="Security\RefreshTokenEntity.cs" /> + <Compile Include="Security\RenewTokenResponse.cs" /> + <Compile Include="Security\RenewTokenRequest.cs" /> + <Compile Include="Security\WebTokenResponse.cs" /> + <Compile Include="Security\TokensManager.cs" /> + <Compile Include="Security\WebToken.cs" /> <Compile Include="DeploymentSlot.cs" /> <Compile Include="DeploymentSlotAddressAttribute.cs" /> + <Compile Include="ExtensionMethods\CloudTableExtensions.cs" /> <Compile Include="ExtensionMethods\DeploymentSlotExtensions.cs" /> <Compile Include="Logging\AzureCloudLogger.cs" /> <Compile Include="SQLServer\SQLServerManager.cs" /> <Compile Include="Storage\ExtensionMethods.cs" /> - <Compile Include="Storage\StorageManager.cs" /> + <Compile Include="Storage\BlobStorageManager.cs" /> + <Compile Include="Storage\TableStorageManager.cs" /> <Compile Include="TangoWebApplication.cs" /> <Compile Include="TangoWebClient.cs" /> <Compile Include="WebConfig.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<RenewTokenRequest, RenewTokenResponse>(GetActionAddress("Renew"), new RenewTokenRequest() + { + RefreshToken = WebToken.RefreshToken, + }); + + Token = response.AccessToken; + _client.AuthenticationToken = Token; + + WebToken = WebToken.FromToken(Token); + + IsAuthenticated = true; + } + protected virtual async Task<TResponse> Post<TRequest, TResponse>(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<TRequest, TResponse>(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 /// <summary> @@ -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<T> + { + 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<T>(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<RefreshTokenEntity>(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 @@ <DependentUpon>Global.asax</DependentUpon> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Security\RefreshTokenEncoder.cs" /> + <Compile Include="Security\RefreshTokensManager.cs" /> </ItemGroup> <ItemGroup> <Content Include="Global.asax" /> @@ -381,7 +383,7 @@ <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> </WebProjectProperties> </FlavorProperties> - <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" /> + <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" /> </VisualStudio> </ProjectExtensions> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> 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 @@ <add key="DEPLOYMENT_SLOT" value="DEV" /> <add key="ENVIRONMENT_GROUP" value="Tango DEV" /> <add key="ENFORCE_MACHINE_STUDIO_VERSION" value="true" /> - <add key="JWT_TOKEN_SECRET" value="GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk" /> + <add key="JWT_TOKEN_SECRET" value="GQDstcKsx0NHjLOuXOYg5MbeJ1yT0u1iwDVTwine" /> + <add key="REFRESH_TOKENS_TABLE_NAME" value="RefreshTokens" /> + <add key="REFRESH_TOKENS_TABLE_PARTITION" value="REFRESH_TOKENS_PART" /> </appSettings> <!-- For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367. |
