Skip to content

Instantly share code, notes, and snippets.

@schirrmacher
Last active May 27, 2021 13:17
Show Gist options
  • Save schirrmacher/ab597e62953eef9f635c576d389fe4e2 to your computer and use it in GitHub Desktop.
Save schirrmacher/ab597e62953eef9f635c576d389fe4e2 to your computer and use it in GitHub Desktop.
Backend Implementation of Apple's DeviceCheck and Google's SafetyNet Attestation API
import BaseService from "./BaseService";
import BaseCoordinator from "./BaseCoordinator";
import { DeviceCheckParams, DeviceCheckService } from "./DeviceCheckService";
import { GoogleSafetyNetAttestationService } from "./GoogleSafetyNetAttestationService";
import { AppleDeviceCheckService } from "./AppleDeviceCheckService";
import * as UserAgentParser from "../helper/UserAgentParser";
export default class DeviceCheckCoordinator extends BaseCoordinator {
private loggingTag = "DeviceAuthenticityCheck";
public async shouldProceed(userAgent: string, token: string | undefined, timestamp: number, binding: string): Promise<boolean> {
if (!token) {
this.logger.warn(`${this.loggingTag}: ${userAgent}: no token given`);
return false;
}
let deviceCheckService: BaseService & DeviceCheckService | undefined;
const deviceCheckParams: DeviceCheckParams = {
timestamp,
token,
binding,
};
if (UserAgentParser.os(userAgent) === "iOS") {
deviceCheckService = new AppleDeviceCheckService();
} else if (UserAgentParser.os(userAgent) === "Android") {
deviceCheckService = new GoogleSafetyNetAttestationService();
} else {
this.logger.warn(`${this.loggingTag}: ${userAgent}: invalid user agent`);
// cannot be the case for valid clients => do not proceed
return false;
}
if (deviceCheckService && deviceCheckParams) {
try {
const isDeviceAllowedToProceed = await deviceCheckService.shouldProceed(deviceCheckParams);
if (isDeviceAllowedToProceed) {
this.logger.info(`${this.loggingTag}: ${userAgent}: device authenticated`);
return true;
} else {
this.logger.warn(`${this.loggingTag}: ${userAgent}: suspicious behavior detected`);
return false;
}
} catch (error) {
this.logger.error(`${this.loggingTag}: ${userAgent}: device check skipped due to error: ${error}`);
// external errors force us to skip check => proceed
// otherwise Apple/Google failures can block our services
return true;
}
}
return false;
}
}
@mjroeleveld
Copy link

Where is AppleDeviceCheckService? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment