Skip to content

Commit

Permalink
Properly implement 2.0 authorize method in MobileWalletAdapterClient (#…
Browse files Browse the repository at this point in the history
…569)

* attempt

* moar protection

* meh

* some cleanup

* add authToken

* fix some things

* remove unused import
  • Loading branch information
Funkatronics authored Oct 16, 2023
1 parent f4f49e6 commit 1a327af
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -307,18 +307,58 @@ public static class InsecureWalletEndpointUriException extends JsonRpc20InvalidR
// authorize
// =============================================================================================

@Deprecated
@NonNull
public AuthorizationFuture authorize(@Nullable Uri identityUri,
@Nullable Uri iconUri,
@Nullable String identityName,
@Nullable String cluster)
throws IOException {
if (identityUri != null && (!identityUri.isAbsolute() || !identityUri.isHierarchical())) {
throw new IllegalArgumentException("If non-null, identityUri must be an absolute, hierarchical Uri");
} else if (iconUri != null && !iconUri.isRelative()) {
throw new IllegalArgumentException("If non-null, iconRelativeUri must be a relative Uri");
}

final JSONObject authorize;
try {
final JSONObject identity = new JSONObject();
identity.put(ProtocolContract.PARAMETER_IDENTITY_URI, identityUri);
identity.put(ProtocolContract.PARAMETER_IDENTITY_ICON, iconUri);
identity.put(ProtocolContract.PARAMETER_IDENTITY_NAME, identityName);
authorize = new JSONObject();
authorize.put(ProtocolContract.PARAMETER_IDENTITY, identity);
authorize.put(ProtocolContract.PARAMETER_CLUSTER, cluster); // null is OK
} catch (JSONException e) {
throw new UnsupportedOperationException("Failed to create authorize JSON params", e);
}

return new AuthorizationFuture(methodCall(ProtocolContract.METHOD_AUTHORIZE, authorize, mClientTimeoutMs));
}

@NonNull
public AuthorizationFuture authorize(@Nullable Uri identityUri,
@Nullable Uri iconUri,
@Nullable String identityName,
@Nullable String chain)
@Nullable String chain,
@Nullable String authToken,
@Nullable String[] features,
@Nullable byte[][] addresses
/* TODO: sign in payload */)
throws IOException {
if (identityUri != null && (!identityUri.isAbsolute() || !identityUri.isHierarchical())) {
throw new IllegalArgumentException("If non-null, identityUri must be an absolute, hierarchical Uri");
} else if (iconUri != null && !iconUri.isRelative()) {
throw new IllegalArgumentException("If non-null, iconRelativeUri must be a relative Uri");
}

if (chain != null && !Identifier.isValidIdentifier(chain)) {
throw new IllegalArgumentException("provided chain is not a valid chain identifier");
}

final JSONArray featuresArr = features != null ? JsonPack.packStrings(features) : null;
final JSONArray addressesArr = addresses != null ? JsonPack.packByteArraysToBase64PayloadsArray(addresses) : null;

final JSONObject authorize;
try {
final JSONObject identity = new JSONObject();
Expand All @@ -328,6 +368,9 @@ public AuthorizationFuture authorize(@Nullable Uri identityUri,
authorize = new JSONObject();
authorize.put(ProtocolContract.PARAMETER_IDENTITY, identity);
authorize.put(ProtocolContract.PARAMETER_CHAIN, chain); // null is OK
authorize.put(ProtocolContract.PARAMETER_AUTH_TOKEN, authToken); // null is OK
authorize.put(ProtocolContract.PARAMETER_FEATURES, featuresArr); // null is OK
authorize.put(ProtocolContract.PARAMETER_ADDRESSES, addressesArr); // null is OK
} catch (JSONException e) {
throw new UnsupportedOperationException("Failed to create authorize JSON params", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class MobileWalletAdapterSession extends MobileWalletAdapterSessionCommon
@Nullable
private SessionProperties mSessionProperties;

@Deprecated
public MobileWalletAdapterSession(@NonNull MessageReceiver decryptedPayloadReceiver,
@Nullable StateCallbacks stateCallbacks) {
this(decryptedPayloadReceiver, stateCallbacks, List.of(SessionProperties.ProtocolVersion.LEGACY));
Expand Down Expand Up @@ -127,9 +128,11 @@ protected void handleSessionEstablishmentMessage(@NonNull byte[] payload)
byte[] encryptedSessionProperties =
Arrays.copyOfRange(payload, ECDSAKeys.ENCODED_PUBLIC_KEY_LENGTH_BYTES, payload.length);
mSessionProperties = parseSessionProps(encryptedSessionProperties);
} catch (ArrayIndexOutOfBoundsException e) {
} catch (IndexOutOfBoundsException e) {
mSessionProperties = new SessionProperties(SessionProperties.ProtocolVersion.LEGACY);
}

doSessionEstablished();
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ public LocalAssociationScenario(@IntRange(from = 0) int clientTimeoutMs,
@NonNull List<SessionProperties.ProtocolVersion> supportedProtocolVersions) {
super(clientTimeoutMs);

// mSupportedProtocolVersions = supportedProtocolVersions;

mPort = new Random().nextInt(WebSocketsTransportContract.WEBSOCKETS_LOCAL_PORT_MAX -
WebSocketsTransportContract.WEBSOCKETS_LOCAL_PORT_MIN + 1) +
WebSocketsTransportContract.WEBSOCKETS_LOCAL_PORT_MIN;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class ProtocolContract {
// METHOD_AUTHORIZE takes an optional PARAMETER_IDENTITY
// METHOD_AUTHORIZE takes an optional PARAMETER_AUTH_TOKEN
// METHOD_AUTHORIZE takes an optional PARAMETER_CHAIN
// METHOD_AUTHORIZE takes an optional PARAMETER_FEATURES
// METHOD_AUTHORIZE takes an optional PARAMETER_ADDRESSES
// METHOD_AUTHORIZE returns a RESULT_AUTH_TOKEN
// METHOD_AUTHORIZE returns a RESULT_ACCOUNTS
// METHOD_AUTHORIZE returns an optional RESULT_WALLET_URI_BASE
Expand Down Expand Up @@ -62,6 +64,8 @@ public class ProtocolContract {

public static final String PARAMETER_CHAIN = "chain"; // type: String (one of the CHAIN_* values)

public static final String PARAMETER_FEATURES = "features"; // type: JSON array of String (feature identifiers)

public static final String PARAMETER_AUTH_TOKEN = "auth_token"; // type: String

public static final String PARAMETER_PAYLOADS = "payloads"; // type: JSON array of String (base64-encoded payloads)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@ protected void generateSessionECDHSecret(@NonNull ECPublicKey otherPublicKey) {
Log.i(TAG, "Encrypted session established");

mDecryptedPayloadReceiver.receiverConnected(this);
}

protected void doSessionEstablished() {
if (mStateCallbacks != null) {
mStateCallbacks.onSessionEstablished();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ protected void handleSessionEstablishmentMessage(@NonNull byte[] payload)
// Generate an EC key on the P-256 curve, and do ECDH to produce the shared secret
final ECPublicKey ourPublicKey = generateSessionECDHKeyPair();
generateSessionECDHSecret(theirPublicKey);
doSessionEstablished();

// Send a response to allow the counterparty to perform ECDH as well
try {
mMessageSender.send(createHelloRsp(ourPublicKey,
new SessionProperties(SessionProperties.ProtocolVersion.LEGACY)));
mMessageSender.send(createHelloRsp(ourPublicKey, getSessionProperties()));
} catch (IOException e) {
Log.e(TAG, "Failed to send HELLO_RSP; terminating session", e);
onSessionError();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ protected LocalScenario(@NonNull Context context,
@NonNull Callbacks callbacks,
@NonNull byte[] associationPublicKey,
@NonNull PowerConfigProvider powerConfigProvider,
@NonNull List<SessionProperties.ProtocolVersion> supportedProtocolVersions) {
@NonNull List<SessionProperties.ProtocolVersion> requestedProtocolVersions) {
mCallbacks = callbacks;
mMobileWalletAdapterConfig = mobileWalletAdapterConfig;
this.associationPublicKey = associationPublicKey;

SessionProperties.ProtocolVersion maxSupportedProtocolVersion =
SessionProperties.ProtocolVersion.LEGACY;
for (SessionProperties.ProtocolVersion version : supportedProtocolVersions) {
for (SessionProperties.ProtocolVersion version : requestedProtocolVersions) {
if (version.ordinal() > maxSupportedProtocolVersion.ordinal()
&& mobileWalletAdapterConfig.supportedProtocolVersions.contains(version)) {
maxSupportedProtocolVersion = version;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public LocalWebSocketServerScenario(@NonNull Context context,
@NonNull LocalScenario.Callbacks callbacks,
@NonNull byte[] associationPublicKey,
@WebSocketsTransportContract.LocalPortRange int port,
@NonNull List<SessionProperties.ProtocolVersion> supportedProtocolVersions) {
@NonNull List<SessionProperties.ProtocolVersion> requestedProtocolVersions) {
this(context, mobileWalletAdapterConfig, authIssuerConfig, callbacks,
associationPublicKey, port, new DevicePowerConfigProvider(context), supportedProtocolVersions);
associationPublicKey, port, new DevicePowerConfigProvider(context), requestedProtocolVersions);
}

/*package*/ LocalWebSocketServerScenario(@NonNull Context context,
Expand All @@ -53,8 +53,8 @@ public LocalWebSocketServerScenario(@NonNull Context context,
@NonNull byte[] associationPublicKey,
@WebSocketsTransportContract.LocalPortRange int port,
PowerConfigProvider powerConfigProvider,
@NonNull List<SessionProperties.ProtocolVersion> supportedProtocolVersions) {
super(context, mobileWalletAdapterConfig, authIssuerConfig, callbacks, associationPublicKey, powerConfigProvider, supportedProtocolVersions);
@NonNull List<SessionProperties.ProtocolVersion> requestedProtocolVersions) {
super(context, mobileWalletAdapterConfig, authIssuerConfig, callbacks, associationPublicKey, powerConfigProvider, requestedProtocolVersions);
this.port = port;
this.mWebSocketServer = new LocalWebSocketServer(this, mWebSocketServerCallbacks);
}
Expand Down

0 comments on commit 1a327af

Please sign in to comment.