-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #68 from EvaEngine/feature/kong-auth
feat(auth): add kong auth integration
- Loading branch information
Showing
5 changed files
with
156 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { Dependencies } from 'constitute'; | ||
import _ from 'lodash'; | ||
|
||
import DI from '../di'; | ||
import wrapper from '../utils/wrapper'; | ||
import { UnauthorizedException } from '../exceptions'; | ||
import Config from '../services/config'; | ||
|
||
/** | ||
* @param _config {Config} | ||
* @returns {function()} | ||
* @constructor | ||
*/ | ||
function AuthKongMiddleware(_config) { | ||
const config = _config.get(); | ||
const token = DI.get('jwt'); | ||
return () => wrapper(async (req, res, next) => { | ||
const jwToken = req.header('X-Token') || req.query.api_key; | ||
if (config.token.faker.enable === true && req.auth && req.auth.uid) { | ||
res.set('X-Uid', req.auth.uid); | ||
return next(); | ||
} | ||
if (config.token.faker.enable === true && jwToken === config.token.faker.key) { | ||
req.auth = { //eslint-disable-line no-param-reassign | ||
type: 'fake', | ||
uid: config.token.faker.uid, | ||
token: config.token.faker.key | ||
}; | ||
res.set('X-Uid', config.token.faker.uid); | ||
return next(); | ||
} | ||
if (req.headers['x-consumer-custom-id']) { | ||
let uid; | ||
if (_.get(config, 'token.kong.noTokenSent')) { | ||
uid = req.headers['x-consumer-custom-id']; | ||
} else { | ||
const parsedToken = await token.find(jwToken); | ||
({ uid } = parsedToken); | ||
if (!uid) { | ||
throw new UnauthorizedException('User info not found in token'); | ||
} | ||
if (req.headers['x-consumer-custom-id'] !== uid.toString()) { | ||
throw new UnauthorizedException('Invalid token.'); | ||
} | ||
} | ||
req.auth = { //eslint-disable-line no-param-reassign | ||
type: 'jwt', | ||
uid, | ||
token: jwToken | ||
}; | ||
res.set('X-Uid', uid); | ||
return next(); | ||
} | ||
|
||
if (req.session && req.session.uid) { | ||
req.auth = { //eslint-disable-line no-param-reassign | ||
type: 'session', | ||
uid: req.session.uid, | ||
token: '' | ||
}; | ||
res.set('X-Uid', req.session.uid); | ||
return next(); | ||
} | ||
throw new UnauthorizedException('No authority token found'); | ||
}); | ||
} | ||
|
||
Dependencies(Config)(AuthKongMiddleware); //eslint-disable-line new-cap | ||
export default AuthKongMiddleware; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { Dependencies } from 'constitute'; | ||
import jwt from 'jwt-simple'; | ||
import _ from 'lodash'; | ||
|
||
import { RuntimeException } from '../exceptions'; | ||
import Config from './config'; | ||
import RestClient from '../services/rest_client'; | ||
import ServiceInterface from './interface'; | ||
|
||
@Dependencies(Config, RestClient) //eslint-disable-line new-cap | ||
export default class KongJsonWebToken extends ServiceInterface { | ||
/** | ||
* @param config {Config} | ||
* @param restClient {RestClient} | ||
*/ | ||
constructor(config, restClient) { | ||
super(); | ||
this.restClient = restClient; | ||
this.config = config.get('token'); | ||
if (!_.get(this.config, 'kong.endpoint')) { | ||
throw new RuntimeException('config item `token.kong.endpoint` can not be null'); | ||
} | ||
} | ||
|
||
getProto() { | ||
return jwt; | ||
} | ||
|
||
async save(uid, item) { | ||
const toSaveItem = Object.assign({ uid }, item); | ||
const tokenString = this.encode(toSaveItem); | ||
await this.restClient.request({ | ||
url: `${this.config.kong.endpoint}/rbac/credentials`, | ||
method: 'post', | ||
body: { | ||
custom_id: uid.toString(), | ||
username: item.username || null, | ||
key: tokenString, | ||
expired_at: item.expiredAt ? item.expiredAt * 1000 : null | ||
} | ||
}); | ||
return tokenString; | ||
} | ||
|
||
async find(tokenString) { | ||
if (!tokenString) { | ||
return { uid: null, expiredAt: 0 }; | ||
} | ||
const parsedToken = this.decode(tokenString); | ||
if (!parsedToken || !{}.hasOwnProperty.call(parsedToken, 'uid')) { | ||
return { uid: null, expiredAt: 0 }; | ||
} | ||
return parsedToken; | ||
} | ||
|
||
clear(tokenString) { | ||
if (!tokenString) { | ||
return true; | ||
} | ||
return this.restClient.request({ | ||
url: `${this.config.kong.endpoint}/rbac/credentials/${tokenString}`, | ||
method: 'delete' | ||
}); | ||
} | ||
|
||
encode(item, secret = this.config.secret) { | ||
return jwt.encode(item, secret); | ||
} | ||
|
||
decode(str, secret = this.config.secret) { | ||
return jwt.decode(str, secret); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters