markdown 挑战20测试JWT
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown 挑战20测试JWT相关的知识,希望对你有一定的参考价值。
# Challenge - Testing JWTs and Protected Endpoints
In this challenge you will update integration tests to support to test JWT authorization. You can use the [Node JWT Auth](https://github.com/Thinkful-Ed/node-jwt-auth) as a guide.
## Access Protected Endpoint
Chia-Http makes accessing endpoints protected by JWTs is relatively easy. Simply create a valid JWT using the site's `JWT_SECRET` and add it as a Bearer token to each request. But there's a wrinkle, the resources (eg. notes, folders and tags) belong to an specifec individual so the JWT must be created using the seed data. And the tests must be updated to check for the specific user's resources.
We'll tackle this challenge in 2 steps. First, configure the tests to generate a valid JWT and use it to test an endpoint. Second, update the tests to verify the data based on the user.
### Create a JWT in `beforeEach`
Starting with `/test/folders.test.js` update the `beforeEach` as follows.
Loop to map over the `seedUser` to hash the passwords. At first, the map contains an array of pending promises which you can pass to `Promise.all()`. When all the promises resolved, then loop over the results and update passwords in `seedData` with the digests. Now you are ready to insert the users along with the folders. Finally, when all the data has been inserted, capture the users and extract the first user and create a valid JWT.
```js
// Define a token and user so it is accessible in the tests
let token;
let user;
beforeEach(function () {
return Promise.all(seedUsers.map(user => User.hashPassword(user.password)))
.then(digests => {
seedUsers.forEach((user, i) => user.password = digests[i]);
return Promise.all([
User.insertMany(seedUsers),
Folder.insertMany(seedFolders),
Folder.createIndexes()
]);
})
.then(([users]) => {
user = users[0];
token = jwt.sign({ user }, JWT_SECRET, { subject: user.username });
});
});
```
### Add JWT to request header
Before attempting to add the JWT to your requests you should update your test suite so only one test is executed. This allows you to focus on one test at a time. In the example below we are focusing on the `GET /api/folders`. Add `.only` or `.skip` to the `describe` and it `blocks` as needed.
Now we need to add the JWT to the `Authorization` header as a Bearer token. Luckily, the Chai-HTTP `.set()` method makes this easy. Below is a generic example
```js
chai.request(app)
.get('/api/protected')
.set('Authorization', `Bearer ${token}`)
.then(() => {
/*...*/
});
```
Add the Authorization header with the Bearer token to the `/api/folders/` test as shown below.
```js
describe.only('GET /api/folders', function () {
it('should return the correct number of folders', function () {
const dbPromise = Folder.find();
const apiPromise = chai.request(app)
.get('/api/folders')
.set('Authorization', `Bearer ${token}`); // <<== Add this
return Promise.all([dbPromise, apiPromise])
.then(([data, res]) => {
expect(res).to.have.status(200);
expect(res).to.be.json;
expect(res.body).to.be.a('array');
expect(res.body).to.have.length(data.length);
});
});
```
Now when you run the test, you should no longer get an Unauthorized error, but the test will not pass. Comment-out the `expect(res.body).to.have.length(data.length)` assertion and run it again.
Let's fix the length issue now.
### Update tests to expect specific user content
The test did not pass because the `/api/folders/` endpoint returns results for a specific user. But the database cross-check is still selecting **all** folders. You need to update the `Folder.find()` to include the User id like so:
```js
Folder.find({ userId: user.id })
```
The complete test will look like this:
```js
it('should return the correct number of folders', function () {
const dbPromise = Folder.find({ userId: user.id });
const apiPromise = chai.request(app)
.get('/api/folders')
.set('Authorization', `Bearer ${token}`);
return Promise.all([dbPromise, apiPromise])
.then(([data, res]) => {
expect(res).to.have.status(200);
expect(res).to.be.json;
expect(res.body).to.be.a('array');
expect(res.body).to.have.length(data.length);
});
});
```
Let's try another one. The next test verifies that the response contains the correct keys. The updated endpoint now returns the `userId` in addition to the `id` and `name`. Update your test with the Authorization header, add a filter to the database query and update the assertion as shown below.
```js
it('should return a list with the correct right fields', function () {
const dbPromise = Folder.find({ userId: user.id }); // <<== Add filter on User Id
const apiPromise = chai.request(app)
.get('/api/folders')
.set('Authorization', `Bearer ${token}`); // <<== Add Authorization header
return Promise.all([dbPromise, apiPromise])
.then(([data, res]) => {
expect(res).to.have.status(200);
expect(res).to.be.json;
expect(res.body).to.be.a('array');
res.body.forEach(function (item) {
expect(item).to.be.a('object');
expect(item).to.have.keys('id', 'name', 'userId', 'createdAt', 'updatedAt'); // <<== Update assertion
});
});
});
```
Your challenge!
Update the rest of the Folder tests **and** then apply your learning to the Tag and Note tests.
## Deploy the app
If time allows, you should push your changes to GitHub and verify your tests pass on Travis CI and are deployed to Heroku.
以上是关于markdown 挑战20测试JWT的主要内容,如果未能解决你的问题,请参考以下文章