diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj
index 2200ce290..681d232d3 100644
--- a/src/Android/Android.csproj
+++ b/src/Android/Android.csproj
@@ -123,6 +123,14 @@
..\..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll
True
+
+ ..\..\packages\Xam.Plugin.DeviceInfo.2.0.2\lib\MonoAndroid10\Plugin.DeviceInfo.dll
+ True
+
+
+ ..\..\packages\Xam.Plugin.DeviceInfo.2.0.2\lib\MonoAndroid10\Plugin.DeviceInfo.Abstractions.dll
+ True
+
..\..\packages\Plugin.Fingerprint.1.1.1-beta\lib\MonoAndroid\Plugin.Fingerprint.dll
True
diff --git a/src/Android/MainApplication.cs b/src/Android/MainApplication.cs
index 49d34b55f..42b7bfae2 100644
--- a/src/Android/MainApplication.cs
+++ b/src/Android/MainApplication.cs
@@ -11,6 +11,7 @@ using Bit.App.Services;
using Microsoft.Practices.Unity;
using Plugin.Connectivity;
using Plugin.CurrentActivity;
+using Plugin.DeviceInfo;
using Plugin.Fingerprint;
using Plugin.Settings;
using PushNotification.Plugin;
@@ -119,6 +120,7 @@ namespace Bit.Android
.RegisterType(new ContainerControlledLifetimeManager())
.RegisterType(new ContainerControlledLifetimeManager())
.RegisterType(new ContainerControlledLifetimeManager())
+ .RegisterType(new ContainerControlledLifetimeManager())
// Repositories
.RegisterType(new ContainerControlledLifetimeManager())
.RegisterType(new ContainerControlledLifetimeManager())
@@ -127,12 +129,13 @@ namespace Bit.Android
.RegisterType(new ContainerControlledLifetimeManager())
.RegisterType(new ContainerControlledLifetimeManager())
// Other
+ .RegisterInstance(CrossDeviceInfo.Current, new ContainerControlledLifetimeManager())
.RegisterInstance(CrossSettings.Current, new ContainerControlledLifetimeManager())
.RegisterInstance(CrossConnectivity.Current, new ContainerControlledLifetimeManager())
.RegisterInstance(UserDialogs.Instance, new ContainerControlledLifetimeManager())
.RegisterInstance(CrossFingerprint.Current, new ContainerControlledLifetimeManager());
- CrossPushNotification.Initialize(container.Resolve(), "SENDERID");
+ CrossPushNotification.Initialize(container.Resolve(), "SECRET_SENDER_ID");
container.RegisterInstance(CrossPushNotification.Current, new ContainerControlledLifetimeManager());
Resolver.SetResolver(new UnityResolver(container));
diff --git a/src/Android/packages.config b/src/Android/packages.config
index 55fc40f36..bbc0a2ce0 100644
--- a/src/Android/packages.config
+++ b/src/Android/packages.config
@@ -11,6 +11,7 @@
+
diff --git a/src/App/Abstractions/Repositories/IDeviceApiRepository.cs b/src/App/Abstractions/Repositories/IDeviceApiRepository.cs
index 962362c3e..8f0874d5a 100644
--- a/src/App/Abstractions/Repositories/IDeviceApiRepository.cs
+++ b/src/App/Abstractions/Repositories/IDeviceApiRepository.cs
@@ -2,9 +2,12 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Models.Api;
+using Bit.App.Repositories;
namespace Bit.App.Abstractions
{
public interface IDeviceApiRepository : IApiRepository
- { }
+ {
+ Task> PutTokenAsync(string identifier, DeviceTokenRequest request);
+ }
}
\ No newline at end of file
diff --git a/src/App/Abstractions/Services/IAppIdService.cs b/src/App/Abstractions/Services/IAppIdService.cs
new file mode 100644
index 000000000..1ea728037
--- /dev/null
+++ b/src/App/Abstractions/Services/IAppIdService.cs
@@ -0,0 +1,7 @@
+namespace Bit.App.Abstractions
+{
+ public interface IAppIdService
+ {
+ string AppId { get; }
+ }
+}
diff --git a/src/App/App.csproj b/src/App/App.csproj
index 5e6f37d38..d6b55ac64 100644
--- a/src/App/App.csproj
+++ b/src/App/App.csproj
@@ -36,6 +36,8 @@
+
+
@@ -65,6 +67,7 @@
+
@@ -117,10 +120,10 @@
True
AppResources.resx
+
-
@@ -140,7 +143,9 @@
-
+
+ Designer
+
@@ -179,6 +184,14 @@
..\..\packages\Xam.Plugin.Connectivity.2.1.2\lib\portable-net45+wp80+wp81+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+Xamarin.Mac20+UAP10\Plugin.Connectivity.Abstractions.dll
True
+
+ ..\..\packages\Xam.Plugin.DeviceInfo.2.0.2\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\Plugin.DeviceInfo.dll
+ True
+
+
+ ..\..\packages\Xam.Plugin.DeviceInfo.2.0.2\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\Plugin.DeviceInfo.Abstractions.dll
+ True
+
..\..\packages\Plugin.Fingerprint.1.1.1-beta\lib\portable-net45+win8+wpa81+wp8\Plugin.Fingerprint.dll
True
diff --git a/src/App/Models/Api/Request/DeviceRequest.cs b/src/App/Models/Api/Request/DeviceRequest.cs
index 2797d274f..929ac37ea 100644
--- a/src/App/Models/Api/Request/DeviceRequest.cs
+++ b/src/App/Models/Api/Request/DeviceRequest.cs
@@ -1,11 +1,23 @@
-using PushNotification.Plugin.Abstractions;
+using Bit.App.Abstractions;
+using Plugin.DeviceInfo.Abstractions;
+using PushNotification.Plugin.Abstractions;
namespace Bit.App.Models.Api
{
public class DeviceRequest
{
+ public DeviceRequest() { }
+
+ public DeviceRequest(IAppIdService appIdService, IDeviceInfo deviceInfo)
+ {
+ Identifier = appIdService.AppId;
+ Name = deviceInfo.Model;
+ Type = deviceInfo.Platform == Platform.Android ? DeviceType.Android : DeviceType.iOS;
+ }
+
public DeviceType Type { get; set; }
public string Name { get; set; }
+ public string Identifier { get; set; }
public string PushToken { get; set; }
}
}
diff --git a/src/App/Models/Api/Request/DeviceTokenRequest.cs b/src/App/Models/Api/Request/DeviceTokenRequest.cs
new file mode 100644
index 000000000..e9b584341
--- /dev/null
+++ b/src/App/Models/Api/Request/DeviceTokenRequest.cs
@@ -0,0 +1,12 @@
+namespace Bit.App.Models.Api
+{
+ public class DeviceTokenRequest
+ {
+ public DeviceTokenRequest(string token)
+ {
+ PushToken = token;
+ }
+
+ public string PushToken { get; set; }
+ }
+}
diff --git a/src/App/Models/Api/Request/TokenRequest.cs b/src/App/Models/Api/Request/TokenRequest.cs
index 5cfba970d..260835e17 100644
--- a/src/App/Models/Api/Request/TokenRequest.cs
+++ b/src/App/Models/Api/Request/TokenRequest.cs
@@ -4,5 +4,6 @@
{
public string Email { get; set; }
public string MasterPasswordHash { get; set; }
+ public DeviceRequest Device { get; set; }
}
}
diff --git a/src/App/Models/Api/Response/DeviceResponse.cs b/src/App/Models/Api/Response/DeviceResponse.cs
index 10fc40802..9cb1483a3 100644
--- a/src/App/Models/Api/Response/DeviceResponse.cs
+++ b/src/App/Models/Api/Response/DeviceResponse.cs
@@ -7,6 +7,7 @@ namespace Bit.App.Models.Api
{
public string Id { get; set; }
public string Name { get; set; }
+ public string Identifier { get; set; }
public DeviceType Type { get; set; }
public DateTime CreationDate { get; set; }
}
diff --git a/src/App/Pages/LoginPage.cs b/src/App/Pages/LoginPage.cs
index 62534de0c..110ae7b89 100644
--- a/src/App/Pages/LoginPage.cs
+++ b/src/App/Pages/LoginPage.cs
@@ -7,6 +7,7 @@ using Bit.App.Abstractions;
using Bit.App.Behaviors;
using Bit.App.Models.Api;
using Bit.App.Resources;
+using Plugin.DeviceInfo.Abstractions;
using Xamarin.Forms;
using XLabs.Ioc;
@@ -18,6 +19,8 @@ namespace Bit.App.Pages
{
var cryptoService = Resolver.Resolve();
var authService = Resolver.Resolve();
+ var deviceInfo = Resolver.Resolve();
+ var appIdService = Resolver.Resolve();
var emailEntry = new Entry
{
@@ -58,13 +61,14 @@ namespace Bit.App.Pages
var request = new TokenRequest
{
Email = emailEntry.Text,
- MasterPasswordHash = cryptoService.HashPasswordBase64(key, masterPasswordEntry.Text)
+ MasterPasswordHash = cryptoService.HashPasswordBase64(key, masterPasswordEntry.Text),
+ Device = new DeviceRequest(appIdService, deviceInfo)
};
var response = await authService.TokenPostAsync(request);
if(!response.Succeeded)
{
- await DisplayAlert(AppResources.AnErrorHasOccurred, response.Errors.First().Message, AppResources.Ok);
+ await DisplayAlert(AppResources.AnErrorHasOccurred, response.Errors.FirstOrDefault()?.Message, AppResources.Ok);
return;
}
diff --git a/src/App/Repositories/DeviceApiRepository.cs b/src/App/Repositories/DeviceApiRepository.cs
index 1a0a0a78a..c08c7b54f 100644
--- a/src/App/Repositories/DeviceApiRepository.cs
+++ b/src/App/Repositories/DeviceApiRepository.cs
@@ -1,11 +1,33 @@
using System;
+using System.Net.Http;
+using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Models.Api;
+using Newtonsoft.Json;
namespace Bit.App.Repositories
{
public class DeviceApiRepository : ApiRepository, IDeviceApiRepository
{
protected override string ApiRoute => "devices";
+
+ public virtual async Task> PutTokenAsync(string identifier, DeviceTokenRequest request)
+ {
+ var requestMessage = new TokenHttpRequestMessage(request)
+ {
+ Method = HttpMethod.Put,
+ RequestUri = new Uri(Client.BaseAddress, string.Concat(ApiRoute, "/identifier/", identifier, "/token")),
+ };
+
+ var response = await Client.SendAsync(requestMessage);
+ if(!response.IsSuccessStatusCode)
+ {
+ return await HandleErrorAsync(response);
+ }
+
+ var responseContent = await response.Content.ReadAsStringAsync();
+ var responseObj = JsonConvert.DeserializeObject(responseContent);
+ return ApiResult.Success(responseObj, response.StatusCode);
+ }
}
}
diff --git a/src/App/Services/AppIdService.cs b/src/App/Services/AppIdService.cs
new file mode 100644
index 000000000..16f589a62
--- /dev/null
+++ b/src/App/Services/AppIdService.cs
@@ -0,0 +1,39 @@
+using System;
+using Bit.App.Abstractions;
+using Plugin.Settings.Abstractions;
+
+namespace Bit.App.Services
+{
+ public class AppIdService : IAppIdService
+ {
+ private const string AppIdKey = "appId";
+ private readonly ISettings _settings;
+ private string _appId;
+
+ public AppIdService(ISettings settings)
+ {
+ _settings = settings;
+ }
+
+ public string AppId
+ {
+ get
+ {
+ if(!string.IsNullOrWhiteSpace(_appId))
+ {
+ return _appId;
+ }
+
+ _appId = _settings.GetValueOrDefault(AppIdKey);
+ if(!string.IsNullOrWhiteSpace(_appId))
+ {
+ return _appId;
+ }
+
+ _appId = Guid.NewGuid().ToString();
+ _settings.AddOrUpdateValue(AppIdKey, _appId);
+ return _appId;
+ }
+ }
+ }
+}
diff --git a/src/App/Services/PushNotificationListener.cs b/src/App/Services/PushNotificationListener.cs
index d0a2b74f2..89df5402e 100644
--- a/src/App/Services/PushNotificationListener.cs
+++ b/src/App/Services/PushNotificationListener.cs
@@ -9,6 +9,8 @@ using PushNotification.Plugin;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Bit.App.Abstractions;
+using Xamarin.Forms;
+using Plugin.DeviceInfo.Abstractions;
namespace Bit.App.Services
{
@@ -18,15 +20,18 @@ namespace Bit.App.Services
private readonly ISyncService _syncService;
private readonly IDeviceApiRepository _deviceApiRepository;
private readonly IAuthService _authService;
+ private readonly IAppIdService _appIdService;
public PushNotificationListener(
ISyncService syncService,
IDeviceApiRepository deviceApiRepository,
- IAuthService authService)
+ IAuthService authService,
+ IAppIdService appIdService)
{
_syncService = syncService;
_deviceApiRepository = deviceApiRepository;
_authService = authService;
+ _appIdService = appIdService;
}
public void OnMessage(JObject values, DeviceType deviceType)
@@ -44,13 +49,8 @@ namespace Bit.App.Services
return;
}
- var response = _deviceApiRepository.PostAsync(new Models.Api.DeviceRequest
- {
- Name = deviceType.ToString(),
- Type = deviceType,
- PushToken = token
- }).GetAwaiter().GetResult();
-
+ var response = _deviceApiRepository.PutTokenAsync(_appIdService.AppId, new Models.Api.DeviceTokenRequest(token))
+ .GetAwaiter().GetResult();
if(response.Succeeded)
{
Debug.WriteLine("Registered device with server.");
diff --git a/src/App/packages.config b/src/App/packages.config
index 8081ede0a..4df604a0b 100644
--- a/src/App/packages.config
+++ b/src/App/packages.config
@@ -11,6 +11,7 @@
+
diff --git a/src/iOS/AppDelegate.cs b/src/iOS/AppDelegate.cs
index 25a157db2..10e70d00f 100644
--- a/src/iOS/AppDelegate.cs
+++ b/src/iOS/AppDelegate.cs
@@ -22,6 +22,7 @@ using Xamarin.Forms;
using Bit.App;
using Bit.iOS.Core.Services;
using PushNotification.Plugin;
+using Plugin.DeviceInfo;
namespace Bit.iOS
{
@@ -187,6 +188,7 @@ namespace Bit.iOS
.RegisterType(new ContainerControlledLifetimeManager())
.RegisterType(new ContainerControlledLifetimeManager())
.RegisterType(new ContainerControlledLifetimeManager())
+ .RegisterType(new ContainerControlledLifetimeManager())
// Repositories
.RegisterType(new ContainerControlledLifetimeManager())
.RegisterType(new ContainerControlledLifetimeManager())
@@ -195,6 +197,7 @@ namespace Bit.iOS
.RegisterType(new ContainerControlledLifetimeManager())
.RegisterType(new ContainerControlledLifetimeManager())
// Other
+ .RegisterInstance(CrossDeviceInfo.Current, new ContainerControlledLifetimeManager())
.RegisterInstance(CrossSettings.Current, new ContainerControlledLifetimeManager())
.RegisterInstance(CrossConnectivity.Current, new ContainerControlledLifetimeManager())
.RegisterInstance(UserDialogs.Instance, new ContainerControlledLifetimeManager())
diff --git a/src/iOS/iOS.csproj b/src/iOS/iOS.csproj
index b71aaa1b4..90107f2c6 100644
--- a/src/iOS/iOS.csproj
+++ b/src/iOS/iOS.csproj
@@ -180,6 +180,14 @@
..\..\packages\Xam.Plugin.Connectivity.2.1.2\lib\Xamarin.iOS10\Plugin.Connectivity.Abstractions.dll
True
+
+ ..\..\packages\Xam.Plugin.DeviceInfo.2.0.2\lib\Xamarin.iOS10\Plugin.DeviceInfo.dll
+ True
+
+
+ ..\..\packages\Xam.Plugin.DeviceInfo.2.0.2\lib\Xamarin.iOS10\Plugin.DeviceInfo.Abstractions.dll
+ True
+
..\..\packages\Plugin.Fingerprint.1.1.1-beta\lib\Xamarin.iOS10\Plugin.Fingerprint.dll
True
diff --git a/src/iOS/packages.config b/src/iOS/packages.config
index f2ab43c98..0f8f94da6 100644
--- a/src/iOS/packages.config
+++ b/src/iOS/packages.config
@@ -11,6 +11,7 @@
+