Skip to content

Commit

Permalink
Merge branch 'master' into 2379-doc-improve-chain-abstraction-overview
Browse files Browse the repository at this point in the history
  • Loading branch information
bucanero authored Jan 8, 2025
2 parents 268f9d1 + 617e69d commit 060dba4
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 85 deletions.
2 changes: 1 addition & 1 deletion docs/1.concepts/storage/decentralized-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ This call will return:
```

:::info
Find a code example about quering storage status on [this link](https://github.com/crustio/crust-demo/blob/main/near/src/index.ts#L144-L147).
Find a code example about querying storage status on [this link](https://github.com/crustio/crust-demo/blob/main/near/src/index.ts#L144-L147).
:::

#### 4. Add file prepaid
Expand Down
88 changes: 5 additions & 83 deletions docs/2.build/4.web3-apps/backend/backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
id: backend-login
title: Authenticate NEAR Users
---

import {Github} from "@site/src/components/codetabs"

Recently NEAR has approved a new standard that, among other things, enables users to authenticate into a backend service.

The basic idea is that the user will sign a challenge with their NEAR wallet, and the backend will verify the signature. If the signature is valid, then the user is authenticated.
Expand Down Expand Up @@ -60,86 +63,5 @@ const signature = wallet.signMessage({ message, recipient, nonce: challenge, cal
### 3. Verify the Signature
Once the user has signed the challenge, the wallet will call the `callbackUrl` with the signature. The backend can then verify the signature.

```js
const naj = require('near-api-js')
const js_sha256 = require("js-sha256")

class Payload {
constructor({ message, nonce, recipient, callbackUrl }) {
// The tag's value is a hardcoded value as per
// defined in the NEP [NEP413](https://github.com/near/NEPs/blob/master/neps/nep-0413.md)
this.tag = 2147484061;
this.message = message;
this.nonce = nonce;
this.recipient = recipient;
if (callbackUrl) { this.callbackUrl = callbackUrl }
}
}

const payloadSchema = {
struct: {
tag: "u32",
message: "string",
nonce: { array: { type: "u8", len: 32 } },
recipient: "string",
// Must be of type { option: "string" }
callbackUrl: { option: "string" },
},
};

export async function authenticate({ accountId, publicKey, signature }) {
// A user is correctly authenticated if:
// - The key used to sign belongs to the user and is a Full Access Key
// - The object signed contains the right message and domain
const full_key_of_user = await verifyFullKeyBelongsToUser({ accountId, publicKey })
const valid_signature = verifySignature({ publicKey, signature })
return valid_signature && full_key_of_user
}

export function verifySignature({ publicKey, signature }) {
// Reconstruct the payload that was **actually signed**
const payload = new Payload({ message: MESSAGE, nonce: CHALLENGE, recipient: APP, callbackUrl: cURL });
const borsh_payload = borsh.serialize(payloadSchema, payload);
const to_sign = Uint8Array.from(js_sha256.sha256.array(borsh_payload))

// Reconstruct the signature from the parameter given in the URL
let real_signature = Buffer.from(signature, 'base64')

// Use the public Key to verify that the private-counterpart signed the message
const myPK = naj.utils.PublicKey.from(publicKey)
return myPK.verify(to_sign, real_signature)
}

export async function verifyFullKeyBelongsToUser({ publicKey, accountId }) {
// Call the public RPC asking for all the users' keys
let data = await fetch_all_user_keys({ accountId })

// if there are no keys, then the user could not sign it!
if (!data || !data.result || !data.result.keys) return false

// check all the keys to see if we find the used_key there
for (const k in data.result.keys) {
if (data.result.keys[k].public_key === publicKey) {
// Ensure the key is full access, meaning the user had to sign
// the transaction through the wallet
return data.result.keys[k].access_key.permission == "FullAccess"
}
}

return false // didn't find it
}

// Aux method
async function fetch_all_user_keys({ accountId }) {
const keys = await fetch(
"https://rpc.testnet.near.org",
{
method: 'post',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body: `{"jsonrpc":"2.0", "method":"query", "params":["access_key/${accountId}", ""], "id":1}`
}).then(data => data.json()).then(result => result)
return keys
}

module.exports = { authenticate, verifyFullKeyBelongsToUser, verifySignature };
```
<Github fname="authenticate.js" language="javascript"
url="https://github.com/near-examples/near-api-examples/blob/main/javascript/examples/verify-signature/authentication.js" />
2 changes: 1 addition & 1 deletion docs/3.tutorials/near-components/bos-loader.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: BOS Loader

# BOS Loader

In this article you'll learn how to develop, test, and deploy BOS components using CLI tools. You can use this workflow to tap into the colaboration, pull-request, and other GitHub benefits while still deploying components to the BOS.
In this article you'll learn how to develop, test, and deploy BOS components using CLI tools. You can use this workflow to tap into the collaboration, pull-request, and other GitHub benefits while still deploying components to the BOS.

[BOS Component Loader](https://github.com/near/bos-loader) serves a local directory of component files as a JSON payload properly formatted to be plugged into a BOS `redirectMap`. When paired with a viewer configured to call out to this loader, it enables local component development.

Expand Down
16 changes: 16 additions & 0 deletions docs/4.tools/near-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,22 @@ When deleting an access key, you need to specify the public key of the key you w

---

## Validate Message Signatures

Users can sign messages using the `wallet-selector` `signMessage` method, which returns a signature. This signature can be verified using the following code:

<Tabs groupId="api">
<TabItem value="js" label="🌐 JavaScript">

<Github fname="authenticate.js" language="javascript"
url="https://github.com/near-examples/near-api-examples/blob/main/javascript/examples/verify-signature/authentication.js" />

</TabItem>
</Tabs>

---


## Utilities

### NEAR to yoctoNEAR {#near-to-yoctonear}
Expand Down

0 comments on commit 060dba4

Please sign in to comment.