private async Task DiscoverDevice() { var authStageInfo = await SecondaryAuthenticationFactorAuthentication.GetAuthenticationStageInfoAsync(); if (authStageInfo.Stage != SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential) { return; // Bad status! } findAuth = true; var deviceList = await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(SecondaryAuthenticationFactorDeviceFindScope.User); var db = new DatabaseContext(); var devicesInDb = db.Devices.ToList(); db.Dispose(); IPDiscover.DiscoverIP(); foreach (var device in deviceList) { var deviceInDb = devicesInDb.Find(d => d.DeviceId.ToString() == device.DeviceId); if (deviceInDb == null) { continue; } var session = new DeviceAuthSession { LastIP = deviceInDb.LastConnectedHost, MACAddress = deviceInDb.DeviceMacAddress, DeviceID = device.DeviceId, DeviceInDb = deviceInDb }; deviceSessions.Add(session); } while (findAuth) { foreach (var session in deviceSessions) { switch (session.Status) { case DeviceStatus.NotConnected: var payload = Convert.ToBase64String(Encoding.UTF8.GetBytes(session.DeviceID)); var data = Encoding.UTF8.GetBytes(DeviceDiscoverPrefix + payload); if (!string.IsNullOrWhiteSpace(session.LastIP)) { try { UDPListener.Send(session.LastIP, data); } catch (Exception) { // ignored } } var ips = session.FindIPs()?.ToList(); if ((ips == null || !ips.Any()) && string.IsNullOrWhiteSpace(session.MACAddress) && IPDiscover.IsDiscoveryCompleted) { session.Status = DeviceStatus.Unreachable; continue; } if (ips != null) { foreach (var ip in ips) { try { UDPListener.Send(ip, data); } catch (Exception) { // ignored } } } await UDPListener.Send(UDPListener.DeviceMulticastGroupAddress, data); break; case DeviceStatus.Unreachable: deviceSessions.Remove(session); break; case DeviceStatus.Established: findAuth = false; break; } } Thread.Sleep(1000); } Auth(deviceSessions.FirstOrDefault(s => s.Status == DeviceStatus.Established)); CurrentSession = null; }
private async void Auth(DeviceAuthSession session) { if (session == null) { await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync("", SecondaryAuthenticationFactorAuthenticationMessage.Invalid); return; } var deviceInDb = session.DeviceInDb; await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(deviceInDb.DeviceFriendlyName, SecondaryAuthenticationFactorAuthenticationMessage.ReadyToSignIn); IBuffer svcAuthNonce = CryptographicBuffer.GenerateRandom(256 / 8); SecondaryAuthenticationFactorAuthenticationResult authResult = await SecondaryAuthenticationFactorAuthentication.StartAuthenticationAsync( session.DeviceID, svcAuthNonce); if (authResult.Status != SecondaryAuthenticationFactorAuthenticationStatus.Started) { var message = SecondaryAuthenticationFactorAuthenticationMessage.Invalid; switch (authResult.Status) { case SecondaryAuthenticationFactorAuthenticationStatus.DisabledByPolicy: message = SecondaryAuthenticationFactorAuthenticationMessage.DisabledByPolicy; break; case SecondaryAuthenticationFactorAuthenticationStatus.InvalidAuthenticationStage: break; default: return; } await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(null, message); return; } var auth = authResult.Authentication; CurrentSession = session; for (int retries = 0; retries < 3; retries++) { var svcAuthHmac = auth.ServiceAuthenticationHmac; var deviceNonce = auth.DeviceNonce; var sessionNonce = auth.SessionNonce; var arr = new byte[3 + svcAuthHmac.Length + deviceNonce.Length + sessionNonce.Length]; arr[0] = (byte)svcAuthHmac.Length; arr[1] = (byte)deviceNonce.Length; arr[2] = (byte)sessionNonce.Length; Array.Copy(svcAuthHmac.ToArray(), 0, arr, 3, svcAuthHmac.Length); Array.Copy(deviceNonce.ToArray(), 0, arr, 3 + svcAuthHmac.Length, deviceNonce.Length); Array.Copy(sessionNonce.ToArray(), 0, arr, 3 + svcAuthHmac.Length + deviceNonce.Length, sessionNonce.Length); var payload = Convert.ToBase64String(arr); UDPListener.Send(session.LastIP, Encoding.UTF8.GetBytes(DeviceDiscoverPrefix + payload)); AuthResultReceivedEvent = new ManualResetEvent(false); try { AuthResultReceivedEvent.WaitOne(20000); } catch (Exception) { // ignored } var result = session.ResultBytes; if (result == null || result.Length <= 2 || result.Length != 2 + result[0] + result[1]) { return; /*await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync("", * SecondaryAuthenticationFactorAuthenticationMessage.TryAgain); * await auth.AbortAuthenticationAsync("No data got."); * continue;*/ } var deviceHmac = new Buffer(result[0]); var sessionHmac = new Buffer(result[1]); result.CopyTo(2, deviceHmac, 0, result[0]); result.CopyTo(2 + result[0], sessionHmac, 0, result[1]); var status = await auth.FinishAuthenticationAsync(deviceHmac, sessionHmac); switch (status) { case SecondaryAuthenticationFactorFinishAuthenticationStatus.Completed: // The credential data is collected and ready for unlock CurrentSession = null; return; default: await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync("", SecondaryAuthenticationFactorAuthenticationMessage.TryAgain); break; } } await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(deviceInDb.DeviceFriendlyName, SecondaryAuthenticationFactorAuthenticationMessage.UnauthorizedUser); CurrentSession = null; }