Skip to content

Auth: add package override support to getTokenWithAccount (#3278)#3468

Open
vijay12481248-lab wants to merge 5 commits into
microg:masterfrom
vijay12481248-lab:fix/getTokenWithAccount-package-override
Open

Auth: add package override support to getTokenWithAccount (#3278)#3468
vijay12481248-lab wants to merge 5 commits into
microg:masterfrom
vijay12481248-lab:fix/getTokenWithAccount-package-override

Conversation

@vijay12481248-lab
Copy link
Copy Markdown

Mirrors the override logic from AccountAuthenticator.getAuthToken into AuthManagerServiceImpl.getTokenWithAccount so that apps calling this path directly (e.g. patched YouTube flavors) also benefit from package overrides, fixing UNREGISTERED_ON_API_CONSOLE errors.

Mirrors the override logic from AccountAuthenticator.getAuthToken into
AuthManagerServiceImpl.getTokenWithAccount so that apps calling this
path directly (e.g. patched YouTube flavors) also benefit from package
overrides, fixing UNREGISTERED_ON_API_CONSOLE errors.
Addresses all code review issues from PR microg#3468:
Critical Fixes:
- Fix overridePackage fallback default that triggered override for all callers
- Add bounds check for getCertificates().get(0) to handle empty cert lists
- Include KEY_ACCOUNT_NAME and KEY_ACCOUNT_TYPE in NeedPermission result
Medium Fixes:
- Fix override trigger condition: only check KEY_OVERRIDE_PACKAGE (not OR)
- Use 'SHA-1' (with hyphen) instead of 'SHA1' for Java MessageDigest standard
- Remove putExtras(extras) that leaked sensitive caller data to activity
Minor Improvements:
- Clean up variable scoping for override-related variables
- Add defensive error handling for edge cases
All changes maintain backward compatibility and no API modifications.
Package override logic now properly mirrors AccountAuthenticator.getAuthToken behavior.
Fixes: microg#3468
…ure block

The setPackageSignature block had certs.get(0) inside an isEmpty() guard,
but the safety was implicit and fragile. Restructure to:
- Fetch overrideCert from extras bytes if present (no cert lookup needed)
- Otherwise call getCertificates and use 'certs.isEmpty() ? null : certs.get(0)'
- Null-check overrideCert before calling setPackageSignature
This makes null safety self-evident without relying on an outer isEmpty()
wrapper, addressing code review feedback on PR microg#3468.
…resolution

The override cert was computed twice — once in the isOverrideAllowed block
and again below for setPackageSignature. Consolidate into a single resolution:
- When overridePackage is provided, resolve and store overrideCert once
- Pass it down for both the userdata key check and setPackageSignature
- Use 'certs.isEmpty() ? null : certs.get(0)' explicitly (no outer guard)
- Null-check overrideCert before calling setPackageSignature
Addresses follow-up review comment on PR microg#3468.
@vijay12481248-lab vijay12481248-lab marked this pull request as ready for review May 12, 2026 18:34
Copy link
Copy Markdown

@matteozanettii matteozanettii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @vijay12481248-lab , few observations regarding the implementation:

  1. Certificate Selection: The logic uses certs.get(0), assuming the first certificate is the target. Have you considered edge cases with APK Signature Scheme v3 where key rotation might introduce multiple certificates?
  2. SHA-1 Usage: I noticed SHA-1 is used for authManager.setPackageSignature. While I assume this is a legacy requirement for the Auth servers, can you confirm if this is strictly necessary instead of moving to SHA-256?
  3. Magic Strings: There are several hardcoded strings like "NeedPermission", "1", and specifically "delegatee_user_id". Extracting these into constants would prevent future typos and improve overall maintainability.
  4. Broad Exception Catch: The catch (Exception e) block when setting the override signature is quite broad. It might be safer to catch specific exceptions like NoSuchAlgorithmException to prevent swallowing unrelated errors.

@vijay12481248-lab
Copy link
Copy Markdown
Author

Hi @vijay12481248-lab , few observations regarding the implementation:

  1. Certificate Selection: The logic uses certs.get(0), assuming the first certificate is the target. Have you considered edge cases with APK Signature Scheme v3 where key rotation might introduce multiple certificates?
  2. SHA-1 Usage: I noticed SHA-1 is used for authManager.setPackageSignature. While I assume this is a legacy requirement for the Auth servers, can you confirm if this is strictly necessary instead of moving to SHA-256?
  3. Magic Strings: There are several hardcoded strings like "NeedPermission", "1", and specifically "delegatee_user_id". Extracting these into constants would prevent future typos and improve overall maintainability.
  4. Broad Exception Catch: The catch (Exception e) block when setting the override signature is quite broad. It might be safer to catch specific exceptions like NoSuchAlgorithmException to prevent swallowing unrelated errors.

@vijay12481248-lab
Copy link
Copy Markdown
Author

Thanks for the review!

1. Certificate Selection (certs.get(0) & v3 key rotation)
certs.get(0) is intentional — it returns the original/leaf cert, which is what was recorded when the override permission was granted (stored as a SHA-256 digest in account userData). Using a newer rotated cert would break existing grants. This mirrors the same logic in AccountAuthenticator.getAuthToken for consistency.

2. SHA-1 in setPackageSignature
Yes, SHA-1 is required here — it's a legacy format expected by Google's Auth servers for package identity lookup, not used for any internal security decision. The authorization gate above it already uses SHA-256. Switching to SHA-256 for setPackageSignature would likely cause server-side auth failures since we don't control that API contract.

overrideCert = certs.isEmpty() ? null : certs.get(0);
}
if (overrideCert != null) {
authManager.setPackageSignature(PackageManagerUtilsKt.toHexString(PackageManagerUtilsKt.digest(overrideCert, "SHA-1"), ""));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
authManager.setPackageSignature(PackageManagerUtilsKt.toHexString(PackageManagerUtilsKt.digest(overrideCert, "SHA-1"), ""));
authManager.setPackageSignature(PackageManagerUtilsKt.toHexString(PackageManagerUtilsKt.digest(overrideCert, "SHA-1"), ""));
if (!effectivePackageName.equals(packageName)) {
// SHA-1 is used here intentionally: Google's Auth servers require the package
// signature in SHA-1 hex form for legacy compatibility. This is not used for
// security decisions — the authorization check above uses SHA-256.
byte[] overrideCertificateBytes = extras.getByteArray(AccountAuthenticator.KEY_OVERRIDE_CERTIFICATE);
CertData overrideCert;
if (overrideCertificateBytes != null) {
overrideCert = new CertData(overrideCertificateBytes);
} else {
// See comment above about certs.get(0) and APK Signature Scheme v3
List<CertData> certs = PackageManagerUtilsKt.getCertificates(context.getPackageManager(), packageName);
overrideCert = certs.isEmpty() ? null : certs.get(0);
}
if (overrideCert != null) {
authManager.setPackageSignature(PackageManagerUtilsKt.toHexString(PackageManagerUtilsKt.digest(overrideCert, "SHA-1"), ""));
}
}

Copy link
Copy Markdown

@matteozanettii matteozanettii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from copilot: Copilot said: I'll help you find a solution for
I'll help you find a solution for this failing job. Let me start by retrieving the job logs.Now let me examine the failing file:## Solution

The build is failing due to a Java compilation error in AuthManagerServiceImpl.java at line 221. The issue is an unreachable exception handler: the code catches NoSuchAlgorithmException, but the only method that could throw it (PackageManagerUtilsKt.digest()) is never actually called in the try block when an override certificate is not present.

Root Cause
Looking at lines 208-223, the try-catch block attempts to handle NoSuchAlgorithmException, but the exception can only be thrown by PackageManagerUtilsKt.digest() at line 219. However, line 219 is only executed if overrideCert != null (line 218). If overrideCert is null, the try block completes without any code that throws NoSuchAlgorithmException, making the catch clause unreachable.

Fix
Remove the try-catch block since the exception handling is not needed. The code is already defensive by checking if overrideCert != null before calling the digest method:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants