-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.js
146 lines (126 loc) · 4.74 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
const express = require("express");
const cors = require("cors");
const { NativeAuthServer } = require("@multiversx/sdk-native-auth-server");
const app = express();
const port = 3000;
app.use(cors());
app.use(express.json());
const router = express.Router();
router.get("/health-check", (req, res) => {
res.set("Cache-control", `no-store`); // never cache this route
res.status(200).json({
version: "0.0.1",
health: "ok",
});
});
router.get("/datastream", async function (req, res) {
console.log("req.headers", req.headers);
res.set("Cache-control", `no-store`); // never cache this route
let accessToken = req.headers.authorization;
// Make sure the Native Auth token is sent
if (!accessToken) {
return res.status(403).json({
error: true,
errorMessage:
"Access Forbidden as this is a protected Data Stream. No credentials sent!",
});
}
// OPTIONAL, may be needed if you are using the Data NFT-PF standard and are NOT doing any Native Auth address + token ID validation.
// ... here we make sure the caller's NFT token ID is from your NFT collection
const callersNFTTokenID = req.headers["itm-marshal-fwd-tokenid"]; // caller's NFT token ID as sent by the Data Marshal network
const allowedNFTCollectionID = "DNFTPHNAUT-f3f22a"; // your collection ID
if (!callersNFTTokenID.includes(allowedNFTCollectionID)) {
return res.status(401).json({
error: true,
errorMessage:
"Access Forbidden as this is a protected Data Stream. Unsupported Data NFT-PH Collection!",
});
}
try {
// let's remove the Bearer from the string or server.decode gets confused
accessToken = accessToken.replace(/Bearer/gi, "").trim();
const server = new NativeAuthServer({
// configure as needed - see https://github.com/multiversx/mx-sdk-js-native-auth-server for more info
apiUrl: "https://devnet-api.multiversx.com",
maxExpirySeconds: 7200,
acceptedOrigins: [
"http://localhost:3000",
"http://localhost",
"https://utils.multiversx.com",
],
});
// decodes the accessToken in its components: ttl, origin, address, signature, blockHash & body
const decoded = await server.decode(accessToken);
// performs validation of the block hash, verifies its validity, as well as origin verification
const validateResult = await server.validate(accessToken);
// start to generate the personalized response (error by default)
let personalizedDataStream = {
error: true,
errorMessage:
"Personalized stream has not been constructed due to some runtime error.",
};
// if the validation results returns an address, then we know it's a valid session
// ... or else, .validate will throw an error that can be caught in catch
if (validateResult?.address) {
// a dummy personalized data stream, update with your own business logic here
personalizedDataStream = {
data_stream: {
name: `private stream for ${validateResult?.address}`,
creator: "you",
created_on: 1692571700,
last_modified_on: 1692571710,
generated_on: validateResult?.issued,
},
data: [
{
txId: 1001,
category: "purchase",
date: 1692571701,
item: "Gold Watch",
store: "Nice jewellers",
meta: `https://some_session_to_full_meta_data_of_transaction?txId=1001&user=${validateResult?.address}&session=${accessToken}`,
},
{
txId: 1000,
category: "purchase",
date: 1692571702,
item: "Small Cafe Latte",
store: "Corner Coffee Shop",
meta: `https://some_session_link_to_full_meta_data_of_transaction?txId=1000&user=${validateResult?.address}&session=${accessToken}`,
},
],
metaData: {
data_marshal_injected: {
"itm-marshal-fwd-chainid":
req.headers?.["itm-marshal-fwd-chainid"] ||
"error, this value should be forwarded",
"itm-marshal-fwd-tokenid":
req.headers?.["itm-marshal-fwd-tokenid"] ||
"error, this value should be forwarded",
},
mvx_native_auth: {
decodedSession: decoded,
validateSession: validateResult,
},
},
};
}
res.status(200).json(personalizedDataStream);
} catch (e) {
// all errors fall here into a 500 error code
console.error(e);
res.status(500).json({
error: true,
errorMessage: e.toString(),
});
}
});
app.use("/", router);
app.use((req, res, next) => {
return res.status(404).json({
error: "Not Found",
});
});
app.listen(port, () => {
console.log(`You API is running on ${port}`);
});