app_device_integrity_plus 1.0.2 copy "app_device_integrity_plus: ^1.0.2" to clipboard
app_device_integrity_plus: ^1.0.2 copied to clipboard

Flutter plugin for App Attest and Play Integrity with real challenge (nonce) support. Replaces static dummy nonce with server-generated values.

App Device Integrity Plus #

πŸ‡ΊπŸ‡Έ English

Why? #

What This Fork Fixes #

The original app_device_integrity had a critical issue:

  • The challengeString (nonce) sent from Flutter was completely ignored.

  • The plugin always used a static Base64.encode(ByteArray(40)) value.

  • This produced the well-known "AAAAAAAAAAAA..." nonce in Play Integrity logs.

  • Real server-side verification was not possible because the nonce never matched.

Fixes in This Version #

This fork fixes all of that.

  • Proper nonce passthrough from Flutter β†’ Native β†’ Play Integrity

  • Removed static dummy nonce (ByteArray(40))

  • Added proper MethodChannel argument handling

  • Updated API to accept challengeString exactly as given

  • Real attestation with server-side validation now works

  • README rewritten for clarity

  • Additional flow diagram for easier understanding


πŸš€ How to Use #

  1. Request nonce from your backend

Your server must generate a unique challenge per session.

final sessionId = await api.getNonce();
  1. Pass nonce into the plugin
final integrity = AppDeviceIntegrityPlus();

if (Platform.isAndroid) {
  final token = await integrity.getAttestationServiceSupport(
    challengeString: sessionId,
    gcp: 523725941100,
  );
} else {
  final token = await integrity.getAttestationServiceSupport(
    challengeString: sessionId,
  );
}
  1. Send token to backend for validation
await api.verifyIntegrity(token);

πŸ“Š Attestation Flow (App ↔ API Server ↔ Google) #

sequenceDiagram
    participant APP
    participant API as API Server
    participant GOOGLE as Google Server (Play Integrity)

    APP->>API: Request requestHash (based on request data)
    API-->>APP: Generate & return requestHash

    note right of APP: Play Integrity preparation (prepare phase)

    APP->>GOOGLE: prepareIntegrityToken(cloudProjectNumber)
    GOOGLE-->>APP: Return IntegrityTokenProvider

    note right of APP: Standard request can now be executed

    APP->>GOOGLE: provider.request(requestHash included)
    GOOGLE-->>APP: Return Standard signed token (JWT)

    APP->>API: Send token to server for verification

    API->>GOOGLE: Validate & decrypt token
    GOOGLE->>API: Return token payload (including requestHash)

    note left of API: Compare requestHash with original

    API-->>APP: OK (valid client) or Error (tampered/replay attack)

πŸ“š References #

πŸ‡°πŸ‡· ν•œκ΅­μ–΄

πŸ”§ μ™œ λ§Œλ“€κ²Œ λ˜μ—ˆλŠ”κ°€? #

원본 app_device_integrity ν”ŒλŸ¬κ·ΈμΈμ˜ 문제 #

  • Integrity API의 기쑴방식 제곡(λ ˆκ±°μ‹œ)
  • Flutterμ—μ„œ λ„˜κΈ΄ challengeString(nonce)을 μ „ν˜€ μ‚¬μš©ν•˜μ§€ μ•ŠμŒ
  • λ‚΄λΆ€μ—μ„œ 항상 ByteArray(40) β†’ Base64 μΈμ½”λ”©ν•œ κ°’ μ‚¬μš©
  • κ·Έλž˜μ„œ Play Integrity λ‘œκ·Έμ— "AAAAAAAAAA..." nonce만 좜λ ₯됨
  • μ„œλ²„ 검증 μ‹œ nonce 뢈일치 β†’ 정상적인 λ³΄μ•ˆ 검증 λΆˆκ°€λŠ₯

βœ… 이 λ²„μ „μ—μ„œ μˆ˜μ • / κ°œμ„ λœ λ‚΄μš© #

  • Integrity API의 ν‘œμ€€ λ°©μ‹μœΌλ‘œ λ¦¬νŽ™ν„°λ§

  • μ„œλ²„μ—μ„œ 받은 nonceλ₯Ό κ·ΈλŒ€λ‘œ Play Integrity에 전달

  • 더 이상 static dummy nonce μ‚¬μš©ν•˜μ§€ μ•ŠμŒ

  • MethodChannel νŒŒλΌλ―Έν„° 처리 μˆ˜μ •

  • Android/iOSμ—μ„œ μ‹€μ œ nonce 기반 토큰 생성 κ°€λŠ₯

  • README μ „λ©΄ μž¬μž‘μ„±

  • ν”Œλ‘œμš° λ‹€μ΄μ–΄κ·Έλž¨ μΆ”κ°€

πŸš€ μ‚¬μš© 방법 #

  1. μ„œλ²„μ—μ„œ nonce λ°œκΈ‰
final sessionId = await api.getNonce();
  1. ν”ŒλŸ¬κ·ΈμΈμ— nonce 전달
final integrity = AppDeviceIntegrityPlus();

if (Platform.isAndroid) {
  final token = await integrity.getAttestationServiceSupport(
    challengeString: sessionId,
    gcp: 523725941100,
  );
} else {
  final token = await integrity.getAttestationServiceSupport(
    challengeString: sessionId,
  );
}
  1. 토큰을 μ„œλ²„λ‘œ 전달해 검증
await api.verifyIntegrity(token);

πŸ“Š 전체 ν”Œλ‘œμš° (μ•± ↔ μ„œλ²„ ↔ Google) #

sequenceDiagram
    participant APP
    participant API as API Server
    participant GOOGLE as Google Server
    
    APP->>API: requestHash μš”μ²­ (μš”μ²­ 데이터 기반)
    API-->>APP: requestHash 생성 & λ°œκΈ‰

    note right of APP: μ•± λ‚΄λΆ€μ—μ„œ Play Integrity μ€€λΉ„(prepare)

    APP->>GOOGLE: prepareIntegrityToken(cloudProjectNumber)
    GOOGLE-->>APP: IntegrityTokenProvider λ°˜ν™˜

    note right of APP: 이제 ν‘œμ€€ μš”μ²­(request) κ°€λŠ₯

    APP->>GOOGLE: provider.request(requestHash 포함)
    GOOGLE-->>APP: Standard signed token λ°˜ν™˜

    APP->>API: token 전달 (검증 μš”μ²­)

    API->>GOOGLE: λ³΅ν˜Έν™” 및 토큰 검증
    GOOGLE->>API: requestHash λ°˜ν™˜

    API-->>APP: OK (정상) λ˜λŠ” Error (μœ„λ³€μ‘°/μž¬μ „μ†‘ 곡격)
    note left of API: requestHash λŒ€μ‘°

πŸ“š μ°Έκ³  #

0
likes
150
points
156
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter plugin for App Attest and Play Integrity with real challenge (nonce) support. Replaces static dummy nonce with server-generated values.

Homepage

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on app_device_integrity_plus

Packages that implement app_device_integrity_plus