Skip to content

Fix push signature verification: include question in the signed string#116

Open
sysrow wants to merge 1 commit into
eduMFA:mainfrom
sysrow:fix/push-signature-question
Open

Fix push signature verification: include question in the signed string#116
sysrow wants to merge 1 commit into
eduMFA:mainfrom
sysrow:fix/push-signature-question

Conversation

@sysrow
Copy link
Copy Markdown

@sysrow sysrow commented May 24, 2026

The eduMFA server signs the push challenge as
{nonce}|{url}|{serial}|{question}|{title}|{sslverify} (6 fields). Upstream
commit 031858d ("Remove question from push request payload and replace it
with a static localizable question") dropped question from the payload and,
with it, from the signed-string reconstruction. The app now rebuilds only
5 fields, so the RSA signature of every incoming challenge fails to verify,
the request is rejected before the dialog is shown, and push approval is
impossible against a stock eduMFA server.

Re-add question to PushRequest (model, JSON, identifier) and insert it into
the signed string in the position the server uses. The on-screen text stays
the static localized question introduced by 031858d; question is used only
to reconstruct the signed payload, not for display.

The eduMFA server signs the push challenge as
{nonce}|{url}|{serial}|{question}|{title}|{sslverify} (6 fields). Upstream
commit 031858d ("Remove question from push request payload and replace it
with a static localizable question") dropped question from the payload and,
with it, from the signed-string reconstruction. The app now rebuilds only
5 fields, so the RSA signature of every incoming challenge fails to verify,
the request is rejected before the dialog is shown, and push approval is
impossible against a stock eduMFA server.

Re-add question to PushRequest (model, JSON, identifier) and insert it into
the signed string in the position the server uses. The on-screen text stays
the static localized question introduced by 031858d; question is used only
to reconstruct the signed payload, not for display.
@Luc1412
Copy link
Copy Markdown
Member

Luc1412 commented May 26, 2026

I didn't encounter this problem yet within my eduMFA testing setup yet. Could this be related to question being customized or not?

@sysrow
Copy link
Copy Markdown
Author

sysrow commented May 26, 2026

Hey, Ive let Claude do a simple bug report, tldr it does happen with a default question, so no customization of it is involved:

Problem

The server signs each push challenge over 6 fields, including question:

{nonce}|{url}|{serial}|{question}|{title}|{sslverify}      (RSA PKCS1v15 + SHA256, base32)

The authenticator on main (since commit 031858d) rebuilds only 5 (it dropped
question), so the signature never verifies: the challenge is rejected before the
approve/decline dialog and push login cannot complete.

  • Triggers on default config (question defaults to DEFAULT_MOBILE_TEXT =
    "Do you want to confirm the login?"; no policy needed).
  • Affects both token types: edupush and legacy push (the legacy class inherits
    the same _build_smartphone_data).

Versions brought up

  • eduMFA server: 2.9.2 (stock PyPI). Reproduced on a vanilla instance.
  • authenticator: main @ 3d2004a

Reproduce

# 1) run the authenticator from main on a device/emulator
git clone https://github.com/eduMFA/authenticator
cd authenticator && flutter pub get && flutter run

# 2) enroll a push token against your eduMFA server (scan the rollout QR)

# 3) trigger a login for that user
curl -s -d "user=<USER>&realm=<REALM>&pass=<PIN>" https://<your-server>/validate/check

# 4) watch the app log (it appears live in the `flutter run` console from step 1;
#    or: adb logcat -s flutter:V | grep -i "incoming message")

No approve/decline dialog appears; the app logs:

[token_notifier.dart#addPushRequestToToken] Validating incoming message failed.
Error: Signature does not match signed data.

Clean-room: commands used to stand up the vanilla server

pip install edumfa==2.9.2
export EDUMFA_CONFIGFILE=edumfa.cfg            # sqlite DB + enckey/audit-key paths
edumfa-manage create_enckey
edumfa-manage create_audit_keys
edumfa-manage createdb
edumfa-manage admin add admin -p <pw>
edumfa-manage run --host 127.0.0.1 --port 5005

# enrollment policy, scope=enrollment (poll-only, no Firebase):
#   action = edupush_firebase_configuration=poll only,
#            edupush_registration_url=http://<host>:5005/ttype/edupush
# enroll: POST /token/init  type=edupush genkey=1 user=<USER> realm=<REALM>

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.

2 participants