aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Web/Tango.MachineService
diff options
context:
space:
mode:
authorShlomo Hecht <shlomo@twine-s.com>2019-02-25 11:02:07 +0200
committerShlomo Hecht <shlomo@twine-s.com>2019-02-25 11:02:07 +0200
commitb462fdd744f491b04137fd99863f6cb6c623cfa0 (patch)
tree2f69f8e953450a0452442c24f3809aec84ce7db0 /Software/Visual_Studio/Web/Tango.MachineService
parenta8ddb23154fe5111c9509fa0a83dcc36adcba4ee (diff)
parent44a35db8a2929fb3f6aa56ed08185e066292f106 (diff)
downloadTango-b462fdd744f491b04137fd99863f6cb6c623cfa0.tar.gz
Tango-b462fdd744f491b04137fd99863f6cb6c623cfa0.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/Tango/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/Web/Tango.MachineService')
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/App_Start/WebApiConfig.cs8
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs41
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs55
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Filters/JwtTokenFilter.cs61
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Filters/MachineStudioLoginFilter.cs35
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Filters/PPCLoginFilter.cs35
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs3
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEncoder.cs26
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEntity.cs55
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokensManager.cs37
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj15
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Web.config11
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/packages.config3
13 files changed, 256 insertions, 129 deletions
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/App_Start/WebApiConfig.cs b/Software/Visual_Studio/Web/Tango.MachineService/App_Start/WebApiConfig.cs
index 0a63e9acb..73265328c 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/App_Start/WebApiConfig.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/App_Start/WebApiConfig.cs
@@ -22,10 +22,10 @@ namespace Tango.MachineService
defaults: new { id = RouteParameter.Optional });
config.Formatters.Insert(0, new ProtoBufFormatter());
- config.Formatters.Insert(1, new JsonNetFormatter(new JsonSerializerSettings()
- {
- PreserveReferencesHandling = PreserveReferencesHandling.All,
- }));
+ //config.Formatters.Insert(1, new JsonNetFormatter(new JsonSerializerSettings()
+ //{
+ // PreserveReferencesHandling = PreserveReferencesHandling.All,
+ //}));
}
}
}
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
index 054c8d781..29cc067d6 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/MachineStudioController.cs
@@ -18,18 +18,28 @@ 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
{
- public class MachineStudioController : JsonController
+ public class MachineStudioController : TangoController<MachineStudioController.TokenObject>
{
private static List<MachineStudioPendingUpload> _pendingUploads;
private ActiveDirectoryManager _ad_manager;
- public static TokensManager<String> TokensManager { get; set; }
+ public class TokenObject
+ {
+ public String UserGuid { get; set; }
+ }
+
+ public class RefreshTokenObject
+ {
+ public String Email { get; set; }
+ public String Password { get; set; }
+ }
#region Constructors
@@ -38,8 +48,6 @@ namespace Tango.MachineService.Controllers
/// </summary>
static MachineStudioController()
{
- TokensManager = new TokensManager<string>();
- TokensManager.ExpirationTime = TimeSpan.FromDays(10);
_pendingUploads = new List<MachineStudioPendingUpload>();
}
@@ -61,11 +69,13 @@ namespace Tango.MachineService.Controllers
/// <param name="request">The request.</param>
/// <returns></returns>
[HttpPost]
- [MachineStudioLoginFilter]
+ [JwtTokenFilter]
public CheckForUpdatesResponse CheckForUpdates(CheckForUpdatesRequest request)
{
LogManager.Log("Request received...");
+ var userID = RequestToken.Object.UserGuid;
+
CheckForUpdatesResponse response = new CheckForUpdatesResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
@@ -82,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);
@@ -103,7 +113,7 @@ namespace Tango.MachineService.Controllers
/// <param name="request">The request.</param>
/// <returns></returns>
[HttpPost]
- [MachineStudioLoginFilter]
+ [JwtTokenFilter]
public DownloadLatestVersionResponse DownloadLatestVersion(DownloadLatestVersionRequest request)
{
LogManager.Log("Request received...");
@@ -118,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);
@@ -138,14 +148,14 @@ namespace Tango.MachineService.Controllers
/// <exception cref="System.ArgumentException">New version must be greater than latest version.</exception>
/// <exception cref="AuthenticationException">Invalid user credentials.</exception>
[HttpPost]
- [MachineStudioLoginFilter]
+ [JwtTokenFilter]
public UploadVersionResponse UploadVersion(UploadVersionRequest request)
{
UploadVersionResponse response = new UploadVersionResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
- String userID = TokensManager.GetTokenObject(request.AccessToken);
+ String userID = RequestToken.Object.UserGuid;
var user = new UserBuilder(db).Set(userID).WithRolesAndPermissions().Build();
@@ -158,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);
@@ -195,7 +205,7 @@ namespace Tango.MachineService.Controllers
/// <returns></returns>
/// <exception cref="System.ArgumentException">Invalid Token.</exception>
[HttpPost]
- [MachineStudioLoginFilter]
+ [JwtTokenFilter]
public UploadCompletedResponse NotifyUploadCompleted(UploadCompletedRequest request)
{
MachineStudioPendingUpload upload = _pendingUploads.FirstOrDefault(x => x.Token == request.Token);
@@ -347,7 +357,10 @@ namespace Tango.MachineService.Controllers
Password = request.Password,
},
- WebToken = TokensManager.GetOrCreate(user.Guid),
+ AccessToken = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
+ {
+ UserGuid = user.Guid,
+ }, DateTime.UtcNow.AddDays(1)).AccessToken,
VersionChangeRequired = versionChangeRequired,
RequiredVersion = requiredVersion,
};
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
index ead64fb38..0f36fa040 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
@@ -19,37 +19,30 @@ 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;
+using Tango.BL.DTO;
namespace Tango.MachineService.Controllers
{
- public class PPCController : JsonController
+ public class PPCController : TangoController<PPCController.TokenObject>
{
private static List<PPCPendingUpload> _pendingUploads;
private ActiveDirectoryManager _ad_manager;
- public class TokenObject : IEquatable<TokenObject>
+ public class TokenObject
{
public LoginMode Mode { get; set; }
public String UserGuid { get; set; }
public String MachineGuid { get; set; }
-
- public bool Equals(TokenObject other)
- {
- return UserGuid == other.UserGuid || MachineGuid == MachineGuid;
- }
}
- public static TokensManager<TokenObject> TokensManager { get; set; }
-
#region Constructors
static PPCController()
{
- TokensManager = new TokensManager<TokenObject>();
_pendingUploads = new List<PPCPendingUpload>();
}
@@ -62,8 +55,8 @@ namespace Tango.MachineService.Controllers
#region Setup & Update
- [PPCLoginFilter]
[HttpPost]
+ [JwtTokenFilter]
public MachineSetupResponse MachineSetup(MachineSetupRequest request)
{
MachineSetupResponse response = new MachineSetupResponse();
@@ -73,7 +66,7 @@ namespace Tango.MachineService.Controllers
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
db.Configuration.LazyLoadingEnabled = false;
- String machine_guid = TokensManager.GetTokenObject(request.AccessToken).MachineGuid;
+ String machine_guid = RequestToken.Object.MachineGuid;
var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);
@@ -93,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);
@@ -136,8 +129,8 @@ namespace Tango.MachineService.Controllers
return response;
}
- [PPCLoginFilter]
[HttpPost]
+ [JwtTokenFilter]
public DownloadUpdateResponse MachineUpdate(DownloadUpdateRequest request)
{
DownloadUpdateResponse response = new DownloadUpdateResponse();
@@ -145,7 +138,7 @@ namespace Tango.MachineService.Controllers
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
db.Configuration.LazyLoadingEnabled = false;
- String machine_guid = TokensManager.GetTokenObject(request.AccessToken).MachineGuid;
+ String machine_guid = RequestToken.Object.MachineGuid;
var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);
@@ -160,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);
@@ -195,15 +188,15 @@ namespace Tango.MachineService.Controllers
return response;
}
- [PPCLoginFilter]
[HttpPost]
+ [JwtTokenFilter]
public CheckForUpdateResponse CheckForUpdate(CheckForUpdateRequest request)
{
CheckForUpdateResponse response = new CheckForUpdateResponse();
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
- String machine_guid = TokensManager.GetTokenObject(request.AccessToken).MachineGuid;
+ String machine_guid = RequestToken.Object.MachineGuid;
var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);
@@ -227,8 +220,8 @@ namespace Tango.MachineService.Controllers
return response;
}
- [PPCLoginFilter]
[HttpPost]
+ [JwtTokenFilter]
public UpdateDBResponse UpdateDB(UpdateDBRequest request)
{
UpdateDBResponse response = new UpdateDBResponse();
@@ -236,7 +229,7 @@ namespace Tango.MachineService.Controllers
using (ObservablesContext db = ObservablesContextHelper.CreateContext())
{
- String machine_guid = TokensManager.GetTokenObject(request.AccessToken).MachineGuid;
+ String machine_guid = RequestToken.Object.MachineGuid;
var machine = db.Machines.SingleOrDefault(x => x.Guid == machine_guid);
@@ -301,8 +294,8 @@ namespace Tango.MachineService.Controllers
return response;
}
- [PPCLoginFilter]
[HttpPost]
+ [JwtTokenFilter]
public UploadVersionResponse UploadVersion(UploadVersionRequest request)
{
UploadVersionResponse response = new UploadVersionResponse();
@@ -315,7 +308,7 @@ namespace Tango.MachineService.Controllers
db.UsersRoles.ToList();
db.RolesPermissions.ToList();
- var user_guid = TokensManager.GetTokenObject(request.AccessToken).UserGuid;
+ var user_guid = RequestToken.Object.UserGuid;
var user = new UserBuilder(db).Set(user_guid).WithRolesAndPermissions().Build();
@@ -338,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);
@@ -369,8 +362,8 @@ namespace Tango.MachineService.Controllers
return response;
}
- [PPCLoginFilter]
[HttpPost]
+ [JwtTokenFilter]
public UploadCompletedResponse NotifyUploadCompleted(UploadCompletedRequest request)
{
PPCPendingUpload upload = _pendingUploads.FirstOrDefault(x => x.Token == request.Token);
@@ -408,7 +401,7 @@ namespace Tango.MachineService.Controllers
{
return new MachineVersionsResponse()
{
- MachineVersions = db.MachineVersions.ToList(),
+ MachineVersions = db.MachineVersions.ToList().Select(x => MachineVersionDTO.FromObservable(x)).ToList(),
};
}
}
@@ -439,11 +432,11 @@ namespace Tango.MachineService.Controllers
throw new AuthenticationException("Domain user found but the database entry validation failed.");
}
- response.WebToken = TokensManager.GetOrCreate(new TokenObject()
+ response.AccessToken = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
{
Mode = LoginMode.User,
UserGuid = user.Guid,
- });
+ }).AccessToken;
}
else if (request.Mode == LoginMode.Machine)
{
@@ -454,11 +447,11 @@ namespace Tango.MachineService.Controllers
throw new AuthenticationException("Invalid serial number.");
}
- response.WebToken = TokensManager.GetOrCreate(new TokenObject()
+ response.AccessToken = WebToken<TokenObject>.CreateNew(MachineServiceConfig.JWT_TOKEN_SECRET, new TokenObject()
{
Mode = LoginMode.Machine,
- UserGuid = machine.Guid,
- });
+ MachineGuid = machine.Guid,
+ }).AccessToken;
}
}
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Filters/JwtTokenFilter.cs b/Software/Visual_Studio/Web/Tango.MachineService/Filters/JwtTokenFilter.cs
new file mode 100644
index 000000000..d4b87f1d5
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Filters/JwtTokenFilter.cs
@@ -0,0 +1,61 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Security.Authentication;
+using System.Web;
+using System.Web.Http;
+using System.Web.Http.Controllers;
+using System.Web.Http.Filters;
+using Tango.Transport.Web;
+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;
+
+ if (authorizationHeader != null && authorizationHeader.Parameter != null)
+ {
+ try
+ {
+ WebToken.Validate(MachineServiceConfig.JWT_TOKEN_SECRET, authorizationHeader.Parameter);
+ }
+ catch (JWT.TokenExpiredException)
+ {
+ if (!AllowExpired)
+ {
+ throw new TokenExpiredException("Token expired.");
+ }
+ }
+ catch (JWT.SignatureVerificationException)
+ {
+ throw new InvalidTokenException("Invalid token.");
+ }
+ }
+ else
+ {
+ throw new AuthenticationException("No token specified.");
+ }
+
+ base.OnActionExecuting(actionContext);
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Filters/MachineStudioLoginFilter.cs b/Software/Visual_Studio/Web/Tango.MachineService/Filters/MachineStudioLoginFilter.cs
deleted file mode 100644
index dfa78f0a0..000000000
--- a/Software/Visual_Studio/Web/Tango.MachineService/Filters/MachineStudioLoginFilter.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Security.Authentication;
-using System.Web;
-using System.Web.Http;
-using System.Web.Http.Controllers;
-using System.Web.Http.Filters;
-using Tango.Transport.Web;
-
-namespace Tango.MachineService.Filters
-{
- public class MachineStudioLoginFilter : ActionFilterAttribute
- {
- public override void OnActionExecuting(HttpActionContext actionContext)
- {
- var json = actionContext.Request.Content.ReadAsStringAsync().Result;
- WebRequestSecureMessage msg = JsonConvert.DeserializeObject<WebRequestSecureMessage>(json);
-
- try
- {
- Controllers.MachineStudioController.TokensManager.Validate(msg.AccessToken);
- }
- catch (Exception ex)
- {
- throw new HttpResponseException(actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, ex));
- }
-
- base.OnActionExecuting(actionContext);
- }
- }
-} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Filters/PPCLoginFilter.cs b/Software/Visual_Studio/Web/Tango.MachineService/Filters/PPCLoginFilter.cs
deleted file mode 100644
index 322023b7d..000000000
--- a/Software/Visual_Studio/Web/Tango.MachineService/Filters/PPCLoginFilter.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Security.Authentication;
-using System.Web;
-using System.Web.Http;
-using System.Web.Http.Controllers;
-using System.Web.Http.Filters;
-using Tango.Transport.Web;
-
-namespace Tango.MachineService.Filters
-{
- public class PPCLoginFilter : ActionFilterAttribute
- {
- public override void OnActionExecuting(HttpActionContext actionContext)
- {
- var json = actionContext.Request.Content.ReadAsStringAsync().Result;
- WebRequestSecureMessage msg = JsonConvert.DeserializeObject<WebRequestSecureMessage>(json);
-
- try
- {
- Controllers.PPCController.TokensManager.Validate(msg.AccessToken);
- }
- catch (Exception ex)
- {
- throw new HttpResponseException(actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, ex));
- }
-
- base.OnActionExecuting(actionContext);
- }
- }
-} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs b/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs
index 289fb08e2..0e6d18ddf 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs
@@ -12,5 +12,8 @@ namespace Tango.MachineService
public static String TANGO_VERSIONS_CONTAINER => ConfigurationManager.AppSettings[nameof(TANGO_VERSIONS_CONTAINER)].ToString();
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..896788ffc
--- /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 json = JsonConvert.SerializeObject(obj);
+ Rfc2898Cryptographer crypt = new Rfc2898Cryptographer();
+ return crypt.Encrypt(json);
+ }
+
+ public T Decode(String token)
+ {
+ Rfc2898Cryptographer crypt = new Rfc2898Cryptographer();
+ String json = crypt.Decrypt(token);
+ return JsonConvert.DeserializeObject<T>(json);
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEntity.cs b/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEntity.cs
new file mode 100644
index 000000000..2788799aa
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokenEntity.cs
@@ -0,0 +1,55 @@
+using Microsoft.WindowsAzure.Storage.Table;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.MachineService.Security
+{
+ public class RefreshTokenEntity<T> : TableEntity where T : class
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RefreshTokenEntity"/> class.
+ /// </summary>
+ public RefreshTokenEntity()
+ {
+
+ }
+
+
+ public RefreshTokenEntity(String identity, String accessToken, String refreshToken, DateTime expiration, T obj)
+ {
+ PartitionKey = MachineServiceConfig.REFRESH_TOKENS_TABLE_PARTITION;
+
+ Identity = identity;
+ AccessToken = accessToken;
+ RefreshToken = refreshToken;
+ Expiration = expiration;
+
+ RefreshTokenEncoder<T> encoder = new RefreshTokenEncoder<T>();
+ Object = encoder.Encode(obj);
+ }
+
+ [IgnoreProperty]
+ public String RefreshToken
+ {
+ get { return RowKey; }
+ set { RowKey = value; }
+ }
+
+ public String Identity { get; set; }
+
+ public String AccessToken { get; set; }
+
+ public DateTime Expiration { get; set; }
+
+ public String Object { get; set; }
+
+ public T GetObject()
+ {
+ RefreshTokenEncoder<T> encoder = new RefreshTokenEncoder<T>();
+ return encoder.Decode(RefreshToken);
+ }
+ }
+}
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..06796c41e
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Security/RefreshTokensManager.cs
@@ -0,0 +1,37 @@
+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<T> where T : class
+ {
+ private TableStorageManager _manager;
+
+ public RefreshTokensManager()
+ {
+ _manager = new TableStorageManager();
+ }
+
+ public RefreshTokenEntity<T> GetToken(String refreshToken)
+ {
+ var table = _manager.GetTable(MachineServiceConfig.REFRESH_TOKENS_TABLE_NAME);
+ return table.GetEntity<RefreshTokenEntity<T>>(MachineServiceConfig.REFRESH_TOKENS_TABLE_PARTITION, refreshToken);
+ }
+
+ public RefreshTokenEntity<T> InsertOrUpdate(RefreshTokenEntity<T> refreshTokenEntity)
+ {
+ var table = _manager.GetTable(MachineServiceConfig.REFRESH_TOKENS_TABLE_NAME);
+ return table.InsertOrUpdateEntity(refreshTokenEntity);
+ }
+
+ public void DeleteToken(RefreshTokenEntity<T> entity)
+ {
+ var table = _manager.GetTable(MachineServiceConfig.REFRESH_TOKENS_TABLE_NAME);
+ table.DeleteEntity(entity);
+ }
+ }
+} \ 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 038849c72..bf0c15541 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj
@@ -56,6 +56,9 @@
<Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
+ <Reference Include="JWT, Version=5.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\JWT.5.0.0\lib\net46\JWT.dll</HintPath>
+ </Reference>
<Reference Include="Microsoft.Azure.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<Reference Include="Microsoft.Azure.Common.NetFramework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="Microsoft.Azure.Management.Sql, Version=0.9.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
@@ -161,8 +164,8 @@
<HintPath>..\..\packages\Microsoft.SqlServer.SqlManagementObjects.140.17283.0\lib\net40\Microsoft.SqlServer.WmiEnum.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Storage, Version=4.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
- <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
@@ -275,8 +278,7 @@
</Compile>
<Compile Include="App_Start\BundleConfig.cs" />
<Compile Include="App_Start\FilterConfig.cs" />
- <Compile Include="Filters\MachineStudioLoginFilter.cs" />
- <Compile Include="Filters\PPCLoginFilter.cs" />
+ <Compile Include="Filters\JwtTokenFilter.cs" />
<Compile Include="MachineServiceConfig.cs" />
<Compile Include="Controllers\MachineStudioController.cs" />
<Compile Include="Models\MachineStudioPendingUpload.cs" />
@@ -288,6 +290,9 @@
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Security\RefreshTokenEncoder.cs" />
+ <Compile Include="Security\RefreshTokenEntity.cs" />
+ <Compile Include="Security\RefreshTokensManager.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Global.asax" />
@@ -371,7 +376,7 @@
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>51581</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
- <IISUrl>http://localhost:51581/</IISUrl>
+ <IISUrl>http://localhost:1111/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Web.config b/Software/Visual_Studio/Web/Tango.MachineService/Web.config
index 72c56b38f..d7413de62 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Web.config
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Web.config
@@ -16,16 +16,19 @@
<add key="DB_ADDRESS" value="twine.database.windows.net" />
<add key="DB_USER_NAME" value="Roy" />
<add key="DB_PASSWORD" value="Aa123456" />
- <add key="DB_CATALOG" value="Tango" />
+ <add key="DB_CATALOG" value="Tango_DEV" />
<add key="STORAGE_ACCOUNT" value="DefaultEndpointsProtocol=https;AccountName=tangostorage;AccountKey=S4z/D+Yg6mwMis+bs/VpcDLA9yE1iZaYq23shQlRIi2KmM9E7JY8zdZjeAPOPdG3gONHoNDEpsgH6D4cqQ/bsA==;EndpointSuffix=core.windows.net" />
<add key="TENANT_ID" value="2ebd63a5-bc2f-41dc-9066-4409ed5e5dd4" />
<add key="CLIENT_ID" value="ec612854-7abc-457b-808a-5d0c5ba80c57" />
<add key="APP_SECRET" value="54)019A7wv+#86l*PQcQWYKu%fd4Dv!@G=VhCiDI5rD+H4BTH" />
- <add key="TANGO_VERSIONS_CONTAINER" value="tango-versions" />
- <add key="MACHINE_STUDIO_VERSIONS_CONTAINER" value="machine-studio-versions" />
+ <add key="TANGO_VERSIONS_CONTAINER" value="tango-versions-dev" />
+ <add key="MACHINE_STUDIO_VERSIONS_CONTAINER" value="machine-studio-versions-dev" />
<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="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.
@@ -59,7 +62,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
- <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
+ <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/packages.config b/Software/Visual_Studio/Web/Tango.MachineService/packages.config
index e9f37dbe5..7bc1a3288 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/packages.config
+++ b/Software/Visual_Studio/Web/Tango.MachineService/packages.config
@@ -3,6 +3,7 @@
<package id="Antlr" version="3.4.1.9004" targetFramework="net45" />
<package id="EntityFramework" version="6.2.0" targetFramework="net461" />
<package id="Google.Protobuf" version="3.4.1" targetFramework="net46" />
+ <package id="JWT" version="5.0.0" targetFramework="net461" />
<package id="Microsoft.ApplicationInsights" version="2.2.0" targetFramework="net45" requireReinstallation="true" />
<package id="Microsoft.ApplicationInsights.Agent.Intercept" version="2.0.6" targetFramework="net45" />
<package id="Microsoft.ApplicationInsights.DependencyCollector" version="2.2.0" targetFramework="net45" />
@@ -25,7 +26,7 @@
<package id="Microsoft.SqlServer.SqlManagementObjects" version="140.17283.0" targetFramework="net461" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="Modernizr" version="2.6.2" targetFramework="net45" />
- <package id="Newtonsoft.Json" version="8.0.3" targetFramework="net46" />
+ <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" />
<package id="Respond" version="1.2.0" targetFramework="net45" />
<package id="System.Data.SQLite" version="1.0.108.0" targetFramework="net46" />
<package id="System.Data.SQLite.Core" version="1.0.108.0" targetFramework="net46" />