-
Notifications
You must be signed in to change notification settings - Fork 360
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
12,130 additions
and
5,105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
--- | ||
id: backend-login | ||
title: Login with NEAR | ||
--- | ||
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. | ||
|
||
--- | ||
|
||
## Backend Auth with a NEAR Wallet | ||
Authenticating users is a common use-case for backends and web applications. This enables services to provide a personalized experience to users, and to protect sensitive data. | ||
|
||
To authenticate a user, the backend must verify that the user is who they say they are. To do so, the backend must verify that the user has access to a full-access key that is associated with their account. | ||
|
||
For this three basic steps are needed: | ||
|
||
1. Create a challenge for the user to sign. | ||
2. Ask the user to sign the challenge with the wallet. | ||
3. Verify the signature corresponds to the user. | ||
|
||
### 1. Create a Challenge | ||
Assume we want to login the user into our application named `application-name`. | ||
|
||
We first need to create a challenge that the user will sign with their wallet. For this, it is recommended to use a cryptographically secure random number generator to create the challenge. | ||
|
||
```js | ||
import { randomBytes } from 'crypto' | ||
const challenge = randomBytes(32) | ||
const message = 'Login with NEAR' | ||
``` | ||
|
||
:::note | ||
Here we use [crypto.randomBytes](https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) to generate a 32 byte random buffer. | ||
::: | ||
|
||
### 2. Ask the User to Sign the Challenge | ||
As of today only [Meteor Wallet](https://meteorwallet.app) supports the `signMessage` method needed to sign the challenge. However, we expect more wallets to support this method in the future. | ||
|
||
The message that the user needs to sign contains 4 fields: | ||
- Message: The message that the user is signing. | ||
- Recipient: The recipient of the message. | ||
- Nonce: The challenge that the user is signing. | ||
- Callback URL: The URL that the wallet will call with the signature. | ||
|
||
```js | ||
// Assuming you setup a wallet selector so far | ||
const signature = wallet.signMessage({ message, recipient, nonce: challenge, callbackUrl: <server-auth-url> }) | ||
``` | ||
|
||
### 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") | ||
|
||
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 }; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
--- | ||
id: quickstart-frontend | ||
title: Hello NEAR 👋 | ||
sidebar_label: ⭐ Quickstart | ||
--- | ||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
import {CodeTabs, Language, Github} from "@site/components/codetabs" | ||
|
||
Hi! Let us guide you in starting and interacting with your first decentralized app (dApp) in NEAR: Hello NEAR. | ||
|
||
**Hello NEAR** is a friendly dApp composed by two main components: | ||
1. A smart contract that stores and retrieves a greeting message | ||
2. A simple web-based frontend that displays the greeting and enables to change it. | ||
|
||
--- | ||
|
||
## Create NEAR App | ||
If you already have [Node.js](https://nodejs.org/en/download) installed, simply run: | ||
|
||
```bash | ||
npx create-near-app@latest | ||
``` | ||
|
||
Use the interactive menu to set up your first project folder, we recommend you to use `javascript`. | ||
|
||
Once the folder is ready, check the README. It will show you how to **build** and **deploy** the smart contract, and **start** the frontend. | ||
|
||
```bash | ||
npm run build | ||
npm start | ||
``` | ||
|
||
<details> | ||
<summary> | ||
Test it online with Gitpod | ||
</summary> | ||
|
||
A new browser window will open automatically with the code, give it a minute and the frontend will pop-up (make sure the pop-up window is not blocked). | ||
|
||
|
||
| 🌐 JavaScript | 🦀 Rust | | ||
|----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------| | ||
| <a href="https://gitpod.io/#https://github.com/near-examples/hello-near-js.git">Open in Gitpod</a> | <a href="https://gitpod.io/#https://github.com/near-examples/hello-near-rs.git">Open in Gitpod</a> | | ||
|
||
</details> | ||
|
||
--- | ||
|
||
## Interacting With Hello NEAR | ||
|
||
Once the app starts you will see the screen below. Now go ahead and sign in with your NEAR account. If you don't have one, you will be able to create one in the moment. | ||
|
||
![img](/docs/assets/examples/hello-near.png) | ||
*Frontend of Hello NEAR* | ||
|
||
Once logged in, change the greeting and see how our Hello NEAR app greets you! | ||
|
||
|
||
--- | ||
|
||
## Structure of a dApp | ||
|
||
Now that you understand what the dApp does, let us take a closer look to its structure: | ||
|
||
1. The frontend code lives in the `/frontend` folder. | ||
2. The smart contract code is in the `/contract` folder. | ||
3. The compiled smart contract can be found in `/out/main.wasm`. | ||
4. The account's name in which the contract was deployed is in `/neardev/dev-account`. | ||
|
||
### Frontend | ||
The frontend is composed by a single HTML file (`frontend/index.html`). This file defines the components displayed in the screen. | ||
|
||
The website's logic lives in `frontend/index.js`, which communicates with the contract through `frontend/near-interface.js`. You will notice in `/frontend/index.js` the following code: | ||
|
||
<CodeTabs> | ||
<Language value="🌐 JavaScript" language="js"> | ||
<Github fname="index.js" | ||
url="https://github.com/near-examples/hello-near-js/blob/master/frontend/index.js" | ||
start="11" end="21" /> | ||
</Language> | ||
</CodeTabs> | ||
|
||
It indicates our app, when it starts, to check if the user is already logged in and execute either `signedInFlow()` or `signedOutFlow()`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
--- | ||
id: welcome | ||
title: Build Web3 Applications | ||
sidebar_label: Home | ||
hide_table_of_contents: true | ||
--- | ||
import {FeatureList, Column, Feature} from "@site/components/featurelist" | ||
import ContactUs from '@site/components/ContactUs.mdx'; | ||
|
||
|
||
Welcome! Here you will find documentation on how to build Web3 applications using NEAR. What are you planning to build? | ||
|
||
<div class="container"> | ||
<div class="row"> | ||
<div class="col col--3"> | ||
<a href="/bos"> | ||
<div class="card"> | ||
<div class="card__image"> | ||
<img src={require("@site/static/docs/assets/welcome-pages/bos-big.png").default} alt="Multichain" /> | ||
</div> | ||
<div class="card__body"> | ||
<h3>Composable Apps</h3> | ||
Simple multi-chain apps. | ||
</div> | ||
</div> | ||
</a> | ||
</div> | ||
<div class="col col--3"> | ||
<a href="/develop/contracts/welcome"> | ||
<div class="card"> | ||
<div class="card__image"> | ||
<img src={require("@site/static/docs/assets/welcome-pages/web-app.png").default} alt="Contracts" /> | ||
</div> | ||
<div class="card__body"> | ||
<h3>WebApp Integration</h3> | ||
Add NEAR to a WebApp. | ||
</div> | ||
</div> | ||
</a> | ||
</div> | ||
<div class="col col--3"> | ||
<a href="/develop/relayers/build-relayer"> | ||
<div class="card"> | ||
<div class="card__image"> | ||
<img src={require("@site/static/docs/assets/welcome-pages/relayer.png").default} alt="Relayers" /> | ||
</div> | ||
<div class="card__body"> | ||
<h3>Relayers</h3> | ||
Cover GAS for your users. | ||
</div> | ||
</div> | ||
</a> | ||
</div> | ||
<div class="col col--3"> | ||
<a href="/develop/integrate/backend-login"> | ||
<div class="card"> | ||
<div class="card__image"> | ||
<img src={require("@site/static/docs/assets/welcome-pages/backend.png").default} alt="Learn" /> | ||
</div> | ||
<div class="card__body"> | ||
<h3>Backend Integration</h3> | ||
Use NEAR in your server. | ||
</div> | ||
</div> | ||
</a> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
|
||
<FeatureList> | ||
<Column title="Build dApps"> | ||
<Feature url="/develop/quickstart-guide" title="Quickstart" subtitle="Spin-up your first dApp" image="quickstart.png" highlight="true" /> | ||
<Feature url="/tutorials/welcome" title="Tutorials & Examples" subtitle="Check-out a vast library of examples" image="tutorials.png" /> | ||
<Feature url="/develop/contracts/introduction" title="Build a Contract" subtitle="Learn how to write smart contracts" image="smartcontract.png" /> | ||
<Feature url="/develop/testing/introduction" title="Test the Contract" subtitle="Write unit & integration tests" image="test.png" /> | ||
<Feature url="/develop/integrate/frontend" title="Build a Web Frontend" subtitle="Learn how to make a web dApp" image="frontend.png" /> | ||
<Feature url="/tools/realtime" title="Track Your Users Activity" subtitle="Learn how to use Indexers" image="monitor.png" /> | ||
</Column> | ||
<Column title="Developer Tools"> | ||
<Feature url="/sdk/js/introduction" title="Javascript SDK" subtitle="Write Contracts in Javascript" image="smartcontract-js.png" /> | ||
<Feature url="/sdk/rust/introduction" title="Rust SDK" subtitle="Write Contracts in Rust" image="smartcontract-rust.png" /> | ||
<Feature url="/tools/near-cli" title="NEAR CLI" subtitle="Use NEAR from the Terminal" image="near-cli.png" /> | ||
<Feature url="/tools/near-api-js/quick-reference" title="NEAR API JS" subtitle="Interact with NEAR from JS" image="near-api-js.png" /> | ||
<Feature url="/api/rpc/introduction" title="RPC API" subtitle="Interact with the NEAR RPC API" image="rpc.png" /> | ||
<Feature url="/tools/indexer-for-explorer" title="Indexer for Explorer" subtitle="Query usage information for a contract" image="blocks.png" /> | ||
</Column> | ||
<Column title="Unleash the Web3"> | ||
<Feature url="/develop/relevant-contracts/ft" title="Fungible Tokens" subtitle="Learn how to use and make FT" image="ft.png" /> | ||
<Feature url="/develop/relevant-contracts/nft" title="Non-Fungible Tokens" subtitle="Enter the NFT space" image="nft.png" /> | ||
<Feature url="/develop/relevant-contracts/dao" title="Autonomous Organizations" subtitle="Understand DAOs" image="dao.png" /> | ||
<Feature url="/develop/relevant-contracts/oracles" title="Oracles" subtitle="Supercharge your app with on-chain oracles" image="oracle.png" /> | ||
<Feature url="https://rainbowbridge.app/transfer" title="Rainbow Bridge" subtitle="Bridge assets with other chains" image="rainbow.png" /> | ||
<Feature url="https://aurora.dev" title="Aurora EVM" subtitle="Run Ethereum apps natively" image="aurora.png" /> | ||
</Column> | ||
</FeatureList> | ||
|
||
<br/> | ||
|
||
--- | ||
|
||
<ContactUs /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.