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
160
points
138
downloads

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

Documentation

API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on app_device_integrity_plus

Packages that implement app_device_integrity_plus