-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add signMessage
method
#779
Conversation
signMessage
methodsignMessage
method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disclaimer: I am just a regular reviewer, I don't have the power of code owner here, so my review comments are just suggestions.
Added
signMessage
to all wallets, all of them just throws until they add the implementation
I know it was a pattern used previously, but I wonder how useful this is. How to even know which wallets support this feature? Imagine I am a dApp developer, I would have a hard time integrating this feature unless I manually test all of the wallets.
packages/core/src/lib/helpers/verify-signature/verify-signature.ts
Outdated
Show resolved
Hide resolved
let nonceArray: Uint8Array = new Uint8Array(32); | ||
nonceArray = crypto.getRandomValues(nonceArray); | ||
const nonce = Buffer.from(nonceArray); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the internal implementation is in charge of the protocol security, and developers do not have any use for the nonce
, I think it is fair to remove it from the public interface. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a dApp developer, they could use nonce
to verify the signature, right? Correct me if I'm wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, well, validation is currently expected to be done manually by dApp developer. I think it would be great to have a higher-level API for dApp developers. This documentation example needs the validation to be featured
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean adding the following to the sample?
import { verifySignature, verifyFullKeyBelongsToUser } from "@near-wallet-selector/core";
// ...
const verifiedSignature = verifySignature({
message,
nonce,
recipient,
publicKey: signedMessage.publicKey,
signature: signedMessage.signature,
});
const verifiedFullKeyBelongsToUser = await verifyFullKeyBelongsToUser({
publicKey: signedMessage.publicKey,
accountId: signedMessage.accountId,
network: selector.options.network,
});
const ok = verifiedSignature && verifiedFullKeyBelongsToUser
Both functions are now exported from @near-wallet-selector/core
. Not sure if we really need a 'higher-level' API for dApp dev.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that is what I missed in the example.
I like this low-level API, but I would still consider having an API that won't expect developers don't forget to do the checks. I would expect that once the message is returned, it is already verified. What would be the use case for dApp developers needing to intervene and need control over each stage and have access to a potentially maliciously constructed message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point.
I'm thinking alternating it like so, where we have a second params (verify will be defaulted to true)
const signedMessage = await wallet.signMessage({
message,
recipient,
}, {verify: true});
Or we just derived the verify flag from the availability of nonce
field.
eg:
// This will verify the message
await wallet.signMessage({
message,
recipient,
})
// This will NOT verify the message
await wallet.signMessage({
message,
nonce,
recipient,
})
Either way, I believe the verification part should be the responsibility of Wallet builders?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kinda agree about making the verification step a bit more intentional from the side of the dApps, since they could potentially do their own (short-lived) caching of a valid public key per user, which would allow for instant actions on their apps instead of always doing an extra API call to check for account valid keys.
In the future, there could also be a standard text payload for simple things like "proof of account ownership" which use the same API, but don't require the user to intentionally complete the action in the wallet every single time (in the case of extension wallets, if it was done once per requesting and currently connected dApp, it could be done automatically each time afterwards using background script communication). To require each of these types of calls to still verify on the blockchain would make things like simply "liking a post" or whatnot, take a lot longer than they need to- deteriorating the user experience.
@frol this NEP and PR is a long time coming. We'd really like to get this implemented so our users can start making use of the feature. We've done it to the latest definition of the standard and followed previous code patterns in this project.
I think your reservations requires a larger discussion about wallet features and support, and building that into Wallet Selector. The churning of NEPs and features in this space definitely does leave a lot of feature gaps in some wallets, so its a relevant discussion to have. For this NEP specifically, wallets have had a long time to figure out their implementations. I think sticking with the error message for now is not the end of the world- dApps can handle that error and let the user know they should use a different wallet to make use of that feature. Again, this has really been a long time coming- the first implementation of which was |
async signMessage({ message, nonce, recipient, callbackUrl, state }) { | ||
logger.log("MyNearWallet:signMessage", { | ||
message, | ||
nonce, | ||
recipient, | ||
callbackUrl, | ||
state, | ||
}); | ||
|
||
throw new Error(`Method not supported by ${metadata.name}`); | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why this wouldn't be supported by MyNearWallet
/NearWallet
since all we need to sign a message is available without needing to redirect to the wallet website. This is how it could be done:
const { contract } = store.getState();
if (!_state.wallet.isSignedIn() || !contract) {
throw new Error("Wallet not signed in");
}
const account = _state.wallet.account();
const { networkId } = account.connection;
const accountId = account.accountId;
const keyPair = await _state.keyStore.getKey(networkId, accountId);
const signer = await nearAPI.InMemorySigner.fromKeyPair(
networkId,
accountId,
keyPair
);
return signer.signMessage(new Uint8Array(Buffer.from(message)));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would sign a message using the function call access key which was added on the Dapp side. I think this API is meant to sign messages with a full access key, which is only available on the wallet side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which makes sense- because otherwise you're handing DApps "signing power" when you sign into them. Only Full Access keys should be allowed to be the source of a wallet account's signed message.
What is the blocker for this PR? It's something that would greatly enhance the BOS experience, being able to sign messages and authenticate with third party servers without having to make the users sign in again and handle the sign in state separately would enable for a much more comprehensive experience. This would enable developers to enhance the UX of apps on BOS, the prime example being Horizon. There are some flows users should be able to perform (mostly including sensitive data that shouldn't be stored on-chain - or at least not without encrypting it first, but that's a whole different issue). And enabling message signing would make this flow's for one doable and for two it would be a better experience for auth on servers compared to current Web2.0 primitives making it an additional selling point. |
Hey @Elabar , Can you help me with this? |
Hi, it is a bug on our extension. Can you try again with extension disabled for now? |
Hey, what do you mean to disable the extension? If I disable it I will not be able to use this feature at all with Meteor wallet. Is this feature still in progress for the Meteor wallet? |
A new version of the extension has been released and it should solve this issue now. |
HERE Wallet already support signMessage method. I support that this should be implemented by other wallets as soon as possible. 👍 |
Hi, @AZbang after trying out the current implementation of The Also, it would be great to show some information for users like Meteor Wallet at this step: |
@Elabar thank you for submitting this PR, we are planning to merge the PR soon but we have a few suggestions and changes that might need to make. We are planning to remove the empty I have already prepared a PR based your current work: Elabar#1 |
Remove empty signMessage from wallets that do not implement it
@kujtimprenkuSQA Thanks for preparing the changes! It is merged now. |
This adds the signMessage at the types when getting the module/wallet from the selector at runtime so typescript does not complain and there is no need to check if this function is defined or not.
Thanks for merging it, I will be adding a small fix based on this comment: Elabar#1 (comment) . You can check the new PR here: Elabar#2 . |
Define signMessage when accessing a wallet/module
Hi, @Elabar do you mind addressing the conflicts? |
@kujtimprenkuSQA done |
Thanks, can you run |
fixed linting issue. |
Hi @Elabar, The signMessage is not working correctly on Meteor Wallet. Can you guys check if the implementation of the signMessage |
Hi @erditkurteshiSQA , @Elabar currently is occupied elsewhere. Can direct any Meteor stuff my way. We'll look into this now- thanks for reporting the issue! |
Hi @erditkurteshiSQA - would you mind following up with some more context in this issue please: Meteor-Wallet/meteor-public#5 |
Description
This PR is largely based on work from #604
signMessage
NEPsignMessage
signMessage
to all wallets, all of them just throws until they add the implementationWallets that support
signMessage
in this PRChecklist:
Type of change.