firebase / firebase/flutterfire

[firebase_app_check]: AppAttestProvider is selected, but generated App Check token appears to use DeviceCheck

Open
#18,665 4 comments 0 reactions 0 assignees View on GitHub
blocked: customer-response platform: ios plugin: app_check type: bug
Dominant language
Dart
Stars
9.3k
Forks
4.1k
Avg merge
1d 19h
Merged PRs (30d)
53

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues.

### Which plugins are affected?

App Check

### Which platforms are affected?

iOS

### Description

I am trying to use Apple App Attest exclusively as the Firebase App Check provider on a physical iOS device.

I explicitly configure the provider as:

await FirebaseAppCheck.instance.activate(
providerApple: const AppleAppAttestProvider(),
);

I am not using appAttestWithDeviceCheckFallback.

The application is running on a physical iPhone in Release mode.

The following are correctly configured:

Apple App Attest capability is enabled in Xcode.
The App Attest entitlement is configured for production.
The application is running on a physical iOS device.
AppleAppAttestProvider is explicitly selected.
There is no DeviceCheck fallback configured.
Native investigation

I added logging to the native FlutterFire implementation to verify which provider is actually being selected.

The native plugin receives:

providerName = appAttest

and the AppCheckProviderWrapper executes:

delegateProvider = AppAttestProvider(app: app)

I also confirmed that the resulting provider is an instance of:

FIRAppAttestProvider

Therefore, it appears that FlutterFire is correctly selecting and instantiating the App Attest provider.

Unexpected result

After activating App Check, I retrieve the token using:

final token = await FirebaseAppCheck.instance.getToken(true);

However, when I decode the returned Firebase App Check JWT, the payload contains:

{
"provider": "device_check_device_identification"
}

This makes it appear that the resulting App Check token is associated with DeviceCheck rather than App Attest.

I also checked the Firebase/Google Cloud logs while requesting the token and could not find an ExchangeAppAttestAttestation operation. Instead, the behavior appears consistent with the DeviceCheck flow.

Expected behavior

Since I explicitly configure:

AppleAppAttestProvider()

I would expect the Firebase App Check token to be generated through the Apple App Attest flow, rather than DeviceCheck.

I would also expect the Firebase App Check token/provider information to indicate that App Attest was used.

Steps to reproduce
Configure Firebase in a Flutter iOS application.
Enable App Check for the Firebase project.
Configure Apple App Attest in the Apple Developer account and Xcode.
Use a physical iOS device.
Run the application in Release mode.
Configure FlutterFire with:
await FirebaseAppCheck.instance.activate(
providerApple: const AppleAppAttestProvider(),
);
Request a token:
final token = await FirebaseAppCheck.instance.getToken(true);
Decode the returned JWT.
Observe that the token contains:
"provider": "device_check_device_identification"
Additional information

I also inspected the FlutterFire native implementation.

The provider selection is definitely reaching the native layer as:

appAttest

and the native implementation creates:

AppAttestProvider(app: app)

Therefore, this does not appear to be a simple Flutter configuration issue or an accidental use of appAttestWithDeviceCheckFallback.

The main question is:

Why does an App Check token appear to be issued using DeviceCheck when AppleAppAttestProvider / FIRAppAttestProvider is explicitly configured and instantiated?

Could this be expected behavior in the underlying Firebase iOS SDK, or could there be an issue in the FlutterFire/native Firebase App Check integration?

Environment
Platform: iOS
Device: Physical iPhone
Build configuration: Release
Apple App Attest: Enabled
App Attest entitlement: Production
FlutterFire provider: AppleAppAttestProvider
DeviceCheck fallback: Not configured
firebase_app_check: 0.4.7
Firebase iOS SDK: 12.18.0

I can provide additional logs, the relevant native FlutterFire source changes, Podfile.lock, or a minimal reproduction project if needed.

### Reproducing the issue

.

### Firebase Core version

4.13.0

### Flutter Version

3.35.7

### Relevant Log Output

```shell

```

### Flutter dependencies

Expand Flutter dependencies snippet

```yaml

Replace this line with the contents of your `flutter pub deps -- --style=compact`.

```

### Additional context and comments

_No response_

Contributor guide

Open the contributing guide

Research direction

Reproduce the report with firebase_app_check 0.4.7 on a physical iOS device, then trace the native provider selection through AppCheckProviderWrapper and AppAttestProvider. Compare the selected provider with the decoded token and Firebase logs, including whether an ExchangeAppAttestAttestation operation occurs. Done means the underlying SDK behavior or FlutterFire integration is identified and the next corrective action is clear.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, firebase, flutter
Domain
mobile, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.