All Projects → veehaitch → devicecheck-appattest

veehaitch / devicecheck-appattest

Licence: Apache-2.0 license
Server-side library to validate the authenticity of Apple App Attest artifacts, written in Kotlin.

Programming Languages

kotlin
9241 projects

Projects that are alternatives of or similar to devicecheck-appattest

adfsmfa
MFA for ADFS 2022/2019/2016/2012r2
Stars: ✭ 86 (+91.11%)
Mutual labels:  webauthn
webauthn-example
Basic WebAuthn client and server in go
Stars: ✭ 53 (+17.78%)
Mutual labels:  webauthn
confidential-computing-zoo
Confidential Computing Zoo provides confidential computing solutions based on Intel SGX, TDX, HEXL, etc. technologies.
Stars: ✭ 177 (+293.33%)
Mutual labels:  attestation
SimpleWebAuthn
WebAuthn, Simplified. A collection of TypeScript-first libraries for simpler WebAuthn integration. Supports modern browsers and Node.
Stars: ✭ 206 (+357.78%)
Mutual labels:  webauthn
passwordless
Passwordless authentication server, supports OTP, WebAuthn, plan to implement TOTP and mobile biometric authentication
Stars: ✭ 34 (-24.44%)
Mutual labels:  webauthn
u2f-php
FIDO/FIDO2 Universal 2 Factors (U2F) support for PHP
Stars: ✭ 25 (-44.44%)
Mutual labels:  webauthn
keycloak-radius-plugin
Make the radius server as part of keycloak SSO
Stars: ✭ 102 (+126.67%)
Mutual labels:  webauthn
LightVerifier
Simple and scalable Linux tools for verifying TPM-based remote attestations 🔬⚖️🔐⛓📏📜
Stars: ✭ 18 (-60%)
Mutual labels:  attestation
awesome-yubikey
Curated list of awesome Yubikey resources, open source projects, tools and tutorials.
Stars: ✭ 22 (-51.11%)
Mutual labels:  webauthn
AttestationSamples
A small subset of the submitted sample data from https://github.com/GrapheneOS/Auditor. It has a sample attestation certificate chain per device model (ro.product.model) along with a subset of the system properties from the sample as supplementary information.
Stars: ✭ 25 (-44.44%)
Mutual labels:  attestation
a12n-server
A ready-to-launch User and Authentication system for those that don't want to build it
Stars: ✭ 324 (+620%)
Mutual labels:  webauthn
secure-payment-confirmation
Explainer for Secure Payment Confirmation
Stars: ✭ 64 (+42.22%)
Mutual labels:  webauthn
Solo
Solo 1: open security key supporting FIDO2 & U2F over USB + NFC
Stars: ✭ 1,986 (+4313.33%)
Mutual labels:  webauthn
line-fido2-server
FIDO2(WebAuthn) server officially certified by FIDO Alliance and Relying Party examples.
Stars: ✭ 350 (+677.78%)
Mutual labels:  webauthn
SecuritySample
(Android) Hide encrypted secret API keys in C/C++ code, retrieve and decrypt them via JNI. Google SafetyNet APIs example.
Stars: ✭ 49 (+8.89%)
Mutual labels:  attestation
kagi
WebAuthn security keys and TOTP multi-factor authentication for Django
Stars: ✭ 17 (-62.22%)
Mutual labels:  webauthn
webauthn-demo
WebAuthn demo with Ionic/Angular and Spring Boot
Stars: ✭ 22 (-51.11%)
Mutual labels:  webauthn
uru-card
Arduino based firmware for FIDO2 Authenticator
Stars: ✭ 114 (+153.33%)
Mutual labels:  webauthn
AttestationServer
Server code for use with the Auditor app: https://github.com/GrapheneOS/Auditor. It provides two services: submission of attestation data samples and a remote attestation implementation with email alerts to go along with the local implementation based on QR code scanning in the app.
Stars: ✭ 64 (+42.22%)
Mutual labels:  attestation
Opensk
OpenSK is an open-source implementation for security keys written in Rust that supports both FIDO U2F and FIDO2 standards.
Stars: ✭ 2,114 (+4597.78%)
Mutual labels:  webauthn

Apple App Attest Validation

Maven central Build status Code coverage License Written in Kotlin JVM 11 required

Server-side library to validate the authenticity of Apple App Attest artifacts, including

  1. attestation statements,
  2. assertions, and
  3. receipts (plus requesting a new one from Apple).

The project targets the JVM in version 11 or later. The library is written purely in Kotlin while leveraging coroutines for asynchronous execution where meaningful. The implementation relies on only two third party dependencies: Bouncy Castle (CMS, ASN.1 parsing) and Jackson (CBOR decoding). The software is available under the conditions of the Apache 2.0 license enabling its usage in most circumstances.

The implementation follows the steps outlined in the articles "Validating Apps That Connect to Your Server" and "Assessing Fraud Risk" at Apple Developer.

Getting Started

The library is published to Maven Central.

Gradle (Kotlin)

dependencies {
    implementation("ch.veehait.devicecheck:devicecheck-appattest:$latestVersion")
}

Gradle (Groovy)

dependencies {
    implementation "ch.veehait.devicecheck:devicecheck-appattest:$latestVersion"
}

Maven

<dependencies>
  <!-- ... -->
  <dependency>
    <groupId>ch.veehait</groupId>
    <artifactId>devicecheck-appattest</artifactId>
    <version>${latestVersion}</version>
  </dependency>
  <!-- ... -->
</dependencies>

Usage

Verify the Attestation

An iOS app creates an attestationObject for a key created through DCAppAttestService.generateKey() by calling DCAppAttestService.attestKey(). Make sure the clientDataHash comprises a payload which includes a challenge you created within your backend prior to the app's call to attestKey. A good challenge is created randomly, only used once (i.e., one challenge per attestation) and large enough to prevent guessing.

let service = DCAppAttestService.shared

service.generateKey { keyId, error in
    guard error == nil else { /* Handle the error. */ }
    // Store keyId for subsequent operations.
}

service.attestKey(keyId, clientDataHash: hash) { attestationObject, error in
    guard error == nil else { /* Handle error and return. */ }
    // Send attestationObject to your server for verification.
}

The server implementation receives the attestationObject, e.g., Base64 encoded, and the keyId. The keyId returned from DCAppAttestService.generateKey() is already Base64 encoded (or more precisely, it is the Base64 encoded SHA-256 digest of the public key of the generated key).

To validate the authenticity of the attestationObject, instantiate an AttestationValidator for the App which calls DCAppAttestService.

// Create an instance of AppleAppAttest specific to a given iOS app, development team and
// Apple Appattest environment
val appleAppAttest = AppleAppAttest(
    app = App("6MURL8TA57", "de.vincent-haupert.apple-appattest-poc"),
    appleAppAttestEnvironment = AppleAppAttestEnvironment.DEVELOPMENT,
)

// Create an AttestationValidator instance
val attestationValidator = appleAppAttest.createAttestationValidator()

// Validate a single attestation object. Throws an AttestationException if a validation
// error occurs.
val result: ValidatedAttestation = attestationValidator.validate(
    attestationObject = Base64.getDecoder().decode("o2NmbXRvYXBwbGUtYXBwYXR0ZXN0Z2F ..."),
    keyIdBase64 = "XGr5wqmUab/9M4b5vxa6KkPOigfeEWDaw7tuK02aJ6c=",
    serverChallenge = "wurzelpfropf".toByteArray(),
)

If the method call returns, the validation has passed and you can now trust the returned result which contains references to the attestation certificate and the verified receipt. You use the public key of the attestation certificate for the verification of assertions and the receipt for obtaining a fraud risk metric.

Also refer to AttestationValidatorTest.

Verify the Assertion

As soon as you validated the attestation statement, your app may leverage the attested public key to create assertions for arbitrary payloads using the App Attest service:

service.generateAssertion(keyId, clientDataHash: clientDataHash) { assertionObject, error in
    guard error == nil else { /* Handle the error. */ }
    // Send the assertion and request to your server.
}

It is worthwhile to note that the returned assertionObject does not contain the keyId by itself. You have to include it in the data which accompanies the assertionObject. Make sure to not rely on the keyId to establish a link to any identity in your systems prior to verifying the assertion's authenticity by calling AssertionValidator.validate():

// Initialize AppleAppAttest as above

val assertionChallengeValidator = object : AssertionChallengeValidator {
    override fun validate(
        assertionObj: Assertion,
        clientData: ByteArray,
        attestationPublicKey: ECPublicKey,
        challenge: ByteArray,
    ): Boolean = TODO("Your application specific challenge validation routine")
}

val assertionValidator = appleAppAttest.createAssertionValidator(
    assertionChallengeValidator
)

val assertion = assertionValidator.validate(/* ... */)

If the call returns, the app successfully proved control of the attested device. Make sure to include a challenge which suits the security demands of your service. A safe approach is to issue server-side per-assertion challenges, similar to those created for the initial attestation statement (see above).

Also refer to AssertionValidatorTest

Assess Fraud Risk with Receipts

See ReceiptValidatorTest and ReceiptExchangeTest.

Contributions

Your contributions are welcome! Just submit a pull request. Also, if you have a question, feel free to open an issue.

License

Apache 2.0 license

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].