mirror of
https://github.com/openstf/stf
synced 2025-10-04 18:29:17 +02:00
use security handler instead of express middleware for access token validation.
This commit is contained in:
parent
f10ae51b53
commit
221bc78e49
5 changed files with 120 additions and 81 deletions
|
@ -6,7 +6,6 @@ swagger:
|
||||||
fittingsDirs: [ fittings ]
|
fittingsDirs: [ fittings ]
|
||||||
defaultPipe: null
|
defaultPipe: null
|
||||||
swaggerControllerPipe: swagger_controllers # defines the standard processing pipe for controllers
|
swaggerControllerPipe: swagger_controllers # defines the standard processing pipe for controllers
|
||||||
swagger: 'swagger/api_v1.yaml'
|
|
||||||
|
|
||||||
# values defined in the bagpipes key are the bagpipes pipes and fittings definitions
|
# values defined in the bagpipes key are the bagpipes pipes and fittings definitions
|
||||||
# (see https://github.com/apigee-127/bagpipes)
|
# (see https://github.com/apigee-127/bagpipes)
|
||||||
|
@ -22,10 +21,13 @@ swagger:
|
||||||
name: swagger_validator
|
name: swagger_validator
|
||||||
validateResponse: true
|
validateResponse: true
|
||||||
|
|
||||||
|
_swagger_security:
|
||||||
|
name: swagger_security
|
||||||
|
securityHandlersModule: helpers/securityHandlers
|
||||||
|
|
||||||
# pipe for all swagger-node controllers
|
# pipe for all swagger-node controllers
|
||||||
swagger_controllers:
|
swagger_controllers:
|
||||||
- onError: json_error_handler
|
- onError: json_error_handler
|
||||||
- cors
|
|
||||||
- swagger_params_parser
|
- swagger_params_parser
|
||||||
- swagger_security
|
- swagger_security
|
||||||
- _swagger_validate
|
- _swagger_validate
|
||||||
|
|
70
lib/units/api/helpers/securityHandlers.js
Normal file
70
lib/units/api/helpers/securityHandlers.js
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
var jwtutil = require('../../../util/jwtutil')
|
||||||
|
var urlutil = require('../../../util/urlutil')
|
||||||
|
var logger = require('../../../util/logger')
|
||||||
|
var dbapi = require('../../../db/api')
|
||||||
|
|
||||||
|
var log = logger.createLogger('api:auth')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
accessTokenAuth: accessTokenAuth
|
||||||
|
}
|
||||||
|
|
||||||
|
function accessTokenAuth(req, res, next) {
|
||||||
|
if (req.headers.authorization) {
|
||||||
|
var tokenId = req.headers.authorization.split(" ")[1]
|
||||||
|
|
||||||
|
if (tokenId) {
|
||||||
|
dbapi.loadAccessToken(tokenId)
|
||||||
|
.then(function(token) {
|
||||||
|
var jwt = token.jwt
|
||||||
|
, data = jwtutil.decode(jwt, req.options.secret)
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
dbapi.loadUser(data.email)
|
||||||
|
.then(function(user) {
|
||||||
|
if (user) {
|
||||||
|
req.user = user
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
log.error('Failed to load token: ', err.stack)
|
||||||
|
res.json(500, {
|
||||||
|
success: false,
|
||||||
|
description: "Bad Access Token"
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
log.error("Bad Access Token Header")
|
||||||
|
res.json(500, {
|
||||||
|
success: false,
|
||||||
|
description: "Bad Access Token Header"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Remove this once frontend become stateless
|
||||||
|
else if (req.session && req.session.jwt) {
|
||||||
|
dbapi.loadUser(req.session.jwt.email)
|
||||||
|
.then(function(user) {
|
||||||
|
if (user) {
|
||||||
|
req.user = user
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.json(500, {
|
||||||
|
success: false,
|
||||||
|
description: "Bad Request"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(next)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res.json(500, {
|
||||||
|
success: false,
|
||||||
|
description: "Request does not have Authorization header"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,8 +7,6 @@ var cookieSession = require('cookie-session')
|
||||||
|
|
||||||
var logger = require('../../util/logger')
|
var logger = require('../../util/logger')
|
||||||
|
|
||||||
var auth = require('./middleware/auth')
|
|
||||||
|
|
||||||
module.exports = function(options) {
|
module.exports = function(options) {
|
||||||
var log = logger.createLogger('api')
|
var log = logger.createLogger('api')
|
||||||
, app = express()
|
, app = express()
|
||||||
|
@ -25,17 +23,19 @@ module.exports = function(options) {
|
||||||
swaggerExpress.register(app);
|
swaggerExpress.register(app);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Adding options in request, so that swagger controller
|
||||||
|
// can use it.
|
||||||
|
app.use(function(req, res, next) {
|
||||||
|
req.options = options
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
|
||||||
// TODO: Remove this once frontend is stateless
|
// TODO: Remove this once frontend is stateless
|
||||||
app.use(cookieSession({
|
app.use(cookieSession({
|
||||||
name: options.ssid
|
name: options.ssid
|
||||||
, keys: [options.secret]
|
, keys: [options.secret]
|
||||||
}))
|
}))
|
||||||
|
|
||||||
app.use(auth({
|
|
||||||
secret: options.secret
|
|
||||||
, authUrl: options.authUrl
|
|
||||||
}))
|
|
||||||
|
|
||||||
server.listen(options.port)
|
server.listen(options.port)
|
||||||
log.info('Listening on port %d', options.port)
|
log.info('Listening on port %d', options.port)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
var jwtutil = require('../../../util/jwtutil')
|
|
||||||
var urlutil = require('../../../util/urlutil')
|
|
||||||
var logger = require('../../../util/logger')
|
|
||||||
var dbapi = require('../../../db/api')
|
|
||||||
|
|
||||||
module.exports = function(options) {
|
|
||||||
return function(req, res, next) {
|
|
||||||
|
|
||||||
var log = logger.createLogger('api:auth')
|
|
||||||
|
|
||||||
if (req.headers.authorization) {
|
|
||||||
var tokenId = req.headers.authorization.split(" ")[1]
|
|
||||||
|
|
||||||
if (tokenId) {
|
|
||||||
dbapi.loadAccessToken(tokenId)
|
|
||||||
.then(function(token) {
|
|
||||||
var jwt = token.jwt
|
|
||||||
, data = jwtutil.decode(jwt, options.secret)
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
dbapi.loadUser(data.email)
|
|
||||||
.then(function(user) {
|
|
||||||
if (user) {
|
|
||||||
req.user = user
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function(err) {
|
|
||||||
log.error('Failed to load token: ', err.stack)
|
|
||||||
res.json(500, {
|
|
||||||
success: false,
|
|
||||||
description: "Bad Access Token"
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
log.error("Bad Access Token")
|
|
||||||
res.json(500, {
|
|
||||||
success: false,
|
|
||||||
description: "Bad Access Token Header"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: Remove this once frontend become stateless
|
|
||||||
else if (req.session && req.session.jwt) {
|
|
||||||
dbapi.loadUser(req.session.jwt.email)
|
|
||||||
.then(function(user) {
|
|
||||||
if (user) {
|
|
||||||
req.user = user
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// We no longer have the user in the database
|
|
||||||
res.redirect(options.authUrl)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(next)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// No session, forward to auth client
|
|
||||||
res.redirect(options.authUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +1,15 @@
|
||||||
swagger: "2.0"
|
swagger: "2.0"
|
||||||
info:
|
info:
|
||||||
version: "1.0.10"
|
version: "2.0.0"
|
||||||
title: Smartphone Test Farm
|
title: Smartphone Test Farm
|
||||||
description: Control and manager real Smartphone devices from browser and apis
|
description: Control and manager real Smartphone devices from browser and restful apis
|
||||||
license:
|
license:
|
||||||
name: Apache-2.0
|
name: Apache-2.0
|
||||||
url: http://www.apache.org/licenses/LICENSE-2.0
|
url: http://www.apache.org/licenses/LICENSE-2.0
|
||||||
contact:
|
contact:
|
||||||
url: http://openstf.io/
|
name: STF Support
|
||||||
email: contact@openstf.io
|
email: contact@openstf.io
|
||||||
|
url: http://openstf.io/
|
||||||
basePath: /api/v1
|
basePath: /api/v1
|
||||||
schemes:
|
schemes:
|
||||||
- http
|
- http
|
||||||
|
@ -17,6 +18,11 @@ consumes:
|
||||||
- application/json
|
- application/json
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
|
tags:
|
||||||
|
- name: user
|
||||||
|
description: User Operations
|
||||||
|
- name: device
|
||||||
|
description: Device Operations
|
||||||
paths:
|
paths:
|
||||||
/me:
|
/me:
|
||||||
x-swagger-router-controller: user
|
x-swagger-router-controller: user
|
||||||
|
@ -24,6 +30,8 @@ paths:
|
||||||
summary: User Profile
|
summary: User Profile
|
||||||
description: The User Profile endpoint returns information about current authorized user.
|
description: The User Profile endpoint returns information about current authorized user.
|
||||||
operationId: getCurrentUser
|
operationId: getCurrentUser
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Current User Profile information
|
description: Current User Profile information
|
||||||
|
@ -33,6 +41,8 @@ paths:
|
||||||
description: Unexpected Error
|
description: Unexpected Error
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/definitions/ErrorResponse"
|
$ref: "#/definitions/ErrorResponse"
|
||||||
|
security:
|
||||||
|
- accessTokenAuth: []
|
||||||
# TODO: Change group endpoint with something more easy to understandable endpoint
|
# TODO: Change group endpoint with something more easy to understandable endpoint
|
||||||
/group:
|
/group:
|
||||||
x-swagger-router-controller: user
|
x-swagger-router-controller: user
|
||||||
|
@ -40,21 +50,27 @@ paths:
|
||||||
summary: User Group
|
summary: User Group
|
||||||
description: The User Group endpoint returns information about user group of current authorized user.
|
description: The User Group endpoint returns information about user group of current authorized user.
|
||||||
operationId: getCurrentUserGroup
|
operationId: getCurrentUserGroup
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Current User Group information
|
description: Current User's Group information
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/definitions/GroupResponse"
|
$ref: "#/definitions/GroupResponse"
|
||||||
default:
|
default:
|
||||||
description: Unexpected Error
|
description: Unexpected Error
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/definitions/ErrorResponse"
|
$ref: "#/definitions/ErrorResponse"
|
||||||
|
security:
|
||||||
|
- accessTokenAuth: []
|
||||||
/accessTokens:
|
/accessTokens:
|
||||||
x-swagger-router-controller: token
|
x-swagger-router-controller: token
|
||||||
get:
|
get:
|
||||||
summary: Access Tokens
|
summary: Access Tokens
|
||||||
description: Return Current User Access Tokens titles
|
description: The Access Tokens endpoints returns titles of all the valid access tokens.
|
||||||
operationId: getAccessTokens
|
operationId: getAccessTokens
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Access Tokens titles
|
description: Access Tokens titles
|
||||||
|
@ -64,12 +80,16 @@ paths:
|
||||||
description: Unexpected Error
|
description: Unexpected Error
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/definitions/ErrorResponse"
|
$ref: "#/definitions/ErrorResponse"
|
||||||
|
security:
|
||||||
|
- accessTokenAuth: []
|
||||||
/devices:
|
/devices:
|
||||||
x-swagger-router-controller: device
|
x-swagger-router-controller: device
|
||||||
get:
|
get:
|
||||||
summary: Device List
|
summary: Device List
|
||||||
description: List of all the STF devices including Disconnected and Offline
|
description: The devices enpoint return list of all the STF devices including Disconnected and Offline
|
||||||
operationId: getDevices
|
operationId: getDevices
|
||||||
|
tags:
|
||||||
|
- device
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: List of Devices
|
description: List of Devices
|
||||||
|
@ -79,12 +99,16 @@ paths:
|
||||||
description: Unexpected Error
|
description: Unexpected Error
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/definitions/ErrorResponse"
|
$ref: "#/definitions/ErrorResponse"
|
||||||
|
security:
|
||||||
|
- accessTokenAuth: []
|
||||||
/devices/{serial}:
|
/devices/{serial}:
|
||||||
x-swagger-router-controller: device
|
x-swagger-router-controller: device
|
||||||
get:
|
get:
|
||||||
summary: Device Information
|
summary: Device Information
|
||||||
description: Device Information
|
description: The device enpoint return information about a single device.
|
||||||
operationId: getDeviceBySerial
|
operationId: getDeviceBySerial
|
||||||
|
tags:
|
||||||
|
- device
|
||||||
parameters:
|
parameters:
|
||||||
- name: serial
|
- name: serial
|
||||||
in: path
|
in: path
|
||||||
|
@ -100,6 +124,8 @@ paths:
|
||||||
description: Unexpected Error
|
description: Unexpected Error
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/definitions/ErrorResponse"
|
$ref: "#/definitions/ErrorResponse"
|
||||||
|
security:
|
||||||
|
- accessTokenAuth: []
|
||||||
/swagger.json:
|
/swagger.json:
|
||||||
x-swagger-pipe: swagger_raw
|
x-swagger-pipe: swagger_raw
|
||||||
definitions:
|
definitions:
|
||||||
|
@ -145,3 +171,9 @@ definitions:
|
||||||
properties:
|
properties:
|
||||||
message:
|
message:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
securityDefinitions:
|
||||||
|
accessTokenAuth:
|
||||||
|
type: apiKey
|
||||||
|
name: accessTokenAuth
|
||||||
|
in: header
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue