Skip to the content.

TT Festival App — Hardcoded credentials, API keys & identifiers

Scope: com.appmiral.ttfestival v2.0.1 (versionCode 5), decompiled APK resources + manifest. Values below are redacted unless they are already non-secret identifiers. The full values are present in the APK/resources; this document avoids re-publishing secret-looking material in git.

This inventory separates:


1. High-risk / secret-looking values shipped in the APK

System Resource / location Redacted value Why it matters
Crowd Connected strings.xml: crowdConnectedKey dd54d39d App/tenant key used to initialise Crowd Connected (ConfigurationBuilder.withAppKey(...)).
Crowd Connected strings.xml: crowdConnectedToken a86f…ecb0 (32 hex chars) Token passed to ConfigurationBuilder.withToken(...). This is a real credential, not just an ID.
Crowd Connected strings.xml: crowdConnectedSecret kW2g…6xJ7 (32 chars) Secret passed to ConfigurationBuilder.withSecret(...). Shipping this client-side means anyone with the APK can extract it.
Spotify strings.xml: spotifyClientId a762…9e3 OAuth client id for Spotify integration. Client IDs are not secret, but should be monitored/restricted.
Spotify strings.xml: spotifySecretId 2517…3eb Client secret shipped in a mobile APK. This is the clearest hardcoded secret outside Crowd Connected.
Appmiral API strings.xml: x_Protect 64d2…bb23 (32 hex chars) Static x-protect header that gates the Appmiral read API (timetable stages/performances/artists, games/bierroute). The same value for every install — not per-user or per-session — so anyone with the APK can read the API as this tenant. See timetable-api-access.md.

Crowd Connected usage path

com.appmiral.crowdconnected.CrowdConnected.enable(...) reads:

CoreApp.getCrowdConnectedApiKey()
CoreApp.getCrowdConnectedApiToken()
CoreApp.getCrowdConnectedApiSecret()

and passes them directly into:

ConfigurationBuilder()
  .withAppKey(...)
  .withToken(...)
  .withSecret(...)

The live run then contacted mobile.crowdconnected.com; logcat also showed the app setting the SNS push endpoint as Crowd Connected alias sns_user_id. That proves these credentials are not dead config.


2. Public cloud/mobile keys and identifiers

These are less like passwords, but still security-sensitive because they identify projects and should be locked down by package name/SHA restrictions, API restrictions, IAM policy, and backend-side validation.

System Resource / location Redacted value Notes
Google Maps Android AndroidManifest.xml: com.google.android.geo.API_KEY AIza…aQ Maps SDK key. Should be restricted to com.appmiral.ttfestival + signing cert SHA and Maps-only APIs.
Firebase / Google API key strings.xml: google_api_key AIza…0E Firebase/Google API key used by Firebase clients. Not a secret by design, but should be API-restricted.
Firebase Crashlytics API key strings.xml: google_crash_reporting_api_key same as google_api_key Crashlytics/Firebase config key.
Crashlytics legacy key AndroidManifest.xml: com.crashlytics.ApiKey c330…5308 Legacy Crashlytics identifier/API key.
Firebase app id strings.xml: google_app_id 1:1057497894154:android:7bf629b172de8884 Firebase app identifier.
Firebase sender id strings.xml: gcm_defaultSenderId 1057497894154 FCM sender/project number.
Firebase DB URL strings.xml: firebase_database_url https://appmiral-prod.firebaseio.com Project endpoint; access depends on Firebase rules.
Google OAuth web client id strings.xml: default_web_client_id 1057497894154-…apps.googleusercontent.com OAuth client identifier.
Firebase project id strings.xml: project_id appmiral-prod Project id.
AWS Cognito/SNS identity pool strings.xml: sns_identity_pool_id eu-west-1:19db…cc01 Lets the app obtain temporary AWS credentials for SNS push endpoint registration. Must be tightly IAM-scoped.

3. Appmiral backend endpoints (not credentials)

Resource Value Purpose
api_url_v6 https://app.appmiral.com/api/v7/ Main Appmiral REST API.
api_function_url https://app.appmiral.com/function/ Appmiral/AWS Lambda function API (used for gamification badge unlocks etc.).
Deep-link host https://ttfestival2026.deeplink.appmiral.com/ Universal/App Links + QR/deeplink routing.

These are not secrets, but they are useful for mapping data flow and attack surface.


4. Explicitly null / inactive vendor credentials

The APK contains many platform-level placeholders from Appmiral. For TT Festival v2.0.1 they are not configured:

Vendor / feature Resource(s) Status
Cookie Information CMP cookieInformationClientId, cookieInformationClientSecret, cookieInformationSolutionId null
Facebook SDK facebookAppId, facebookClientToken; manifest auto-init/log-events disabled null / disabled
Braze brazeApiKeyAndroid, brazeApiKeyIos, brazeCustomEndpoint, brazeLocationEnabled null
Permutive permutiveApiKey, permutiveOrganisationId null
Salesforce Marketing Cloud salesforceAccessToken, salesforceApplicationId, salesforceClientCode, salesforceMarketingCloudUrl, salesforceMid null
CM Push app key cmPushApplicationKey null
Ticketmaster ticketmasterConsumerKeyAndroid, ticketmasterConsumerKeyIos null
Secondary Firebase secondaryFirebaseApiKey, secondaryFirebaseAppId, secondaryFirebaseProjectId empty
Sports Alliance sportsAllianceKey, sportsAllianceOrigin, sportsAllianceSecret, sportsAllianceTenant null

These placeholders are important because they explain why the consent registry lists SDKs that are not actually active/bundled.


5. Risk summary

Finding Risk
Crowd Connected app key + token + secret are embedded in the APK Anyone can extract them and attempt to talk to Crowd Connected mobile APIs as this app/tenant. Backend-side validation and rate limiting are essential.
x_Protect is a single static header shared by every install It is the only gate on the Appmiral read API (programme, games). It is not per-user/session and never rotates, so it is trivially replayed; it provides obfuscation, not access control. See timetable-api-access.md.
Spotify client secret is embedded in the APK Mobile apps are public clients; a client secret in an APK should be treated as compromised and rotated/replaced with PKCE-only OAuth.
AWS Cognito identity-pool id is embedded and used pre-consent for SNS Not a secret by itself, but IAM policy must limit actions to the minimum SNS endpoint operations.
Google/Firebase/Maps keys are embedded Normal for Android, but they must be package/signature/API restricted.
Many marketing/vendor secrets are null Good: Braze/Salesforce/Permutive/Facebook/etc. are not active in this build despite being present in the Appmiral platform registry.

6. Recommendation

  1. Treat crowdConnectedToken, crowdConnectedSecret, and spotifySecretId as exposed secrets; rotate them if they grant meaningful backend access.
  2. Confirm Crowd Connected credentials are tenant-scoped, write-only, rate-limited and cannot read back user/location data.
  3. Remove Spotify client secret from mobile clients; use Authorization Code with PKCE.
  4. Verify Google API keys are restricted to package name + signing certificate SHA and only the required APIs.
  5. Verify the AWS Cognito unauthenticated role can only perform the exact SNS endpoint registration/update calls needed by the app.