Skip to content

Instantly share code, notes, and snippets.

@Gumball12
Created November 8, 2019 09:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gumball12/4c9e25284e4fd4cdbf2e070a232f5808 to your computer and use it in GitHub Desktop.
Save Gumball12/4c9e25284e4fd4cdbf2e070a232f5808 to your computer and use it in GitHub Desktop.
SERVERLESS_WITH_OAUTH HANDER_CODE
'use strict';
// import modules
const _ = require('lodash');
const aws = require('aws-sdk');
const randomEmoji = require('random-emoji');
// aws lambda
const lambda = new aws.Lambda({
region: 'ap-northeast-2',
});
/* handlers */
/**
* xss filtering function
* @param {Object} payload payload
* @param {Object} payload.body payload body
* @param {String} payload.body.target filtering target
* @param {Object} payload.body.payload transfer payload
* @param {String} payload.body.payload.userId user id
* @param {String} payload.body.payload.password user password
*/
module.exports.filter = async ({ body }) => {
// parse body
const { target, payload } = JSON.parse(body);
// target branching
switch (target) {
/**
* invoke 'resource-owner' lambda func
* @description http 200: Success (return Auth Grant)
* @description http 401: Unauthorized user (return message)
* @return {String} Auth Grant ID | message
*/
case 'resource-owner': {
const { Payload } = await lambda.invoke({
FunctionName: process.env.resourceOwner,
Payload: JSON.stringify(payload), // with payload
}).promise();
// success or error (just payload data)
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: Payload, // auth grant id
};
break;
}
/**
* invoke 'authorization-server' lambda func
* @description http 200: Success (return Access/Refresh Token)
* @description http 401: Unauthorized user (return message)
* @return {String} Token | message
*/
case 'authorization-server': {
const { Payload } = await lambda.invoke({
FunctionName: process.env.authorizationServer,
Payload: JSON.stringify(payload),
}).promise();
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: Payload, // token
};
break;
}
/**
* invoke 'resource-server' lambda func
* @description http 200: Success (return Protected Resource)
* @description http 401: Unauthorized user (return message)
* @description http 403: Forbidden (return message)
* @return {String} Resource | message
*/
case 'resource-server': {
const { Payload } = await lambda.invoke({
FunctionName: process.env.resourceServer,
Payload: JSON.stringify(payload),
}).promise();
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: Payload, // resource
};
break;
}
}
};
/**
* mocking function for resource owner
* @param {Object} payload
* @param {String} payload.userId
* @param {String} payload.password
* @param {Boolean} payload.isRegister
* @return {String} Authorization Grant ID | http status code
*/
module.exports.resourceOwner = async ({ userId, password, isRegister }) => {
if (isRegister) {
if (userId !== 'darwin10') {
return {
statusCode: 201,
};
}
// error
return {
statusCode: 401,
body: 'Registration failed'
};
}
// check user id
if (userId === 'darwin') {
// get auth grant using internal lambda function
const { Payload } = await lambda.invoke({
FunctionName: process.env.getGrant,
}).promise();
// success
return {
statusCode: 200,
body: JSON.parse(Payload).body.id, // return Authorization Grant ID
};
}
// error
return {
statusCode: 401,
body: 'Failed to get token',
};
};
/**
* mocking function for authorization server
* @param {Object} payload
* @param {String} payload.userId init token mode (optional)
* @param {String} payload.refreshToken new token mode (optional)
* @param {String} payload.grant auth grant id
* @param {String} payload.isExpired is refresh token expired? (optional)
* @return {String} access/refresh token
*/
module.exports.authorizationServer = async ({ grant, refreshToken, userId, isExpired }) => {
let validation = false;
// check payload
if (grant) { // init token mode
validation = (grant === '101204' && userId === 'darwin');
} else { // new token mode
validation = (refreshToken === 'zhckdtk-refresh' && userId === 'darwin');
}
// validation check
if (validation) {
// check token is expired
if (isExpired) {
return {
statusCode: 403, // expired
body: 'Token has expired',
};
}
// get token
const { Payload } = await lambda.invoke({
FunctionName: process.env.getToken,
}).promise();
// success
return {
statusCode: 200,
body: _.at(JSON.parse(Payload).body, ['accessToken', 'refreshToken']),
};
}
// error
return {
statusCode: 401,
body: 'Failed to get token',
};
};
/**
* mocking function for resource server
* @param {Object} payload
* @param {String} payload.accessToken
* @param {String} payload.userId
* @param {Boolean} payload.isExpired is access token expired? (optional)
* @return {String} protected resource
*/
module.exports.resourceServer = async ({ accessToken, userId, isExpired }) => {
// check token, userid
if (accessToken === 'zhckdtk-access' && userId === 'darwin') {
// check token is expired
if (isExpired) {
return {
statusCode: 403, // expired token
body: 'Token has expired',
};
}
// get resource
const { Payload } = await lambda.invoke({
FunctionName: process.env.getResource,
}).promise();
// success
return {
statusCode: 200,
body: JSON.parse(Payload).body.data,
};
}
// error
return {
statusCode: 401,
body: 'Failed to get resource',
};
};
/**
* get auth grant
* (internal lambda function tool)
* @return {Object} grant payload
*/
module.exports.getGrant = async () => ({
statusCode: 200,
body: {
id: '101204',
userId: 'darwin',
created: _.now(),
expired: _.now() + 1000 * 5, // + 5 sec
},
});
/**
* get access, refresh tokens
* (internal lambda function tool)
* @return {Object} token
*/
module.exports.getToken = async () => ({
statusCode: 200,
body: {
userId: 'darwin',
accessToken: 'zhckdtk-access',
refreshToken: 'zhckdtk-refresh',
expired_accessToken: _.now() + 1000 * 60 * 60, // + 1 hour
expired_refreshToken: _.now() + 1000 * 60 * 60 * 12, // + 12 hour
},
});
/**
* get resource
* (internal lambda func tool)
* @return {Object} protected resource
*/
module.exports.getResource = async () => ({
statusCode: 200,
body: {
data: `${randomEmoji.random({ count: 1 })[0].character}-${Math.floor(0xffffff * Math.random())}`,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment