From 2134106187873fdb6cfd7503f750cf03cac50696 Mon Sep 17 00:00:00 2001 From: James Ray Date: Mon, 2 May 2022 08:16:35 -0400 Subject: [PATCH] fix(lambda): got them all working as expected --- functions/src/confirmRegistration.js | 21 +++- functions/src/helpers/hashSecret.js | 6 +- functions/src/helpers/parseAWSError.js | 12 ++ functions/src/home.js | 2 +- functions/src/login.js | 46 ++++---- functions/src/register.js | 24 ++-- latest-api-definition.yml | 145 +++++++++++++++++++++++++ 7 files changed, 218 insertions(+), 38 deletions(-) create mode 100644 functions/src/helpers/parseAWSError.js diff --git a/functions/src/confirmRegistration.js b/functions/src/confirmRegistration.js index 4cfa9d6..19874f0 100644 --- a/functions/src/confirmRegistration.js +++ b/functions/src/confirmRegistration.js @@ -2,6 +2,7 @@ import AWSXRay from "aws-xray-sdk-core"; import AWSNoXRay from "aws-sdk"; import dotenv from "dotenv"; import hashSecret from "./helpers/hashSecret"; +import parseAWSError from "./helpers/parseAWSError"; const AWS = AWSXRay.captureAWS(AWSNoXRay); @@ -12,12 +13,24 @@ const provider = new AWS.CognitoIdentityServiceProvider({ }); -exports.handler = function(event, callback) { +exports.handler = function(event, context, callback) { const segment = new AWSXRay.Segment("confirm_register_user"); + var body; + if (event.body !== null && event.body !== undefined) { + body = JSON.parse(event.body); + } else{ + callback(new Error("Expected post Body")); + } + var confirm_code; + if (typeof body.confirmation_code === "string" || body.confirmation_code instanceof String){ + confirm_code = body.confirmation_code; + }else { + confirm_code = body.confirmation_code.toString(); + } var params = { ClientId: process.env.CLIENT_ID, - ConfirmationCode: event.body.confirmation_code, - Username: event.body.username + ConfirmationCode: confirm_code, + Username: body.username }; hashSecret(params); @@ -32,7 +45,7 @@ exports.handler = function(event, callback) { }) .catch(err => { segment.close(); - callback(new Error(err)); + callback(null, parseAWSError(err)); return false; }).finally(() => { segment.close(); diff --git a/functions/src/helpers/hashSecret.js b/functions/src/helpers/hashSecret.js index 3348272..3aa3472 100644 --- a/functions/src/helpers/hashSecret.js +++ b/functions/src/helpers/hashSecret.js @@ -1,10 +1,10 @@ import crypto from "crypto"; -export default (params) => { +export default (params, usernameKey = "Username", secretKey = "SecretHash") => { let secretHash = crypto .createHmac("SHA256", process.env.CLIENT_SECRET) - .update(params.Username + process.env.CLIENT_ID) + .update(params[usernameKey] + process.env.CLIENT_ID) .digest("base64"); - params.SecretHash = secretHash; + params[secretKey] = secretHash; return params; }; diff --git a/functions/src/helpers/parseAWSError.js b/functions/src/helpers/parseAWSError.js new file mode 100644 index 0000000..ab63d83 --- /dev/null +++ b/functions/src/helpers/parseAWSError.js @@ -0,0 +1,12 @@ +export default (err) => { + return { + "statusCode": parseInt(err.statusCode), + "headers": { + "content-type": "application/json" + }, + "body": JSON.stringify({ + "code": err.code, + "message": err.message + }) + }; +}; diff --git a/functions/src/home.js b/functions/src/home.js index 3e8fe8f..f82bd01 100644 --- a/functions/src/home.js +++ b/functions/src/home.js @@ -1,6 +1,6 @@ import AWSXRay from "aws-xray-sdk-core"; -exports.handler = function(event, callback) { +exports.handler = function(event, context, callback) { const segment = new AWSXRay.Segment("home_page"); let res = { "message": "We are currently not taking in new registrations" diff --git a/functions/src/login.js b/functions/src/login.js index c9b3099..e1488ae 100644 --- a/functions/src/login.js +++ b/functions/src/login.js @@ -1,6 +1,8 @@ import AWSXRay from "aws-xray-sdk-core"; import AWSNoXRay from "aws-sdk"; import dotenv from "dotenv"; +import hashSecret from "./helpers/hashSecret"; +import parseAWSError from "./helpers/parseAWSError"; const AWS = AWSXRay.captureAWS(AWSNoXRay); @@ -11,35 +13,33 @@ const provider = new AWS.CognitoIdentityServiceProvider({ }); -exports.handler = function(event, callback) { +exports.handler = function(event, context, callback) { + var body; + if (event.body !== null && event.body !== undefined) { + body = JSON.parse(event.body); + } else{ + callback(new Error("Expected post Body")); + } const segment = new AWSXRay.Segment("login_user"); - if (!event.body || !event.body.email || !event.body.password) { + if (!body || !body.email || !body.password) { callback(new Error("Invalid parameters.")); return false; } - var poolData = { - UserPoolId: process.env.POOL_ID, - ClientId: process.env.CLIENT_ID - }; - - var userPool = provider.CognitoUserPool(poolData); - var authData = { - Username: event.body.email, - Password: event.body.password + var params = { + "AuthFlow": "USER_PASSWORD_AUTH", + "ClientId": process.env.CLIENT_ID, + "AuthParameters": { + "USERNAME": body.email, + "PASSWORD": body.password + } }; - - var authDetails = provider.AuthenticationDetails(authData); - var userData = { - Username: event.body.email, - Pool: userPool - }; - - var cognitoUser = provider.CognitoUser(userData); - - cognitoUser.authenticateUser(authDetails).promise() + hashSecret(params.AuthParameters, "USERNAME", "SECRET_HASH"); + console.log(params); + provider.initiateAuth(params).promise() .then(data => { segment.close(); + console.log(data); callback(null, { success: true, data: data @@ -48,10 +48,12 @@ exports.handler = function(event, callback) { }) .catch(err => { segment.close(); - callback(new Error(err)); + console.log(err); + callback(null, parseAWSError(err)); return false; }).finally(() => { segment.close(); }); + console.log("other"); return false; }; diff --git a/functions/src/register.js b/functions/src/register.js index f33d89d..aa41faa 100644 --- a/functions/src/register.js +++ b/functions/src/register.js @@ -2,6 +2,7 @@ import AWSXRay from "aws-xray-sdk-core"; import AWSNoXRay from "aws-sdk"; import dotenv from "dotenv"; import hashSecret from "./helpers/hashSecret"; +import parseAWSError from "./helpers/parseAWSError"; const AWS = AWSXRay.captureAWS(AWSNoXRay); @@ -33,26 +34,33 @@ const provider = new AWS.CognitoIdentityServiceProvider({ }); // Handler -exports.handler = function(event, callback) { +exports.handler = function(event, context, callback) { + var body; + if (event.body !== null && event.body !== undefined) { + body = JSON.parse(event.body); + } else{ + callback(new Error("Expected post Body")); + } + const segment = new AWSXRay.Segment("register_user"); try { - verifyBody(event.body); + verifyBody(body); } catch (error) { callback(new Error(error)); return false; } var params = { ClientId: process.env.CLIENT_ID, - Password: event.body.password, - Username: event.body.email, + Password: body.password, + Username: body.email, UserAttributes: [ { Name: "email", - Value: event.body.email + Value: body.email }, { Name: "phone_number", - Value: event.body.phone_number + Value: body.phone_number } ] }; @@ -67,9 +75,9 @@ exports.handler = function(event, callback) { return true; }) .catch(err => { + callback(null, parseAWSError(err)); segment.close(); - callback(new Error(err)); - return false; + return true; }).finally(() => { segment.close(); }); diff --git a/latest-api-definition.yml b/latest-api-definition.yml index 46fa463..6dae8dd 100644 --- a/latest-api-definition.yml +++ b/latest-api-definition.yml @@ -24,7 +24,33 @@ components: type: string phone_number: type: string + confirm: + description: Confirmation Body + type: object + properties: + username: + type: string + description: email + confirmation_code: + type: string + login: + description: Login Body + type: object + properties: + email: + type: string + description: email + password: + type: string examples: + login: + value: + email: example@example.com + password: "password" + confirm: + value: + username: Email + confirmation_code: "123456" Register: value: email: example@example.com @@ -33,8 +59,82 @@ components: phone_number: "5555550555" paths: + /: + get: + responses: + '200': + description: "No application" + content: + application/json: + schema: + type: object + properties: + message: + type: string + default: "We are currently not taking in new registrations" + '500': + description: "Internal Error" + content: + application/json: + schema: + type: object + properties: + message: + type: string + default: 'Internal Server Error' + + /login: + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/login' + examples: + objectExample: + $ref: '#/components/examples/login' + responses: + '200': + description: 'Successful login' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + default: true + data: + type: object + properties: + ChallengeParameters: + type: object + AuthenticationResult: + type: object + properties: + AccessToken: + type: string + ExpiresIn: + type: integer + TokenType: + type: string + RefreshToken: + type: string + IdToken: + type: string + + default: + description: "Default response for POST /login" /confirm: post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/confirm' + examples: + objectExample: + $ref: '#/components/examples/confirm' responses: default: description: "Default response for POST /confirm" @@ -50,5 +150,50 @@ paths: $ref: '#/components/examples/Register' responses: + '200': + description: 'Registration Succesful' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + default: true + data: + type: object + properties: + UserConfirmed: + type: boolean + default: false + CodeDeliveryDetails: + type: object + properties: + Destination: + type: string + default: "e***@e***" + DeliveryMedium: + type: string + default: EMAIL + AttributeName: + type: string + default: email + UserSub: + type: string + default: "bjhk2134kj-234d-234n-890d-fd932rjklio" + + '400': + description: 'Forbidden' + content: + application/json: + schema: + type: object + properties: + code: + type: string + default: "NotAuthroizedException" + message: + type: string + default: "SignUp is not permitted for this user pool" default: description: "Default response for POST /register"