Skip to content

Commit

Permalink
Merge pull request #156 from sasjs/fix-swagger-api-with-csrf
Browse files Browse the repository at this point in the history
fix: consume swagger api with CSRF
  • Loading branch information
allanbowe authored May 1, 2022
2 parents 6d34206 + 5aaac24 commit c9d66b8
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 25 deletions.
18 changes: 9 additions & 9 deletions api/package-lock.json

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

2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"mongoose-sequence": "^5.3.1",
"morgan": "^1.10.0",
"multer": "^1.4.3",
"swagger-ui-express": "^4.1.6"
"swagger-ui-express": "4.3.0"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
Expand Down
15 changes: 15 additions & 0 deletions api/public/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,21 @@ info:
name: '4GL Ltd'
openapi: 3.0.0
paths:
/:
get:
operationId: Home
responses:
'200':
description: Ok
content:
application/json:
schema:
type: string
summary: 'Render index.html'
tags:
- Web
security: []
parameters: []
/login:
post:
operationId: Login
Expand Down
26 changes: 26 additions & 0 deletions api/src/controllers/web.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import path from 'path'
import express from 'express'
import { Request, Route, Tags, Post, Body, Get } from 'tsoa'
import { readFile } from '@sasjs/utils'

import User from '../model/User'
import { getWebBuildFolderPath } from '../utils'

@Route('/')
@Tags('Web')
export class WebController {
/**
* @summary Render index.html
*
*/
@Get('/')
public async home(@Request() req: express.Request) {
return home(req)
}

/**
* @summary Accept a valid username/password
*
Expand All @@ -31,6 +44,19 @@ export class WebController {
}
}

const home = async (req: express.Request) => {
const indexHtmlPath = path.join(getWebBuildFolderPath(), 'index.html')

// Attention! Cannot use fileExists here,
// due to limitation after building executable
const content = await readFile(indexHtmlPath)

req.res?.cookie('XSRF-TOKEN', req.csrfToken())
req.res?.setHeader('Content-Type', 'text/html')

return content
}

const login = async (
req: express.Request,
{ username, password }: LoginPayload
Expand Down
12 changes: 11 additions & 1 deletion api/src/routes/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,22 @@ router.use('/group', desktopRestrict, groupRouter)
router.use('/stp', authenticateAccessToken, stpRouter)
router.use('/code', authenticateAccessToken, codeRouter)
router.use('/user', desktopRestrict, userRouter)

router.use(
'/',
swaggerUi.serve,
swaggerUi.setup(undefined, {
swaggerOptions: {
url: '/swagger.yaml'
url: '/swagger.yaml',
requestInterceptor: (request: any) => {
request.credentials = 'include'

const cookie = document.cookie
const startIndex = cookie.indexOf('XSRF-TOKEN')
const csrf = cookie.slice(startIndex + 11).split('; ')[0]
request.headers['X-XSRF-TOKEN'] = csrf
return request
}
}
})
)
Expand Down
19 changes: 5 additions & 14 deletions api/src/routes/web/web.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
import path from 'path'
import express from 'express'
import { readFile } from '@sasjs/utils'
import { WebController } from '../../controllers/web'
import { getWebBuildFolderPath, loginWebValidation } from '../../utils'
import { loginWebValidation } from '../../utils'

const webRouter = express.Router()
const controller = new WebController()

webRouter.get('/', async (req, res) => {
const indexHtmlPath = path.join(getWebBuildFolderPath(), 'index.html')

try {
// Attention! Cannot use fileExists here, due to limitation after building executable
const content = await readFile(indexHtmlPath)

res.cookie('XSRF-TOKEN', req.csrfToken())
res.setHeader('Content-Type', 'text/html')
return res.send(content)
const response = await controller.home(req)
return res.send(response)
} catch (_) {
return res.send('Web Build is not present')
}
Expand All @@ -25,7 +18,6 @@ webRouter.post('/login', async (req, res) => {
const { error, value: body } = loginWebValidation(req.body)
if (error) return res.status(400).send(error.details[0].message)

const controller = new WebController()
try {
const response = await controller.login(req, body)
res.send(response)
Expand All @@ -35,10 +27,9 @@ webRouter.post('/login', async (req, res) => {
})

webRouter.get('/logout', async (req, res) => {
const controller = new WebController()
try {
await controller.logout(req)
res.status(200).send()
res.status(200).send('OK!')
} catch (err: any) {
res.status(400).send(err.toString())
}
Expand Down

0 comments on commit c9d66b8

Please sign in to comment.