From 9406763c844e6df1a69ed4a499feb33926e1ae88 Mon Sep 17 00:00:00 2001 From: Nick Mills-Barrett Date: Mon, 6 Jul 2026 13:42:01 +0100 Subject: [PATCH 1/2] messagix/blocks: improve transient token error after AFAD flow --- pkg/connector/login.go | 3 +++ pkg/messagix/messengerlite.go | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/pkg/connector/login.go b/pkg/connector/login.go index a975445d..2c7ce370 100644 --- a/pkg/connector/login.go +++ b/pkg/connector/login.go @@ -221,6 +221,7 @@ var ( ErrLoginConsent = bridgev2.RespError{ErrCode: "FI.MAU.META_CONSENT_ERROR", Err: "Consent required, please check the official website or app and then try again", StatusCode: http.StatusBadRequest} ErrLoginCheckpoint = bridgev2.RespError{ErrCode: "FI.MAU.META_CHECKPOINT_ERROR", Err: "Checkpoint required, please check the official website or app and then try again", StatusCode: http.StatusBadRequest} ErrLoginTokenInvalidated = bridgev2.RespError{ErrCode: "FI.MAU.META_TOKEN_ERROR", Err: "Got logged out immediately", StatusCode: http.StatusBadRequest} + ErrLoginTransientToken = bridgev2.RespError{ErrCode: "FI.MAU.META_TRANSIENT_TOKEN_ERROR", Err: "Login approved but could not be completed automatically, please try again", StatusCode: http.StatusBadRequest} ErrLoginUnknown = bridgev2.RespError{ErrCode: "M_UNKNOWN", Err: "Internal error logging in", StatusCode: http.StatusInternalServerError} ) @@ -377,6 +378,8 @@ func (m *MetaNativeLogin) proceed(ctx context.Context, userInput map[string]stri log.Error().Err(err).Msg("Login steps returned error") if errors.As(err, &bloks.CheckpointError{}) { err = ErrLoginCheckpoint + } else if errors.Is(err, messagix.ErrTransientTokenLogin) { + err = ErrLoginTransientToken } return nil, err } diff --git a/pkg/messagix/messengerlite.go b/pkg/messagix/messengerlite.go index 35563221..6473f8e2 100644 --- a/pkg/messagix/messengerlite.go +++ b/pkg/messagix/messengerlite.go @@ -3,6 +3,7 @@ package messagix import ( "context" "encoding/json" + "errors" "fmt" "net/http" "net/url" @@ -19,6 +20,8 @@ import ( "go.mau.fi/mautrix-meta/pkg/messagix/useragent" ) +var ErrTransientTokenLogin = errors.New("login approved but could not be completed automatically, please try logging in again") + type MessengerLiteMethods struct { client *Client @@ -200,6 +203,7 @@ func (m *MessengerLiteMethods) DoLoginSteps(ctx context.Context, userInput map[s // is two_factor. It depends on the account, not on the MFA method // selected. m.client.Logger.Warn().Msg("Got credential_type transient_token, login will fail") + return nil, nil, ErrTransientTokenLogin } if len(loginRespPayload.SessionCookies) == 0 { From f5359be65050db5e8fc738f6459d1763fc958b4a Mon Sep 17 00:00:00 2001 From: Nick Mills-Barrett Date: Mon, 6 Jul 2026 13:50:39 +0100 Subject: [PATCH 2/2] messagix/bloks: move AFAD to the last MFA option Approve from another device often results in transient credentials we don't yet exchange for cookies, breaking the login, so pushing it down to the bottom of the options list. --- pkg/messagix/bloks/selenium.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/messagix/bloks/selenium.go b/pkg/messagix/bloks/selenium.go index 56725b2f..9b171b34 100644 --- a/pkg/messagix/bloks/selenium.go +++ b/pkg/messagix/bloks/selenium.go @@ -1074,13 +1074,16 @@ func (b *Browser) DoLoginStep(ctx context.Context, userInput map[string]string) methodNames := []string{} knownMethods := map[string]bool{ + "Authentication app": true, + "Email": true, + "Text message": true, + "Backup code": true, + "WhatsApp": true, + // Disabled because there's no reasonable way to support this outside of a webview + "Verify with Google": false, + // Intentionally last because this tends to give transient_token results rather than + // cookies directly, which requires a currently unknown extra step. "Notification on another device": true, - "Authentication app": true, - "Email": true, - "Text message": true, - "Backup code": true, - "WhatsApp": true, - "Verify with Google": false, } listItems := b.CurrentPage.FindDescendant(FilterByAttribute(