Skip to content

[Bug][MWA] keepConnectionAlive restores public key without restoring auth_token, causing inconsistent reconnect semantics and mid-session Authorize() prompts #267

@JoshhSandhu

Description

@JoshhSandhu

Describe the bug

When a player explicitly taps Logout in my Unity Android game (SolRacer) and then relaunches the app, adapter restores Account state without restoring authorization state. Logout is supposed to end the session, but the wallet acts as if it never happened.

While investigating I found three related lifecycle inconsistencies in SolanaMobileWalletAdapter:

  1. Logout() does not clear the in-memory _authToken, so within the same session subsequent signing operations may still attempt Reauthorize() using a token the player intended to revoke.

  2. Logout() does not clearly define whether wallet-side authorization is revoked when keepConnectionAlive is enabled, which creates ambiguity between local adapter logout and transport-level session termination.

  3. keepConnectionAlive = true restores PlayerPrefs["pk"] but does not restore _authToken, so on restart _Login() returns a cached account silently, while the first SignTransaction() call triggers a full Authorize() popup mid-gameplay instead of at login time.


To Reproduce

  1. Build a Unity Android game using SolanaWalletAdapter with keepConnectionAlive = true
  2. Launch on an Android device with Phantom or Seeker installed
  3. Connect the wallet, complete the full Authorize() flow, tap Approve in the wallet
  4. Tap Logout inside the game
  5. Kill the app completely and relaunch it
  6. Observe: the wallet reconnects silently with no authorization prompt shown

To reproduce the mid-gameplay popup (the keepConnectionAlive half-reconnect bug):

  1. Same setup, but skip the logout step, just kill and relaunch after connecting
  2. The app appears connected (no login prompt is shown)
  3. Trigger any on-chain transaction (e.g. submitting a race result)
  4. Observe: a full Authorize() wallet approval sheet appears in the middle of gameplay

Expected behavior

After an explicit Logout, the next app launch should show the wallet authorization prompt. The player made an active choice to log out, the game should not silently reconnect them.

For the keepConnectionAlive case: if a cached session exists and is still valid, the reconnect should be fully silent including signing (via reauthorize). If it is not valid or was explicitly revoked, the full Authorize() prompt should appear at login time, not mid-session during a transaction.

Adapter lifecycle invariant:

If Account is restored from cached state when keepConnectionAlive = true,
then authorization state should also be restored (via reauthorize),
or the adapter should trigger authorization during login instead of deferring it
until the first signing request.


Screenshots

N/A, the issue is a missing wallet approval prompt that should appear but does not.


Smartphone

  • Device: Solana Seeker (Android)
  • OS: Android 14
  • Wallet: Seeker Wallet / Phantom for Android
  • Unity version: 2022.3 LTS
  • Solana Unity SDK: com.solana.unity_sdk (PackageCache hash cedf547211d1)

Additional context

The root cause is that IAdapterOperations and MobileWalletAdapterClient have no deauthorize RPC implementation. The Mobile Wallet Adapter spec defines authorize, reauthorize, and deauthorize as three distinct operations, the SDK only implements the first two. Without deauthorize, there is no way to implement correct logout behavior in a Unity game on top of this SDK without reimplementing the MWA transport layer yourself.

The specific lines where the gaps are:

// SolanaMobileWalletAdapter.cs  Logout() never clears _authToken
public override void Logout()
{
    base.Logout();
    PlayerPrefs.DeleteKey("pk");
    PlayerPrefs.Save();
    // _authToken is never set to null here
}
// _Login() returns cached account but _authToken is null on restart
if (_walletOptions.keepConnectionAlive)
{
    string pk = PlayerPrefs.GetString("pk", null);
    if (!pk.IsNullOrEmpty()) return new Account(string.Empty, new PublicKey(pk));
    // auth token is not restored first sign op will trigger full Authorize() again
}
// IAdapterOperations.cs no Deauthorize() method exists
public interface IAdapterOperations
{
    Task<AuthorizationResult> Authorize(...);
    Task<AuthorizationResult> Reauthorize(...);
    Task<SignedResult> SignTransactions(...);
    Task<SignedResult> SignMessages(...);
    // Deauthorize() is missing
}

This affects any Unity game on Solana Mobile / Seeker that needs logout, player account switching, or multi-user device support.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions