update pin login service

This commit is contained in:
Luke Pulverenti 2016-02-04 13:03:40 -05:00
parent fa42486e1c
commit e5f80aebd0

View File

@ -11,20 +11,25 @@ namespace MediaBrowser.Api
[Route("/Auth/Pin", "POST", Summary = "Creates a pin request")] [Route("/Auth/Pin", "POST", Summary = "Creates a pin request")]
public class CreatePinRequest : IReturn<PinCreationResult> public class CreatePinRequest : IReturn<PinCreationResult>
{ {
[ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public string DeviceId { get; set; } public string DeviceId { get; set; }
} }
[Route("/Auth/Pin", "GET", Summary = "Gets pin status")] [Route("/Auth/Pin", "GET", Summary = "Gets pin status")]
public class GetPinStatusRequest : IReturn<PinStatusResult> public class GetPinStatusRequest : IReturn<PinStatusResult>
{ {
[ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string DeviceId { get; set; } public string DeviceId { get; set; }
[ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string Pin { get; set; } public string Pin { get; set; }
} }
[Route("/Auth/Pin/Exchange", "POST", Summary = "Exchanges a pin")] [Route("/Auth/Pin/Exchange", "POST", Summary = "Exchanges a pin")]
public class ExchangePinRequest : IReturn<PinExchangeResult> public class ExchangePinRequest : IReturn<PinExchangeResult>
{ {
[ApiMember(Name = "DeviceId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public string DeviceId { get; set; } public string DeviceId { get; set; }
[ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public string Pin { get; set; } public string Pin { get; set; }
} }
@ -32,6 +37,7 @@ namespace MediaBrowser.Api
[Authenticated] [Authenticated]
public class ValidatePinRequest : IReturnVoid public class ValidatePinRequest : IReturnVoid
{ {
[ApiMember(Name = "Pin", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public string Pin { get; set; } public string Pin { get; set; }
} }
@ -41,18 +47,18 @@ namespace MediaBrowser.Api
public object Post(CreatePinRequest request) public object Post(CreatePinRequest request)
{ {
var pin = GetNewPin(5); var pin = GetNewPin();
var key = GetKey(request.DeviceId, pin);
var value = new MyPinStatus var value = new MyPinStatus
{ {
CreationTimeUtc = DateTime.UtcNow, CreationTimeUtc = DateTime.UtcNow,
IsConfirmed = false, IsConfirmed = false,
IsExpired = false, IsExpired = false,
Pin = pin Pin = pin,
DeviceId = request.DeviceId
}; };
_activeRequests.AddOrUpdate(key, value, (k, v) => value); _activeRequests.AddOrUpdate(pin, value, (k, v) => value);
return ToOptimizedResult(new PinCreationResult return ToOptimizedResult(new PinCreationResult
{ {
@ -67,17 +73,12 @@ namespace MediaBrowser.Api
{ {
MyPinStatus status; MyPinStatus status;
if (!_activeRequests.TryGetValue(GetKey(request.DeviceId, request.Pin), out status)) if (!_activeRequests.TryGetValue(request.Pin, out status))
{ {
throw new ResourceNotFoundException(); throw new ResourceNotFoundException();
} }
CheckExpired(status); EnsureValid(request.DeviceId, status);
if (status.IsExpired)
{
throw new ResourceNotFoundException();
}
return ToOptimizedResult(new PinStatusResult return ToOptimizedResult(new PinStatusResult
{ {
@ -91,37 +92,78 @@ namespace MediaBrowser.Api
{ {
MyPinStatus status; MyPinStatus status;
if (!_activeRequests.TryGetValue(GetKey(request.DeviceId, request.Pin), out status)) if (!_activeRequests.TryGetValue(request.Pin, out status))
{ {
throw new ResourceNotFoundException(); throw new ResourceNotFoundException();
} }
CheckExpired(status); EnsureValid(request.DeviceId, status);
if (status.IsExpired) if (!status.IsConfirmed)
{ {
throw new ResourceNotFoundException(); throw new ResourceNotFoundException();
} }
return ToOptimizedResult(new PinExchangeResult return ToOptimizedResult(new PinExchangeResult
{ {
// TODO: Add access token
UserId = status.UserId
}); });
} }
public void Post(ValidatePinRequest request) public void Post(ValidatePinRequest request)
{ {
MyPinStatus status;
if (!_activeRequests.TryGetValue(request.Pin, out status))
{
throw new ResourceNotFoundException();
} }
private void CheckExpired(MyPinStatus status) EnsureValid(status);
status.IsConfirmed = true;
status.UserId = AuthorizationContext.GetAuthorizationInfo(Request).UserId;
}
private void EnsureValid(string requestedDeviceId, MyPinStatus status)
{
if (!string.Equals(requestedDeviceId, status.DeviceId, StringComparison.OrdinalIgnoreCase))
{
throw new ResourceNotFoundException();
}
EnsureValid(status);
}
private void EnsureValid(MyPinStatus status)
{ {
if ((DateTime.UtcNow - status.CreationTimeUtc).TotalMinutes > 10) if ((DateTime.UtcNow - status.CreationTimeUtc).TotalMinutes > 10)
{ {
status.IsExpired = true; status.IsExpired = true;
} }
if (status.IsExpired)
{
throw new ResourceNotFoundException();
}
} }
private string GetNewPin(int length) private string GetNewPin()
{ {
var pin = GetNewPinInternal();
while (IsPinActive(pin))
{
pin = GetNewPinInternal();
}
return pin;
}
private string GetNewPinInternal()
{
var length = 5;
var pin = string.Empty; var pin = string.Empty;
while (pin.Length < length) while (pin.Length < length)
@ -133,14 +175,28 @@ namespace MediaBrowser.Api
return pin; return pin;
} }
private string GetKey(string deviceId, string pin) private bool IsPinActive(string pin)
{ {
return deviceId + pin; MyPinStatus status;
if (!_activeRequests.TryGetValue(pin, out status))
{
return true;
}
if (status.IsExpired)
{
return true;
}
return false;
} }
public class MyPinStatus : PinStatusResult public class MyPinStatus : PinStatusResult
{ {
public DateTime CreationTimeUtc { get; set; } public DateTime CreationTimeUtc { get; set; }
public string DeviceId { get; set; }
public string UserId { get; set; }
} }
} }
} }