Skip to content

Commit 5298361

Browse files
authored
Merge pull request #34 from Azure-Samples/yoelhor-dev
Adding the todolist endpoints
2 parents 3a239c7 + 6719b25 commit 5298361

File tree

4 files changed

+156
-9
lines changed

4 files changed

+156
-9
lines changed

config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
},
1717
"settings": {
1818
"isB2C": true,
19-
"validateIssuer": false,
19+
"validateIssuer": true,
2020
"passReqToCallback": false,
2121
"loggingLevel": "info"
2222
}

index.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ const express = require('express');
22
const morgan = require('morgan');
33
const passport = require('passport');
44
const config = require('./config.json');
5-
5+
const todolist = require('./todolist');
6+
const cors = require('cors');
67
const BearerStrategy = require('passport-azure-ad').BearerStrategy;
78

9+
10+
global.global_todos = [];
11+
812
const options = {
913
identityMetadata: `https://${config.credentials.tenantName}.b2clogin.com/${config.credentials.tenantName}.onmicrosoft.com/${config.policies.policyName}/${config.metadata.version}/${config.metadata.discovery}`,
1014
clientID: config.credentials.clientID,
@@ -24,30 +28,37 @@ const bearerStrategy = new BearerStrategy(options, (token, done) => {
2428

2529
const app = express();
2630

31+
app.use(express.json());
32+
33+
//enable CORS (for testing only -remove in production/deployment)
34+
app.use(cors({
35+
origin: '*'
36+
}));
37+
2738
app.use(morgan('dev'));
2839

2940
app.use(passport.initialize());
3041

3142
passport.use(bearerStrategy);
3243

33-
//enable CORS (for testing only -remove in production/deployment)
34-
app.use((req, res, next) => {
35-
res.header('Access-Control-Allow-Origin', '*');
36-
res.header('Access-Control-Allow-Headers', 'Authorization, Origin, X-Requested-With, Content-Type, Accept');
37-
next();
38-
});
44+
// To do list endpoints
45+
app.use('/api/todolist', todolist);
3946

4047
// API endpoint
4148
app.get('/hello',
4249
passport.authenticate('oauth-bearer', {session: false}),
4350
(req, res) => {
4451
console.log('Validated claims: ', req.authInfo);
45-
52+
53+
4654
// Service relies on the name claim.
4755
res.status(200).json({'name': req.authInfo['name']});
4856
}
4957
);
5058

59+
// API anonymous endpoint
60+
app.get('/public', (req, res) => res.send( {'date': new Date() } ));
61+
5162
const port = process.env.PORT || 5000;
5263

5364
app.listen(port, () => {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"dev": "nodemon index.js"
1313
},
1414
"dependencies": {
15+
"cors": "^2.8.5",
1516
"express": "^4.14.0",
1617
"morgan": "^1.7.0",
1718
"passport": "^0.4.1",

todolist.js

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/**
2+
IMPORTANT: This sample code is not production ready. It's only intended as an example of how validate Azure
3+
AD B2C bearer token (this part can be used in production environments). The to do list methods in this module:
4+
- Do NOT validate user input and query string parameters.
5+
- The global_todos is a global variable (local memory) without using lock mechanism.
6+
- The CORS settings allow ANY origin.
7+
- Some of the methods do NOT validate the caller ID. For example, the deleted method.
8+
- Never tested for security, performances and usability.
9+
**/
10+
11+
const express = require('express');
12+
const morgan = require('morgan');
13+
const passport = require('passport');
14+
const config = require('./config.json')
15+
16+
var router = express.Router();
17+
18+
const BearerStrategy = require('passport-azure-ad').BearerStrategy;
19+
20+
const options = {
21+
identityMetadata: `https://${config.credentials.tenantName}.b2clogin.com/${config.credentials.tenantName}.onmicrosoft.com/${config.policies.policyName}/${config.metadata.version}/${config.metadata.discovery}`,
22+
clientID: config.credentials.clientID,
23+
audience: config.credentials.clientID,
24+
policyName: config.policies.policyName,
25+
isB2C: config.settings.isB2C,
26+
validateIssuer: config.settings.validateIssuer,
27+
loggingLevel: config.settings.loggingLevel,
28+
passReqToCallback: config.settings.passReqToCallback
29+
}
30+
31+
const bearerStrategy = new BearerStrategy(options, (token, done) => {
32+
// Send user info using the second argument
33+
done(null, {}, token);
34+
}
35+
);
36+
37+
// Get the caller to do list.
38+
// GET: api/TodoItems
39+
router.get('/',
40+
passport.authenticate('oauth-bearer', { session: false }),
41+
(req, res) => {
42+
console.log('Validated claims: ', req.authInfo);
43+
44+
// Get the caller to do list
45+
var todos = getCallerTodos(req);
46+
47+
// Return the caller to do list
48+
res.status(200).json(todos);
49+
}
50+
);
51+
52+
// Get a single item from the caller to do list.
53+
// GET: api/TodoItems
54+
router.get('/*',
55+
passport.authenticate('oauth-bearer', { session: false }),
56+
(req, res) => {
57+
console.log('Validated claims: ', req.authInfo);
58+
59+
// Get the caller to do list
60+
var todos = getCallerTodos(req);
61+
62+
// Find the item by id from the caller to do list
63+
var item = todos.find(item => item.id === parseInt(req.params[0]));
64+
65+
// Return the selected item
66+
res.status(200).json(item);
67+
}
68+
);
69+
70+
// Add a new item to the global to do list
71+
// POST: api/TodoItems
72+
router.post('/', passport.authenticate('oauth-bearer', { session: false }),
73+
(req, res) => {
74+
75+
// Get the max ID from the global to do list
76+
var maxId = 1;
77+
if (global_todos.length > 0)
78+
maxId = Math.max.apply(Math, global_todos.map(function (item) { return item.id; })) + 1;
79+
80+
// Create new item and add it to the global to do list
81+
var item = { "id": maxId, "owner": req.authInfo['sub'], "description": req.body.description, "status": false };
82+
global_todos.push(item);
83+
84+
// Return the new item
85+
res.status(200).json(item);
86+
}
87+
);
88+
89+
// Update an item
90+
// PUT: api/TodoItems/5
91+
router.put('/*',
92+
passport.authenticate('oauth-bearer', { session: false }),
93+
(req, res) => {
94+
console.log('Validated claims: ', req.authInfo);
95+
96+
// Get the caller to do list
97+
var todos = getCallerTodos(req);
98+
99+
// Find the item by id from the caller to do list
100+
var item = todos.find(item => item.id === parseInt(req.body.id));
101+
item.description = req.body.description;
102+
item.status = req.body.status;
103+
104+
// Return the selected item
105+
res.status(200).json(item);
106+
}
107+
);
108+
109+
// Delate an item
110+
// DELETE: api/TodoItems/5
111+
router.delete('/*',
112+
passport.authenticate('oauth-bearer', { session: false }),
113+
(req, res) => {
114+
console.log('Validated claims: ', req.authInfo);
115+
116+
// Find the item by id from the global to do list
117+
var item = global_todos.find(item => item.id === parseInt(req.params[0]));
118+
119+
// Find the item index in the global to do list
120+
let pos = global_todos.findIndex(item => item.id === parseInt(req.params[0]));
121+
122+
// Remove the item from the global list
123+
global_todos.splice(pos, 1)
124+
125+
// Return the selected item
126+
res.status(200).json(item);
127+
}
128+
);
129+
130+
// Return the caller items
131+
function getCallerTodos(req) {
132+
return global_todos.filter(item => item.owner === req.authInfo['sub']);
133+
}
134+
135+
module.exports = router;

0 commit comments

Comments
 (0)