Closed benalleng closed 7 months ago
Right now for web applications you can press the show details button and click copy raw json I'm still testing how to send data back to the web clients Maybe we can use a url callback
newAnchor.href = `intent:${encodedJson}#Intent;scheme=nostrsigner;S.type=sign_event;S.callbackUrl=https://example.com/externalSigner?event=;end`;
Something like this
Changed the readme for web applications I'm not a web dev so i don't know if this is the best aproach to sending intents to a android app I'm generating a new build of the application with the changes from the example in the readme
https://github.com/greenart7c3/Amber#support-for-web-applications
Sweet! been testing out amber for support in a non-nostr web app and having a callbackurl should really reduce the friction of all the clipboard shenanigans
Working on a PoC if you want to take a look at the possibilities for Amber! https://github.com/saving-satoshi/saving-satoshi/pull/485
I think we should be using an encoded payload like base64 or web safe base64. https://base64.guru/standards/base64url
You never know what compatibility and security issues we could have with random characters in a hyperlink.
Sending the event json can lead to a large url that breaks the limit of the browsers So to fix this i'm now sending it gzip compressed
you can decompress it with something like:
const decodedData = atob(encodedString);
const gzipedDataArray = Uint8Array.from(decodedData, c => c.charCodeAt(0))
const ungzipedData = pako.ungzip(gzipedDataArray);
console.log( new TextDecoder().decode(ungzipedData))
🤔 sounds like a little versioning or flagging might be worth doing here.
Being able to choose or change the compression type in the future or even upgrade how the data is encoded seems like a potential future requirement.
That, or we just try to get a shit load of eyes on this so that we can be confident with a single solution.
Something like a single beginning character would suffice cashu uses base64 encoded tokens and prefixes with "cashu" and "A" where A is the version number.
So you get cashuAey1.....
We may not need the prefix aspect, or at least, I don't understand it's usefulness if we're using a custom http scheme.
How you handle a callback URL is also interesting. Needs some testing, but if you pass back data using the anchor #
, then you have no data size limits, but the server doesn't see the data.
This might actually be a good thing. What we want here is not to call the callback URL using a http client, but to launch a browser so that the webpage can do the broadcasting for you. This will let clients that are single page applications with no backends work without requiring server logic hosting costs.
I haven't thought too hard about this, there's no real security reason to do this as far as I know, but it's an option if it becomes useful.
There are two things there btw:
Callback by launching a web browser to let client side broadcasting of messages instead of requiring a web server.
Using # in the URL (e.g. https://example.com/externalSigner#event=;end;
) to allow larger payloads with the caveat that a server cannot read the data (which is typically nice when you want to provide sensitive data to a webpage to handle, but not the server that processed the request).
They don't rely on one another.
Using # also doesn't work. Android intent also breaks and won't let you send the event. We need to send it with gzip or other compression or send only the signature back. Maybe we can use something in the url callback like if contains #event then send the event else send only the signature
Yeah, sorry, I applied the #
to the callback URL only, not the intent itself.
Sorry if that caused some confusion, but we are on the same page.
Here's what I did for now: I'm using SignerA... where A is the version number then in the website you have to decode the url with something like decodeURIComponent and then decompress the event. We can also add a option in the intent so clients that don't send large events can use Amber without compressing the data or change it to don't compress the data by default. S.compression=none
newAnchor.href = `intent:${encodedJson}#Intent;scheme=nostrsigner;S.type=sign_event;S.compression=none;S.callbackUrl=https://example.com/externalSigner?event=;end`;
which approach do you think is better?
Hi. I am upgrading my webapp Nostr/Amber signin integration with this new stuff (before I had the user manually paste the signed json)
Now my intent is:
`intent:${encodeURIComponent(eventString)}#Intent;scheme=nostrsigner;S.compressionType=none;S.returnType=signature;S.type=sign_event;S.callbackUrl=${callbackUrl};end`
And I get called back and get an event string like:
c8374b2debd8a5bd5a496d6cbb3098deaef4524df5e461f490813cec9340d3e76c25e8b80c9d58000c9c23701dd629f1b9aaf24419f68c73538739171c4374ab
But I cannot extract anything from that... How can I get the signed event string from that?
Thanks.
just from first glance it looks like you are just getting the signature
S.returnType=signature;
try removing that, I think the whole event is the default functionality...?
Here is what I believe is the relevant code
} else if (intentData.callBackUrl != null) {
if (intentData.returnType == ReturnType.SIGNATURE) {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(intentData.callBackUrl + Uri.encode(value))
context.startActivity(intent)
} else {
if (intentData.compression == CompressionType.GZIP) {
// Compress the string using GZIP
val byteArrayOutputStream = ByteArrayOutputStream()
val gzipOutputStream = GZIPOutputStream(byteArrayOutputStream)
gzipOutputStream.write(event.toByteArray())
gzipOutputStream.close()
// Convert the compressed data to Base64
val compressedData = byteArrayOutputStream.toByteArray()
val encodedString = Base64.getEncoder().encodeToString(compressedData)
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(intentData.callBackUrl + Uri.encode("Signer1$encodedString"))
context.startActivity(intent)
// With no returnType or CompressionType you should get the raw event back
} else {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(intentData.callBackUrl + Uri.encode(event))
context.startActivity(intent)
}
}
just from first glance it looks like you are just getting the signature
S.returnType=signature;
try removing that, I think the whole event is the default functionality...?
yes, just tried that, actually changed to "event" and now I can parse the hex string.
With the addition of the base64 encoding of events I feel as though this issue can safely be closed @greenart7c3 what do you think?
Sure, I'll close this for now
Does the web intent have support for returning the signed event and not only the signature as there currently aren't signerTypes for web?