Skip to content

Commit af64a52

Browse files
committed
Modify to work with Jwt authorization schema
1 parent 572fbeb commit af64a52

File tree

8 files changed

+131
-77
lines changed

8 files changed

+131
-77
lines changed

ApiTesting.http

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,33 @@ Content-Type: application/json
1111
"password": "toohardpasswd"
1212
}
1313

14+
###################################################################################
15+
###### LOGIN ######
16+
###################################################################################
17+
### Send POST request with json body
18+
POST http://localhost:3000/auth/login
19+
Content-Type: application/json
20+
21+
{
22+
"email": "[email protected]",
23+
"password": "toohardpasswd"
24+
}
25+
26+
###################################################################################
27+
###### EXAMPLE ROUTE TESTS, WITH AUTH AND NO AUTH ######
28+
###################################################################################
29+
30+
### No authentication, result will be ok without token
31+
GET http://localhost:3000/example-no-auth
32+
Accept: application/json
33+
34+
### Token missing, throw error 400
35+
GET http://localhost:3000/example-with-auth
36+
Accept: application/json
37+
38+
### Token provided, get token from login
39+
GET http://localhost:3000/example-with-auth
40+
Accept: application/json
41+
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3RAdGVzdGVyLmNvbSIsImlhdCI6MTU5MjM4MTIzNiwiZXhwIjoxNTkyMzg0ODM2fQ.bZrrHCvdxeZscfVZUKzRtLO-4o2DoNwUnqFbYiFAuWA
42+
1443
###

src/components/Authentication/index.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ import {NextFunction, Request, Response} from 'express';
22
import app from "../../server/server";
33
import HttpError from "../../server/error";
44
import * as jwt from 'jsonwebtoken';
5-
import {UserModel, UserModelInterface} from "../../database/models/user";
5+
import {UserModelInterface} from "../../database/models/user";
66
import * as User from '../../database/dao/user'
7-
import * as crypto from 'crypto';
87
import * as bcrypt from 'bcrypt';
98

109
/**
@@ -77,5 +76,48 @@ export async function createAccount(req: Request, res: Response, next: NextFunct
7776
* @returns {Promise < void >}
7877
*/
7978
export async function login(req: Request, res: Response, next: NextFunction): Promise<void> {
80-
res.json({result: 'ok'});
79+
try {
80+
81+
// Details from post body
82+
const user = <UserModelInterface>{
83+
email: req.body.email,
84+
password: req.body.password
85+
};
86+
87+
// Check for mandatory details
88+
if (user.email === undefined || user.password === undefined) {
89+
throw new Error('Missing login details!');
90+
}
91+
92+
// Find user with email
93+
const dbUser: UserModelInterface = await User.findOne(<UserModelInterface>user);
94+
95+
96+
const isMatched: boolean = await bcrypt.compare(user.password, dbUser.password);
97+
if (isMatched) {
98+
99+
const token: string = jwt.sign({email: user.email}, app.get('secret'), {
100+
expiresIn: app.get('jwt-expire')
101+
});
102+
103+
res.json({
104+
name: dbUser.name,
105+
email: dbUser.email,
106+
status: 200,
107+
token: token,
108+
message: 'Login authentication success'
109+
});
110+
} else {
111+
throw new Error('Invalid password or email');
112+
}
113+
114+
} catch (error) {
115+
if (error.code === 500) {
116+
return next(new HttpError(error.message.status, error.message));
117+
}
118+
res.json({
119+
status: 400,
120+
message: error.message
121+
});
122+
}
81123
}

src/components/Authentication/interface.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/components/Authentication/service.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/routes/ExampleRouter.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ const router: Router = Router();
88

99
router.get('/', ExampleComponent.test);
1010
// router.post('/', ExampleComponent.create);
11-
// router.get('/:id', ExampleComponent.findOne);
1211
// router.delete('/:id', ExampleComponent.remove);
1312

1413
/**

src/routes/index.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as express from 'express';
22
import * as http from 'http';
33
import * as swaggerUi from 'swagger-ui-express';
4+
import * as jwtConfig from '../server/jwtAuth';
45

56
import AuthenticationRouter from '../routes/AuthenticationRouter'
67
import ExampleRouter from '../routes/ExampleRouter'
@@ -24,25 +25,16 @@ try {
2425
export function init(app: express.Application): void {
2526
const router: express.Router = express.Router();
2627

27-
/**
28-
* @description
29-
* Forwards any requests to the /v1/users URI to our UserRouter
30-
* Also, check if user authenticated
31-
* @constructs
32-
*/
33-
// app.use('/v1/users', jwtConfig.isAuthenticated, UserRouter);
3428

3529
/**
36-
* @description Forwards any requests to the /auth URI to our AuthRouter
37-
* @constructs
30+
* Specify main routes and their routers
31+
* either with authentication required or not
32+
* see examples below
3833
*/
39-
app.use('/auth', AuthenticationRouter);
4034

41-
/**
42-
* @description Forwards any requests to the /example URI to our ExampleRouter
43-
* @constructs
44-
*/
45-
app.use('/example', ExampleRouter);
35+
app.use('/auth', AuthenticationRouter);
36+
app.use('/example-no-auth', ExampleRouter);
37+
app.use('/example-with-auth', jwtConfig.isAuthenticated, ExampleRouter);
4638

4739
/**
4840
* @description
@@ -55,7 +47,7 @@ export function init(app: express.Application): void {
5547
app.get('/docs', swaggerUi.setup(swaggerDoc));
5648
} else {
5749
app.get('/docs', (req, res) => {
58-
res.send('<p>Seems like you doesn\'t have <code>swagger.json</code> file.</p>' +
50+
res.send('<p>Seems like you don\'t have <code>swagger.json</code> file.</p>' +
5951
'<p>For generate doc file use: <code>swagger-jsdoc -d swagger.js -o swagger.json</code> in terminal</p>' +
6052
'<p>Then, restart your application</p>');
6153
});

src/server/jwtAuth.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as jwt from 'jsonwebtoken';
2+
import {NextFunction, Request, Response} from 'express';
3+
import app from '../server/server';
4+
import HttpError from '../server/error';
5+
import * as http from 'http';
6+
7+
interface RequestWithUser extends Request {
8+
user: object | string;
9+
}
10+
11+
/**
12+
*
13+
* @param {RequestWithUser} req
14+
* @param {Response} res
15+
* @param {NextFunction} next
16+
* @returns {void}
17+
* @swagger
18+
* components:
19+
* securitySchemes:
20+
* bearerAuth:
21+
* type: http
22+
* scheme: bearer
23+
* bearerFormat: JWT
24+
* name: authorization
25+
*/
26+
export function isAuthenticated(req: RequestWithUser, res: Response, next: NextFunction): void {
27+
const jwtToken: any = req.headers['authorization'].replace(/^Bearer\s/, '');
28+
29+
if (jwtToken) {
30+
try {
31+
const user: object | string = jwt.verify(jwtToken, app.get('secret'));
32+
33+
req.user = user;
34+
35+
return next();
36+
37+
} catch (error) {
38+
return next(new HttpError(401, http.STATUS_CODES[401]));
39+
}
40+
}
41+
42+
return next(new HttpError(400, 'No token provided'));
43+
44+
}

swagger.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@
3434
}
3535
},
3636
"securitySchemes": {
37-
"ApiKeyAuth": {
38-
"type": "apiKey",
39-
"in": "header",
40-
"name": "x-access-token"
37+
"bearerAuth": {
38+
"type": "http",
39+
"scheme": "bearer",
40+
"bearerFormat": "JWT",
41+
"name": "authorization"
4142
}
4243
}
4344
},

0 commit comments

Comments
 (0)