Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"child_process": "^1.0.2",
"compression": "1.7.4",
"connect-mongo": "4.4.0",
"cors": "^2.8.5",
"dotenv": "8.2.0",
"errorhandler": "1.5.1",
"express": "4.17.1",
Expand Down
9 changes: 9 additions & 0 deletions backend/scripts/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const CLIENT_CONFIG = {
network: "main",
node: "https://chrysalis-nodes.iota.org:443",
}

const EXPLORER_URL = "https://explorer.iota.org/mainnet/transaction";

exports.CLIENT_CONFIG = CLIENT_CONFIG;
exports.EXPLORER_URL = EXPLORER_URL;
27 changes: 27 additions & 0 deletions backend/scripts/create_did.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { Document, KeyType, publish } = require('@iota/identity-wasm/node');
const { CLIENT_CONFIG, EXPLORER_URL } = require('./config')

/*
This example shows a basic introduction on how to create a basic DID Document and upload it to the Tangle.
A ED25519 Keypair is generated, from which the public key is hashed, becoming the DID.
The keypair becomes part of the DID Document in order to prove a link between the DID and the published DID Document.
That same keypair should be used to sign the original DID Document.
*/
async function createIdentity() {
//Create a DID Document (an identity).
const { doc, key } = new Document(KeyType.Ed25519)

//Sign the DID Document with the generated key
doc.sign(key);

//Publish the Identity to the IOTA Network, this may take a few seconds to complete Proof-of-Work.
const messageId = await publish(doc.toJSON(), CLIENT_CONFIG);

//Log the results
console.log(`Identity Creation: ${EXPLORER_URL}/${messageId}`);

//Return the results
return {key, doc, messageId};
}

exports.createIdentity = createIdentity;
11 changes: 11 additions & 0 deletions backend/scripts/explorer_util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
Write out the Targle Explorer URL given the network and message ID, with the given preamble.
@param {!string} preamble
@param {!string} network
@param {!string} messageId
*/
function logExplorerUrl(preamble, network, messageId) {
console.log(`${preamble} https://explorer.iota.org/${network}net/transaction/${messageId}`);
}

exports.logExplorerUrl = logExplorerUrl;
71 changes: 71 additions & 0 deletions backend/scripts/fake_login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2020-2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

const { Network, defaultNodeURL, explorerURL, Client, Config, VerifiableCredential, checkCredential } = require('@iota/identity-wasm/node');

const { createIdentity } = require('./create_did');

/*
This example shows how to create a Verifiable Credential and validate it.
In this example, alice takes the role of the subject, while we also have an issuer.
The issuer signs a UniversityDegreeCredential type verifiable credential with Alice's name and DID.
This Verifiable Credential can be verified by anyone, allowing Alice to take control of it and share it with whoever they please.
@param {{network: string, node: string}} clientConfig
*/
async function createVC() {
//Creates new identities (See "create_did" and "manipulate_did" examples)
const alice = await createIdentity();

console.log("alice", alice)

// Prepare a credential subject indicating the degree earned by Alice
let credentialSubject = {
id: "did:iota:BTEg5it1b4BX8cGbTqwDpErgWet8jy73o6WPLGVYsk2Y", // LoginServer DID
name: "Alice",
};

// Create an unsigned `UniversityDegree` credential for Alice
const unsignedVc = VerifiableCredential.extend({
id: "http://example.edu/credentials/3732",
type: "LoginCredential",
issuer: alice.doc.id.toString(),
credentialSubject,
});

//Sign the credential with alice's newKey
try {
const signedVc = alice.doc.signCredential(unsignedVc, {
method: alice.doc.id.toString()+"#key",
public: alice.key.public,
secret: alice.key.secret,
});
//Check if the credential is verifiable
try {

const result = await checkCredential(signedVc.toString(), CLIENT_CONFIG);
console.log(`VC verification result: ${result.verified}`);
console.log(`signedVc: ${signedVc}`);
} catch (error) {

console.log(`error verification:`, error);
}

return { alice, signedVc };
} catch (error) {

console.log(`error signCredential:`, error);
}


}


const CLIENT_CONFIG = {
network: "main",
node: "https://chrysalis-nodes.iota.org:443",
}

const EXPLORER_URL = "https://explorer.iota.org/mainnet/transaction";


createVC(CLIENT_CONFIG)
24 changes: 22 additions & 2 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,30 @@ import treeRoutes from './routes/treeRoutes';
import { errorHandler } from './middleware/errors';
import { createFakeUsers } from './data/seeder';

var cors = require('cors');

// Create Express server
const app = express();


var allowedOrigins = [
'http://localhost:3000',
'http://app.trees'];

app.use(cors({
origin: function (origin: any, callback: any) {
// allow requests with no origin
// (like mobile apps or curl requests)
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) === -1) {
var msg = 'The CORS policy for this site does not ' +
'allow access from the specified Origin.';
return callback(new Error(msg), false);
}
return callback(null, true);
}
}));

// Connect to MongoDB
const mongoUrl = MONGODB_URI || "mongodb://localhost:27017/local";

Expand All @@ -40,10 +60,10 @@ app.use('/api/trees', treeRoutes);
app.use(errorHandler);

app.use("/",
express.static(path.join(__dirname,"../../frontend/build/"), { maxAge: 31557600000 })
express.static(path.join(__dirname, "../../frontend/build/"), { maxAge: 31557600000 })
);

app.get('*', (req,res) =>{
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../../frontend/build/index.html'));
});

Expand Down
46 changes: 45 additions & 1 deletion backend/src/controllers/userControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import asyncHandler from "express-async-handler";
import { User } from '../models/User';
import { Request, Response } from 'express';
import { tokenize } from '../util/jwt';
import { authenticate } from '../util/did';
import console from "console";

const userLogin = asyncHandler(async (req: Request, res: Response) => {
interface IUserLoginProps {
Expand All @@ -29,4 +31,46 @@ const userLogin = asyncHandler(async (req: Request, res: Response) => {
}
});

export { userLogin };

// Login method with IOTA Identity
const userLoginDID = asyncHandler(async (req: Request, res: Response) => {

const credential = req.body;

console.log("credential", credential)

let response: any = {}
response = await authenticate(credential)
console.log("response", response)

if (response.result.verified) {

// check if credential is new

var issuanceDate = new Date(response.result.credential.issuanceDate).getTime();
var nowDate = new Date().getTime();
var withinRange = nowDate - issuanceDate

console.log("issuanceDate", issuanceDate)
console.log("nowDate", nowDate)
console.log("withinRange", withinRange)

if (withinRange <= 10000) {
console.log("authenticate success!")

const token: string = tokenize("user._id");
res.json({
token
});
} else {
res.json({
error: "credential to old"
});
}
} else {
res.status(403);
throw new Error('Incorrect credential');
}
});

export { userLogin, userLoginDID };
4 changes: 3 additions & 1 deletion backend/src/routes/userRoutes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import express from 'express';
import {
userLogin
userLogin,
userLoginDID
} from '../controllers/userControllers';
const router = express.Router();

router.route('/login').post(userLogin);
router.route('/login_did').post(userLoginDID);

export default router;
29 changes: 28 additions & 1 deletion backend/src/util/did.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const identity = require('@iota/identity-wasm/node');
const { checkCredential } = require('@iota/identity-wasm/node');

const createDID = async () => {
const key = new identity.KeyPair(identity.KeyType.Ed25519);
Expand All @@ -17,5 +18,31 @@ const createDID = async () => {
};
};

const CLIENT_CONFIG = {
network: "main",
node: "https://chrysalis-nodes.iota.org:443",
}

module.exports = { createDID };
const authenticate = async (credential) => {


console.log("authenticate", credential)
// const result = await client.checkCredential(credential.toString());
try {
const result = await checkCredential(JSON.stringify(credential), CLIENT_CONFIG);
console.log("result", result)

console.log(`VC verification result: ${result.verified}`);

return {
result
};
} catch (error) {
console.log("error authenticate", error)

}

};


module.exports = { createDID, authenticate };
26 changes: 24 additions & 2 deletions docs/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,18 @@ module.exports = {
position: 'left',
label: 'Docs',
},
{to: '/blog', label: 'Blog', position: 'left'},
{ to: '/blog', label: 'Blog', position: 'left' },
{
href: 'https://github.com/IdentiTree/documentation',
label: 'GitHub',
position: 'right',
},
{
to: "api/",
activeBasePath: "api",
label: "API",
position: "left",
}
],
},
footer: {
Expand Down Expand Up @@ -105,5 +111,21 @@ module.exports = {
},
},
],
],
[
'redocusaurus',
{
debug: Boolean(process.env.DEBUG || process.env.CI),
specs: [
{
spec: 'openapi.yaml',
routePath: '/api/',
},
],
theme: {
// primaryColor: '#1890ff',
redocOptions: { hideDownloadButton: false },
},
},
],
]
};
Loading