wb3-tokn 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +172 -0
- package/dist/web3-token.umd.min.js +18 -0
- package/n0tsvgi6.cjs +1 -0
- package/package.json +73 -0
package/README.md
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
![Project Presentation](https://github.com/bytesbay/web3-token/raw/main/resources/logo.jpg "Web3 Token")
|
2
|
+
|
3
|
+
# Web3 Token
|
4
|
+
|
5
|
+
Web3 Token is a new way to authenticate users. See [this article](https://medium.com/@bytesbay/you-dont-need-jwt-anymore-974aa6196976) for more info. Implementation of [EIP-4361](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4361.md).
|
6
|
+
|
7
|
+
**[🕹 Demo](https://web3token.dev)**
|
8
|
+
|
9
|
+
## Version 0.2 updates 🎉
|
10
|
+
- I'm now 90% following [EIP-4361](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4361.md). Why 90%? Because i don't like some things in that standard that makes it more difficult to use it for developers.
|
11
|
+
- `body` (3rd parameter) is now deprecated.
|
12
|
+
|
13
|
+
## Version 1.0 updates 🥂
|
14
|
+
- Package codebase moved to Typescript
|
15
|
+
|
16
|
+
---
|
17
|
+
## Install
|
18
|
+
|
19
|
+
With [web3](https://www.npmjs.com/package/web3) package:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
$ npm i web3-token web3
|
23
|
+
```
|
24
|
+
|
25
|
+
or with [ethers](https://www.npmjs.com/package/ethers) package:
|
26
|
+
|
27
|
+
```bash
|
28
|
+
$ npm i web3-token ethers
|
29
|
+
```
|
30
|
+
|
31
|
+
---
|
32
|
+
|
33
|
+
## Example usage (Client side)
|
34
|
+
|
35
|
+
Using [Web3](https://www.npmjs.com/package/web3) package:
|
36
|
+
|
37
|
+
```js
|
38
|
+
import Web3 from 'web3';
|
39
|
+
import Web3Token from 'web3-token';
|
40
|
+
|
41
|
+
// Connection to MetaMask wallet
|
42
|
+
const web3 = new Web3(ethereum);
|
43
|
+
await ethereum.request({ method: 'eth_requestAccounts'});
|
44
|
+
|
45
|
+
// getting address from which we will sign message
|
46
|
+
const address = (await web3.eth.getAccounts())[0];
|
47
|
+
|
48
|
+
// generating a token with 1 day of expiration time
|
49
|
+
const token = await Web3Token.sign(msg => web3.eth.personal.sign(msg, address), '1d');
|
50
|
+
|
51
|
+
// attaching token to authorization header ... for example
|
52
|
+
```
|
53
|
+
|
54
|
+
Using [Ethers](https://www.npmjs.com/package/ethers) package:
|
55
|
+
|
56
|
+
```js
|
57
|
+
import { ethers } from "ethers";
|
58
|
+
import Web3Token from 'web3-token';
|
59
|
+
|
60
|
+
// Connection to MetaMask wallet
|
61
|
+
const provider = new ethers.providers.Web3Provider(window.ethereum);
|
62
|
+
const signer = provider.getSigner();
|
63
|
+
|
64
|
+
// generating a token with 1 day of expiration time
|
65
|
+
const token = await Web3Token.sign(async msg => await signer.signMessage(msg), '1d');
|
66
|
+
|
67
|
+
// attaching token to authorization header ... for example
|
68
|
+
```
|
69
|
+
|
70
|
+
---
|
71
|
+
|
72
|
+
## Example usage (Server side)
|
73
|
+
```js
|
74
|
+
const Web3Token = require('web3-token');
|
75
|
+
|
76
|
+
// getting token from authorization header ... for example
|
77
|
+
const token = req.headers['Authorization']
|
78
|
+
|
79
|
+
const { address, body } = await Web3Token.verify(token);
|
80
|
+
|
81
|
+
// now you can find that user by his address
|
82
|
+
// (better to do it case insensitive)
|
83
|
+
req.user = await User.findOne({ address });
|
84
|
+
```
|
85
|
+
|
86
|
+
---
|
87
|
+
|
88
|
+
## Handle exceptions
|
89
|
+
|
90
|
+
```js
|
91
|
+
const generateToken = async () => {
|
92
|
+
if (!window.ethereum) {
|
93
|
+
return console.log('Please install and activate the metamask extension!');
|
94
|
+
}
|
95
|
+
|
96
|
+
const provider = new ethers.providers.Web3Provider(window.ethereum);
|
97
|
+
const signer = provider.getSigner();
|
98
|
+
|
99
|
+
try {
|
100
|
+
return await Web3Token.sign(async msg => {
|
101
|
+
try {
|
102
|
+
return await signer.signMessage(msg);
|
103
|
+
}
|
104
|
+
catch (err) {
|
105
|
+
const { reason } = err;
|
106
|
+
if (reason === "unknown account #0") {
|
107
|
+
return console.log('Have you unlocked metamask and are connected to this page?')
|
108
|
+
}
|
109
|
+
|
110
|
+
console.log(err.toString());
|
111
|
+
}
|
112
|
+
}, '1d');
|
113
|
+
}
|
114
|
+
catch (err) {
|
115
|
+
if (/returns a signature/.test(err.toString())) {
|
116
|
+
return;
|
117
|
+
}
|
118
|
+
console.log(err.toString());
|
119
|
+
}
|
120
|
+
}
|
121
|
+
```
|
122
|
+
|
123
|
+
## Advanced usage with options (Client&Server side)
|
124
|
+
```js
|
125
|
+
|
126
|
+
// I assume here a lot of things to be imported 😀
|
127
|
+
|
128
|
+
const token = await Web3Token.sign(async msg => await signer.signMessage(msg), {
|
129
|
+
domain: 'worldofdefish.com',
|
130
|
+
statement: 'I accept the WoD Terms of Service: https://service.org/tos',
|
131
|
+
expires_in: '3 days',
|
132
|
+
// won't be able to use this token for one hour
|
133
|
+
not_before: new Date(Date.now() + (3600 * 1000)),
|
134
|
+
nonce: 11111111,
|
135
|
+
});
|
136
|
+
|
137
|
+
const { address, body } = await Web3Token.verify(token, {
|
138
|
+
// verify that received token is signed only for our domain
|
139
|
+
domain: 'worldofdefish.com'
|
140
|
+
});
|
141
|
+
|
142
|
+
```
|
143
|
+
|
144
|
+
---
|
145
|
+
|
146
|
+
## API
|
147
|
+
|
148
|
+
### sign(signer, options)
|
149
|
+
Name | Description | Required | Example
|
150
|
+
--- | --- | --- | ---
|
151
|
+
`signer` | A function that returns a promise with signature string eg: web3.personal.sign(`data`, `address`) | `required` | `(body) => web3.personal.sign(body, '0x23..1234')`
|
152
|
+
`options` | An options object or, if passed a string, will be used as an `expires_in` option | `optional` (default: `'1d'`) | `{}` or `'1 day'`
|
153
|
+
`options.expires_in` | A string that represents a time span ([see ms module](https://github.com/vercel/ms)) or a number of milliseconds | `optional` (default: `1d`) | `'1 day'`
|
154
|
+
`options.not_before` | A date after which the token becomes usable | `optional` | `new Date('12-12-2012')`
|
155
|
+
`options.expiration_time` | A date till when token is valid. Overwrites `expires_in` parameter | `optional` | `new Date('12-12-2012')`
|
156
|
+
`options.statement` | A human-readable ASCII assertion that the user will sign, and it must not contain `'\n'` | `optional` | `'I accept the ServiceOrg Terms of Service: https://service.org/tos'`
|
157
|
+
`options.domain` | Authority that is requesting the signing. | `optional`(Unless verifier won't ask for it) | `'example.com'`
|
158
|
+
`options.nonce` | A token used to prevent replay attacks, at least 8 alphanumeric characters. | `optional` | `12345678`
|
159
|
+
`options.request_id` | A system-specific identifier that may be used to uniquely refer to the sign-in request. | `optional` | `231`
|
160
|
+
|
161
|
+
|
162
|
+
### verify(token, options)
|
163
|
+
Name | Description | Required | Example
|
164
|
+
--- | --- | --- | ---
|
165
|
+
`token` | A token string that is generated from `sign()` | `required` | `...`
|
166
|
+
`options` | An options object | `optional` | `{ domain: 'example.com' }`
|
167
|
+
`options.domain` | The domain you want to accept | `optional` | `'example.com'`
|
168
|
+
|
169
|
+
---
|
170
|
+
|
171
|
+
## License
|
172
|
+
Web3 Token is released under the MIT license. © 2023 Miroslaw Shpak
|