public async Task VerifyTokenTest() { var app = new AuthorizedAppConfig { PackageName = "com.xamarin.exposurenotification.sampleapp", Platform = "android", }; var nonce = submission.GetAndroidNonce(); var verified = await AndroidVerify.VerifyToken(actualSubmission.DeviceVerificationPayload, nonce, DateTimeOffset.UtcNow, app); Assert.True(verified); }
public async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "selfdiagnosis")] HttpRequest req, ILogger log) { var requestBody = await new StreamReader(req.Body).ReadToEndAsync(); if (req.Method.Equals("put", StringComparison.OrdinalIgnoreCase)) { var diagnosis = JsonConvert.DeserializeObject <SelfDiagnosisSubmission>(requestBody); // Verification may be disabled for testing if (!settings.Value.DisableDeviceVerification) { var platform = AuthorizedAppConfig.ParsePlatform(diagnosis.Platform); var authApp = storage.GetAuthorizedApp(platform); // Verify the device payload (safetynet attestation on android, or device check token on iOS) if (!await Verify.VerifyDevice(diagnosis, DateTimeOffset.UtcNow, platform, authApp)) { log.LogInformation($"Device Failed {platform} Attestation/Verification, returning OK"); // The suggestion from Apple/Google is to return OK here to prevent abuse return(new OkResult()); } } if (!diagnosis.Validate()) { log.LogInformation("Invalid Submission Key data - Validate() failed"); return(new OkResult()); } try { await storage.SubmitPositiveDiagnosisAsync(diagnosis); } catch (InvalidOperationException) { log.LogInformation("Maximum keys for VerificationPayload reached, skipping key submission..."); } } return(new OkResult()); }
public static Task <bool> VerifyDevice(SelfDiagnosisSubmission submission, DateTimeOffset requestTime, AuthorizedAppConfig.DevicePlatform platform, AuthorizedAppConfig auth) => platform switch {
public static async Task <bool> VerifyToken(string token, byte[] expectedNonce, DateTimeOffset requestTime, AuthorizedAppConfig app) { var claims = ParsePayload(token); // Validate the nonce if (Convert.ToBase64String(claims.Nonce) != Convert.ToBase64String(expectedNonce)) { return(false); } // Validate time interval var now = requestTime.ToUnixTimeMilliseconds(); if (app.SafetyNetPastTimeSeconds > 0) { var minTime = now - (app.SafetyNetPastTimeSeconds * 1000); if (claims.TimestampMilliseconds < minTime) { return(false); } } if (app.SafetyNetFutureTimeSeconds > 0) { var minTime = now + (app.SafetyNetFutureTimeSeconds * 1000); if (claims.TimestampMilliseconds > minTime) { return(false); } } // Validate certificate if (app.SafetyNetApkDigestSha256?.Length > 0) { var apkSha = Convert.ToBase64String(claims.ApkCertificateDigestSha256); if (!app.SafetyNetApkDigestSha256.Contains(apkSha)) { return(false); } } // Validate integrity if (app.SafetyNetCtsProfileMatch) { if (!claims.CtsProfileMatch) { return(false); } } if (app.SafetyNetBasicIntegrity) { if (!claims.BasicIntegrity) { return(false); } } return(true); }
public static async Task <bool> VerifyToken(string token, DateTimeOffset requestTime, AuthorizedAppConfig app) { var http = new HttpClient(); var timestamp = requestTime.ToUnixTimeMilliseconds(); var id = Guid.NewGuid().ToString(); var json = new JObject(); json["device_token"] = token; json["timestamp"] = timestamp; json["transaction_id"] = id; var str = json.ToString(); Console.WriteLine(str); //var json = "{\"device_token\":\"" + token + "\",\"transaction_id\":\"" + id + "\",\"timestamp\":" + timestamp + "}"; var jwt = GenerateClientSecretJWT(requestTime, app.DeviceCheckKeyId, app.DeviceCheckTeamId, app.DeviceCheckPrivateKey); var req = new HttpRequestMessage(HttpMethod.Post, appleDeviceCheckUrl); req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", jwt); req.Content = new StringContent(str); var response = await http.SendAsync(req); if (response.StatusCode != System.Net.HttpStatusCode.OK) { return(false); } return(true); }