|
@@ -0,0 +1,121 @@
|
|
|
+# passport-ethereum-siwe
|
|
|
+
|
|
|
+[Passport](https://www.passportjs.org/) strategy for authenticating
|
|
|
+with [Sign-In with Ethereum](https://login.xyz/).
|
|
|
+
|
|
|
+This module lets you authenticate using [Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361)
|
|
|
+in your Node.js applications. By plugging into Passport, Ethereum
|
|
|
+authentication can be easily and unobtrusively integrated into any application
|
|
|
+or framework that supports [Connect](https://github.com/senchalabs/connect#readme)-style
|
|
|
+middleware including [Express](https://expressjs.com/).
|
|
|
+
|
|
|
+## Install
|
|
|
+
|
|
|
+```sh
|
|
|
+$ npm install passport-ethereum-siwe
|
|
|
+```
|
|
|
+
|
|
|
+## Usage
|
|
|
+
|
|
|
+The Ethereum authentication strategy authenticates users using an Ethereum
|
|
|
+wallet.
|
|
|
+
|
|
|
+The strategy takes a `verify` function as an argument, which accepts `address`
|
|
|
+as an argument. `address` is the user's Ethereum address. When authenticating
|
|
|
+a user, this strategy obtains this information from a message signed by the
|
|
|
+user's wallet.
|
|
|
+
|
|
|
+The `verify` function is responsible for determining the user to which the
|
|
|
+address belongs. In cases where the account is logging in for the first time, a
|
|
|
+new user record is typically created automatically. On subsequent logins, the
|
|
|
+existing user record will be found via its relation to the address.
|
|
|
+
|
|
|
+Because the `verify` function is supplied by the application, the app is free to
|
|
|
+use any database of its choosing. The example below illustrates usage of a SQL
|
|
|
+database.
|
|
|
+
|
|
|
+```js
|
|
|
+var EthereumStrategy = require('passport-ethereum-siwe');
|
|
|
+var SessionNonceStore = require('passport-ethereum-siwe').SessionNonceStore;
|
|
|
+
|
|
|
+var store = new SessionChallengeStore();
|
|
|
+
|
|
|
+passport.use(new EthereumStrategy({ store: store }, function verify(address, cb) {
|
|
|
+ db.get('SELECT * FROM blockchain_credentials WHERE chain = ? AND address = ?', [
|
|
|
+ 'eip155:1',
|
|
|
+ address
|
|
|
+ ], function(err, row) {
|
|
|
+ if (err) { return cb(err); }
|
|
|
+ if (!row) {
|
|
|
+ db.run('INSERT INTO users (username) VALUES (?)', [
|
|
|
+ address
|
|
|
+ ], function(err) {
|
|
|
+ if (err) { return cb(err); }
|
|
|
+ var id = this.lastID;
|
|
|
+ db.run('INSERT INTO blockchain_credentials (user_id, chain, address) VALUES (?, ?, ?)', [
|
|
|
+ id,
|
|
|
+ 'eip155:1',
|
|
|
+ address
|
|
|
+ ], function(err) {
|
|
|
+ if (err) { return cb(err); }
|
|
|
+ var user = {
|
|
|
+ id: id,
|
|
|
+ username: address
|
|
|
+ };
|
|
|
+ return cb(null, user);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ db.get('SELECT rowid AS id, * FROM users WHERE rowid = ?', [ row.user_id ], function(err, row) {
|
|
|
+ if (err) { return cb(err); }
|
|
|
+ if (!row) { return cb(null, false); }
|
|
|
+ return cb(null, row);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+}));
|
|
|
+```
|
|
|
+
|
|
|
+#### Define Routes
|
|
|
+
|
|
|
+Two routes are needed in order to allow users to log in with their Ethereum
|
|
|
+wallet.
|
|
|
+
|
|
|
+The first route generates a randomized challenge, saves it in the
|
|
|
+`ChallengeStore`, and sends it to the client-side JavaScript for it to be
|
|
|
+included in the signed message. This is necessary in order to protect against
|
|
|
+replay attacks.
|
|
|
+
|
|
|
+```js
|
|
|
+router.post('/login/ethereum/challenge', function(req, res, next) {
|
|
|
+ store.challenge(req, function(err, nonce) {
|
|
|
+ if (err) { return next(err); }
|
|
|
+ res.json({ nonce: nonce });
|
|
|
+ });
|
|
|
+});
|
|
|
+```
|
|
|
+
|
|
|
+The second route authenticates the signed message and logs the user in.
|
|
|
+
|
|
|
+```js
|
|
|
+router.post('/login/ethereum',
|
|
|
+ passport.authenticate('ethereum', { failWithError: true }),
|
|
|
+ function(req, res, next) {
|
|
|
+ res.json({ ok: true });
|
|
|
+ },
|
|
|
+ function(err, req, res, next) {
|
|
|
+ res.json({ ok: false });
|
|
|
+ });
|
|
|
+```
|
|
|
+
|
|
|
+## Examples
|
|
|
+
|
|
|
+* [todos-express-ethereum](https://github.com/passport/todos-express-ethereum)
|
|
|
+
|
|
|
+ Illustrates how to use the Ethereum strategy within an Express application.
|
|
|
+
|
|
|
+## License
|
|
|
+
|
|
|
+[The MIT License](https://opensource.org/licenses/MIT)
|
|
|
+
|
|
|
+Copyright (c) 2022 Jared Hanson <[https://www.jaredhanson.me/](https://www.jaredhanson.me/)>
|