How to log in to cognito Google Oauth using Cypress? - javascript

I want to test an app that only has Google Oauth Login via AWS Cognito. Lots of guides on how to use cypress to programatically login to Cognito using AWS Amplify with a username and password, but cannot find anything on how to do it with Google Oauth.
Im trying to use cypress to click the buttons to authenticate but I think there is a click forgery protection on Google.
I have also been able to use this cypress documentation to login to Google directly and get a jwt into session storage but not sure if there is a way to pass this to Cognito.

If you're doing end to end testing, then the simplest way would be to have another non prod staging environment without the Google Oauth login in Cognito, and instead the username password login you mentioned that has working examples.
This is also a good idea, as you shouldn't be using your production user system in testing anyway.

I tried many approaches to this including getting oauth token from Google and trying to exchange that manually with Cognito for the token I needed for AWS API Gateway. I also tried cypress-social-logins without success (because of this bug)
Finally I just wrote my own cypress steps to log me into my app with a valid session. NOTE THIS WILL NOT WORK IN A CI/CD because it will probably trigger Google validations and so it is a semi-automated solution.
If in doubt I recommend Tom Roman's answer below about creating a pre-prod environment in cognito that allows username/password login instead of messing about with google login.
// /support/login.js
Cypress.Commands.add('loginByGoogle', () => {
cy.visit('http://localhost:3030')
cy.origin('https://somecognitouserpool.auth.eu-west-1.amazoncognito.com', () => {
cy.contains('button', 'Continue with Google')
.click({force: true})
})
cy.origin('https://accounts.google.com', () => {
const resizeObserverLoopError = /^[^(ResizeObserver loop limit exceeded)]/;
Cypress.on('uncaught:exception', (err) => {
/* returning false here prevents Cypress from failing the test */
if (resizeObserverLoopError.test(err.message)) {
return false;
}
});
cy.get('input#identifierId[type="email"]')
.type(Cypress.env('googleSocialLoginUsername'))
.get('button[type="button"]').contains('Next')
.click()
.get('div#password input[type="password"]')
.type(Cypress.env('googleSocialLoginPassword'))
.get('button[type="button"]').contains('Next')
.click();
});
});
// /e2e/sometest.cy.js
before(() => {
cy.loginByGoogle();
});
describe('E2E testing', () => {
it('should now have a session', () => {
})
});
You also need a .env file (because you don't want to be saving your google credentials into github)
GOOGLE_USERNAME = ''
GOOGLE_PASSWORD = ''
You also need two experimental flags (as of 14th Nov 2022)
// cypress.config.js
const { defineConfig } = require('cypress');
require('dotenv').config()
module.exports = defineConfig({
env: {
googleSocialLoginUsername: process.env.GOOGLE_USERNAME,
googleSocialLoginPassword: process.env.GOOGLE_PASSWORD
},
e2e: {
experimentalSessionAndOrigin: true,
experimentalModifyObstructiveThirdPartyCode: true
}
})
Here is my package.json so that you can see the exact packages I am using.
In particular I added the flags --headed --no-exit in order to complete 2 factor authentication manually as necessary. I have not yet figured out how to stop Google asking for this every time.
{
"name": "docs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "http-server . -p 3030",
"cy:run": "cypress run --headed --no-exit",
"test": "start-server-and-test start http://localhost:3030 cy:run"
},
"author": "",
"license": "ISC",
"devDependencies": {
"cypress": "^11.0.1",
"start-server-and-test": "^1.14.0"
},
"dependencies": {
"dot-env": "^0.0.1",
"dotenv": "^16.0.3"
}
}

Related

AWS EC2 IAM Role Credentials not passed into Node.js application

I am developing a Node.js application which is deployed on an EC2 instance. I am using the AWS SDK for JavaScript. I have tried both v2 and v3. My problem is that whenever I make a call to any AWS service in my application, I get an error saying that the credentials are missing. However, according to the documentation, assigning an IAM role to the EC2 instance should enable the SDK to automatically retrieve the credentials: AWS Documentation. I believe that I have correctly added the IAM role with sufficient permissions to the EC2 instance so I don't understand why the requests are not going through. I do not want to use Environment variables as I would have to manually use them in my code then. Any suggestions of how to debug this issue or thoughts what the problem might be, are greatly appreciated.
For example, a call is made as follows:
const client = new CloudFormationClient({ region: "eu-central-1" });
const params = {
StackStatusFilter: [
"CREATE_IN_PROGRESS"
]
};
const command = new ListStacksCommand(params);
client.send(command).then(
(data) => {
console.log(data);
},
(error) => {
console.log(error);
}
);
The error is simply: Error: Credential is missing.
This originates from the console.log(error).
In have tried with multiple roles but even with the AdministratorAccess the same error occurs. For reference, the permissions are:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}

How to move from Firebase Functions to Cloud Run after encountering 540s timeout limit?

I was reading this Reddit thread where a user mentioned that 540s is the limit of Firebase Functions and that moving to Cloud Run was recommended.
As others have said 540s is the maximum timeout and if you want to increase it without changing much else about your code, consider moving to Cloud Run. ​- #samtstern on Reddit
After looking at the Node.JS QuickStart documentation
and other content on YouTube and Google, I did not find a good guide explaining how to move your Firebase Function to Cloud Run.
One of the issues that were not addressed by what I read, for example: what do I replace the firebase-functions package with to define the function? Etc...
So, how may I move my Firebase Function over to Cloud Run to not run into the 540s max timeout limitation ?
​const functions = require('firebase-functions');
​const runtimeOpts = {timeoutSeconds: 540,memory: '2GB'}
​exports.hourlyData = functions.runWith(runtimeOpts).pubsub.schedule('every 1 hours')
Preface: The following steps have been generalized for a wider audience than just the OP's problem (covers HTTP Event, Scheduled and Pub/Sub Functions) and have been adapted from the documentation linked in the question: Deploying Node.JS Images on Cloud Run.
Step 0: Code/Architecture Review
More often than not, exceeding the 9-minute timeout of a Cloud Function is a result of a bug in your code - make sure to evaluate this before switching to Cloud Run as this will just make the problem worse. The most common of these is sequential instead of parallelized asynchronous processing (normally caused by using await in a for/while loop).
If your code is doing meaningful work that is taking a long time, consider sharding it out to "subfunctions" that can all work on the input data in parallel. Instead of processing data for every user in your database, you can use a single function to trigger multiple instances of a function that each that take care of different user ID ranges such as a-l\uf8ff, m-z\uf8ff, A-L\uf8ff, M-Z\uf8ff and 0-9\uf8ff.
Lastly, Cloud Run and Cloud Functions are quite similar, they are designed to take a request, process it and then return a response. Cloud Functions have a limit of up to 9 minutes and Cloud Runs have a limit of up to 60 minutes. Once that response has been completed (because the server ended the response, the client lost connection or the client aborted the request), the instance is severely throttled or terminated. While you can use WebSockets and gRPC for a persistent communication between server and client when using Cloud Run, they are still subject to this limitation. See the Cloud Run: General development tips documentation for more information.
Like other serverless solutions, your client and server need to be able to handle connecting to different instances. Your code shouldn't make use of local state (like a local store for session data). See the Setting request timeout documentation for more information.
Step 1: Install Google Cloud SDK
I'll refer you to the Installing Google Cloud SDK documentation for this step.
Once installed, call gcloud auth login and login with the account used for the target Firebase project.
Step 2: Get your Firebase Project settings
Open up your project settings in the Firebase Console and take note of your Project ID and your Default GCP resource location.
Firebase Functions and Cloud Run instances should be co-located with your GCP resources where possible. In Firebase Functions, this is achieved by changing the region in code and deploying using the CLI. For Cloud Run, you specify these parameters on the command line as flags (or use the Google Cloud Console). For the below instructions and for simplicity, I will be using us-central1 as my Default GCP resources location is nam5 (us-central).
If using the Firebase Realtime Database in your project, visit your RTDB settings in the Firebase Console and take note of your Database URL. This is usually of the form https://PROJECT_ID.firebaseio.com/.
If using Firebase Storage in your project, visit your Cloud Storage settings in the Firebase Console and take note of your Bucket URI. From this URI, we need to take note of the host (ignore the gs:// part) which is usually of the form PROJECT_ID.appspot.com.
Here's a table that you can copy to help keep track:
Project ID:
PROJECT_ID
Database URL:
https://PROJECT_ID.firebaseio.com
Storage Bucket:
PROJECT_ID.appspot.com
Default GCP Resource Location:
Chosen Cloud Run Region:
Step 3: Create Directories
In your Firebase Project directory or a directory of your choosing, create a new cloudrun folder.
Unlike Firebase Cloud Functions, where you can define multiple functions in a single module of code, each Cloud Run image uses its own module of code. For this reason, each Cloud Run image should be stored in its own directory.
As we are going to define a Cloud Run instance called helloworld, we'll create a directory called helloworld inside cloudrun.
mkdir cloudrun
mkdir cloudrun/helloworld
cd cloudrun/helloworld
Step 4: Create package.json
For correct deployment of the Cloud Run image, we need to provide a package.json that is used to install dependencies in the deployed container.
The format of the package.json file resembles:
{
"name": "SERVICE_NAME",
"description": "",
"version": "1.0.0",
"private": true,
"main": "index.js",
"scripts": {
"start": "node index.js"
"image": "gcloud builds submit --tag gcr.io/PROJECT_ID/SERVICE_NAME --project PROJECT_ID",
"deploy:public": "gcloud run deploy SERVICE_NAME --image gcr.io/PROJECT_ID/SERVICE_NAME --allow-unauthenticated --region REGION_ID --project PROJECT_ID",
"deploy:private": "gcloud run deploy SERVICE_NAME --image gcr.io/PROJECT_ID/SERVICE_NAME --no-allow-unauthenticated --region REGION_ID --project PROJECT_ID",
"describe": "gcloud run services describe SERVICE_NAME --region REGION_ID --project PROJECT_ID --platform managed",
"find": "gcloud run services describe SERVICE_NAME --region REGION_ID --project PROJECT_ID --platform managed --format='value(status.url)'"
},
"engines": {
"node": ">= 12.0.0"
},
"author": "You",
"license": "Apache-2.0",
"dependencies": {
"express": "^4.17.1",
"body-parser": "^1.19.0",
/* ... */
},
"devDependencies": {
/* ... */
}
}
In the above file, SERVICE_NAME, REGION_ID and PROJECT_ID are to be swapped out as appropriate with the details from step 2. We also install express and body-parser to handle the incoming request.
There are also a handful of module scripts to help with deployment.
Script Name
Description
image
Submits the image to Cloud Build to be added to the Container Registry for other commands.
deploy:public
Deploys the image from the above command to be used by Cloud Run (while allowing any requester to invoke it) and returns its service URL (which is partly randomized).
deploy:private
Deploys the image from the above command to be used by Cloud Run (while requiring that the requester that invokes it is an authorized user/service account) and returns its service URL (which is partly randomized).
describe
Gets the statistics & configuration of the deployed Cloud Run.
find
Extracts only the service URL from the response of npm run describe
Note: Here, "Authorized User" refers to a Google Account associated with the project, not an ordinary Firebase User. To allow a Firebase User to invoke your Cloud Run, you must deploy it using deploy:public and handle token validation in your Cloud Run's code, rejecting requests appropriately.
As an example of this file filled in, you get this:
{
"name": "helloworld",
"description": "Simple hello world sample in Node with Firebase",
"version": "1.0.0",
"private": true,
"main": "index.js",
"scripts": {
"start": "node index.js"
"image": "gcloud builds submit --tag gcr.io/com-example-cloudrun/helloworld --project com-example-cloudrun",
"deploy:public": "gcloud run deploy helloworld --image gcr.io/com-example-cloudrun/helloworld --allow-unauthenticated --region us-central1 --project com-example-cloudrun",
"deploy:public": "gcloud run deploy helloworld --image gcr.io/com-example-cloudrun/helloworld --no-allow-unauthenticated --region us-central1 --project com-example-cloudrun",
"describe": "gcloud run services describe helloworld --region us-central1 --project com-example-cloudrun --platform managed",
"find": "gcloud run services describe helloworld --region us-central1 --project com-example-cloudrun --platform managed --format='value(status.url)'"
},
"engines": {
"node": ">= 12.0.0"
},
"author": "You",
"license": "Apache-2.0",
"dependencies": {
/* ... */
},
"devDependencies": {
/* ... */
}
}
Step 5: Create your container files
To tell Cloud Build what container to use for your Cloud Run image, you must create a Dockerfile for your image. To prevent sending the wrong files to the server, you should also specify a .dockerignore file.
In this file, we use the Firebase Project settings from Step 2 to recreate the process.env.FIREBASE_CONFIG environment variable. This variable is used by the Firebase Admin SDK and contains the following information as a JSON string:
{
databaseURL: "https://PROJECT_ID.firebaseio.com",
storageBucket: "PROJECT_ID.appspot.com",
projectId: "PROJECT_ID"
}
Here is cloudrun/helloworld/Dockerfile:
# Use the official lightweight Node.js 14 image.
# https://hub.docker.com/_/node
FROM node:14-slim
# Create and change to the app directory.
WORKDIR /usr/src/app
# Copy application dependency manifests to the container image.
# A wildcard is used to ensure copying both package.json AND package-lock.json (when available).
# Copying this first prevents re-running npm install on every code change.
COPY package*.json ./
# Install production dependencies.
# If you add a package-lock.json, speed your build by switching to 'npm ci'.
# RUN npm ci --only=production
RUN npm install --only=production
# Copy local code to the container image.
COPY . ./
# Define default configuration for Admin SDK
# databaseURL is usually "https://PROJECT_ID.firebaseio.com", but may be different.
# TODO: Update me
ENV FIREBASE_CONFIG={"databaseURL":"https://PROJECT_ID.firebaseio.com","storageBucket":"PROJECT_ID.appspot.com","projectId":"PROJECT_ID"}
# Run the web service on container startup.
CMD [ "node", "index.js" ]
Here is cloudrun/helloworld/.dockerignore:
Dockerfile
.dockerignore
node_modules
npm-debug.log
Step 6: Create & deploy your entry point
When a new Cloud Run instance is launched, it will normally specify the port it wants your code to listen on using the PORT environment variable.
Variant: Migrating a HTTP Event Function
When you use a HTTP Event function from the firebase-functions package, it internally handles body-parsing on your behalf. The Functions Framework uses the body-parser package for this and defines the parsers here.
To handle user authorization, you could use this validateFirebaseIdToken() middleware to check the ID token given with the request.
For a HTTP-based Cloud Run, configuring CORS will be required to invoke it from a browser. This can be done by installing the cors package and configuring it appropriately. In the below sample, cors will reflect the origin sent to it.
const express = require('express');
const cors = require('cors')({origin: true});
const app = express();
app.use(cors);
// To replicate a Cloud Function's body parsing, refer to
// https://github.com/GoogleCloudPlatform/functions-framework-nodejs/blob/d894b490dda7c5fd4690cac884fd9e41a08b6668/src/server.ts#L47-L95
// app.use(/* body parsers */);
app.enable('trust proxy'); // To respect X-Forwarded-For header. (Cloud Run is behind a load balancer proxy)
app.disable('x-powered-by'); // Disables the 'x-powered-by' header added by express (best practice)
// Start of your handlers
app.get('/', (req, res) => {
const name = process.env.NAME || 'World';
res.send(`Hello ${name}!`);
});
// End of your handlers
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`helloworld: listening on port ${port}`);
});
In the $FIREBASE_PROJECT_DIR/cloudrun/helloworld directory, execute the following commands to deploy your image:
npm run image // builds container & stores to container repository
npm run deploy:public // deploys container image to Cloud Run
Variant: Invoke using Cloud Scheduler
When invoking a Cloud Run using the Cloud Scheduler, you can choose which method is used to invoke it (GET, POST (the default), PUT, HEAD, DELETE). To replicate a Cloud Function's data and context parameters, it is best to use POST as these will then be passed in the body of the request. Like Firebase Functions, these requests from Cloud Scheduler may be retried so make sure to handle idempotency appropriately.
Note: Even though the body of a Cloud Scheduler invocation request is JSON-formatted, the request is served with Content-Type: text/plain, which we need to handle.
This code has been adapted from the Functions Framework source (Google LLC, Apache 2.0)
const express = require('express');
const { json } = require('body-parser');
async function handler(data, context) {
/* your logic here */
const name = process.env.NAME || 'World';
console.log(`Hello ${name}!`);
}
const app = express();
// Cloud Scheduler requests contain JSON using
"Content-Type: text/plain"
app.use(json({ type: '*/*' }));
app.enable('trust proxy'); // To respect X-Forwarded-For header. (Cloud Run is behind a load balancer proxy)
app.disable('x-powered-by'); // Disables the 'x-powered-by' header added by express (best practice)
app.post('/*', (req, res) => {
const event = req.body;
let data = event.data;
let context = event.context;
if (context === undefined) {
// Support legacy events and CloudEvents in structured content mode, with
// context properties represented as event top-level properties.
// Context is everything but data.
context = event;
// Clear the property before removing field so the data object
// is not deleted.
context.data = undefined;
delete context.data;
}
Promise.resolve()
.then(() => handler(data, context))
.then(
() => {
// finished without error
// the return value of `handler` is ignored because
// this isn't a callable function
res.sendStatus(204); // No content
},
(err) => {
// handler threw error
console.error(err.stack);
res.set('X-Google-Status', 'error');
// Send back the error's message (as calls to this endpoint
// are authenticated project users/service accounts)
res.send(err.message);
}
)
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`helloworld: listening on port ${port}`);
});
Note: The Functions Framework handles errors by sending back a HTTP 200 OK response with a X-Google-Status: error header. This effectively means "failed successfully". As an outsider, I'm not sure why this is done but I can assume it's so that the invoker knows to not bother retrying the function - it'll just get the same result.
In the $FIREBASE_PROJECT_DIR/cloudrun/helloworld directory, execute the following commands to deploy your image:
npm run image // builds container & stores to container repository
npm run deploy:private // deploys container image to Cloud Run
Note: In the following setup commands (only need to run these once), PROJECT_ID, SERVICE_NAME, SERVICE_URL and IAM_ACCOUNT will need to be substituted as appropriate.
Next we need to create a service account that Cloud Scheduler can use to invoke the Cloud Run. You can call it whatever you want such as scheduled-run-invoker. The email of this service account will be referred to as IAM_ACCOUNT in the next step. This Google Cloud Tech YouTube video (starts at the right spot, about 15s) will quickly show what you need to do. Once you've created the account, you can create the Cloud Scheduler job following the next 30 or so seconds of the video or use the following command:
gcloud scheduler jobs create http scheduled-run-SERVICE_NAME /
--schedule="every 1 hours" /
--uri SERVICE_URL /
--attempt-deadline 60m /
--http-method post /
--message-body='{"optional-custom-data":"here","if-you":"want"}' /
--oidc-service-account-email IAM_ACCOUNT
--project PROJECT_ID
Your Cloud Run should now be scheduled.
Variant: Invoke using Pub/Sub
To my understanding, the deploy process is the same as for a scheduled run (deploy:private) but I'm unsure about the specifics. However, here is the Cloud Run source for a Pub/Sub parser:
This code has been adapted from the Functions Framework source (Google LLC, Apache 2.0)
const express = require('express');
const { json } = require('body-parser');
const PUBSUB_EVENT_TYPE = 'google.pubsub.topic.publish';
const PUBSUB_MESSAGE_TYPE =
'type.googleapis.com/google.pubsub.v1.PubsubMessage';
const PUBSUB_SERVICE = 'pubsub.googleapis.com';
/**
* Extract the Pub/Sub topic name from the HTTP request path.
* #param path the URL path of the http request
* #returns the Pub/Sub topic name if the path matches the expected format,
* null otherwise
*/
const extractPubSubTopic = (path: string): string | null => {
const parsedTopic = path.match(/projects\/[^/?]+\/topics\/[^/?]+/);
if (parsedTopic) {
return parsedTopic[0];
}
console.warn('Failed to extract the topic name from the URL path.');
console.warn(
"Configure your subscription's push endpoint to use the following path: ",
'projects/PROJECT_NAME/topics/TOPIC_NAME'
);
return null;
};
async function handler(message, context) {
/* your logic here */
const name = message.json.name || message.json || 'World';
console.log(`Hello ${name}!`);
}
const app = express();
// Cloud Scheduler requests contain JSON using
"Content-Type: text/plain"
app.use(json({ type: '*/*' }));
app.enable('trust proxy'); // To respect X-Forwarded-For header. (Cloud Run is behind a load balancer proxy)
app.disable('x-powered-by'); // Disables the 'x-powered-by' header added by express (best practice)
app.post('/*', (req, res) => {
const body = req.body;
if (!body) {
res.status(400).send('no Pub/Sub message received');
return;
}
if (typeof body !== "object" || body.message === undefined) {
res.status(400).send('invalid Pub/Sub message format');
return;
}
const context = {
eventId: body.message.messageId,
timestamp: body.message.publishTime || new Date().toISOString(),
eventType: PUBSUB_EVENT_TYPE,
resource: {
service: PUBSUB_SERVICE,
type: PUBSUB_MESSAGE_TYPE,
name: extractPubSubTopic(req.path),
},
};
// for storing parsed form of body.message.data
let _jsonData = undefined;
const data = {
'#type': PUBSUB_MESSAGE_TYPE,
data: body.message.data,
attributes: body.message.attributes || {},
get json() {
if (_jsonData === undefined) {
const decodedString = Buffer.from(base64encoded, 'base64')
.toString('utf8');
try {
_jsonData = JSON.parse(decodedString);
} catch (parseError) {
// fallback to raw string
_jsonData = decodedString;
}
}
return _jsonData;
}
};
Promise.resolve()
.then(() => handler(data, context))
.then(
() => {
// finished without error
// the return value of `handler` is ignored because
// this isn't a callable function
res.sendStatus(204); // No content
},
(err) => {
// handler threw error
console.error(err.stack);
res.set('X-Google-Status', 'error');
// Send back the error's message (as calls to this endpoint
// are authenticated project users/service accounts)
res.send(err.message);
}
)
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`helloworld: listening on port ${port}`);
});

Firebase from Centos and express as backend not working

I have decided to use firebase as a backend for authentication and basic form information with firestore.
In the past I've used this express api in cloud functions to do this, and am basing this new setup off of that. But I'm looking to just use it on a Vultr Centos server instead, to put with the rest of my api, and just make everything easier for now as i don't want to overcomplicate things (until later :P).
Now - I've just cloned this repo onto my server, and I want to test it with postman, and i'm having trouble just accessing it.
I'm not sure how to solve the issue and if anyone could point me in the right direction that would make my life so much easier!
here is the index file and the package json file currently. I've created the server.listen to try and make it work at the moment.
const functions = require("firebase-functions");
const app = require("express")();
const FBAuth = require("./util/fbAuth");
const server = require('http').createServer(app);
const cors = require("cors");
//This was recently added to try and make it all work easier!
server.listen(port, ipaddress, () => {
});
app.use(cors());
const { db } = require("./util/admin");
const {
getAllWorkflows,
...
} = require("./handlers/workflow");
const {
signup,
login,
uploadImage,
addUserDetails,
getAuthenticatedUser,
getUserDetails
} = require("./handlers/users");
// Workflow Routes
app.get("/Workflows", getAllWorkflows);
...
// user route
app.post("/user", FBAuth, addUserDetails);
app.post("/user/image", FBAuth, uploadImage);
...
// cloud functions are better than firebase library because of load time.
exports.api = functions.https.onRequest(app);
here is the package.json file.
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"serve": "firebase serve --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"dependencies": {
"busboy": "^0.3.1",
"cors": "^2.8.5",
"express": "^4.17.1",
"firebase": "^7.21.1",
"firebase-admin": "^8.9.0",
"firebase-functions": "^3.11.0",
"firebase-tools": "^7.11.0"
},
"devDependencies": {
"firebase-functions-test": "^0.1.6",
"node-gyp": "^5.0.7"
},
"private": true
}
With the backend i am fixing up, I use this sort of workthrough (if it helps!), which I am replacing with firebase stuff above - if that makes sense. It works currently, is accessible for signup and login functionality, the key part for me is just using firebase and firestore with it.
const config = require('../../config');
const express = require('express');
const app = express();
const server = require('http').createServer(app);
.....
server.listen(config.serverParams.port, config.serverParams.address, () => {
console.log(`Server running at http://${server.address().address}:${server.address().port}`);
});
....
app.use((req,res,next)=>{
//can reaplce * with website we want to allow access
res.header('Access-Control-Allow-Origin', 'https://moodmap.app/stats');
next();
});
....
io.on('connection', socket => {
socket.use((packet, next) => {
.....
});
});
Really appreciate any guidance on this matter!
Firebase and firestore seems like a nice way to avoid reinventing the wheel, if only i could simply type npm start, and begin testing with postman the underlying functionality :s
The API is based off another side project i did, which is largely here for those interested in exploring it more.
https://github.com/Hewlbern/LightSpeed/tree/master/sigops
Very happy to just use the easiest way forward - I don't want to have any of the libraries on the client side though, as i want to make my front end super efficient. Thanks!
Cloud Functions does not allow you to listen on any ports in order to receive requests. It automatically handles incoming connections using the URL automatically provided during deployment. All incoming requests to that URL are routed to your function callback defined by the exported function built by functions.https.onRequest().
If you require the ability to listen to specific ports, Cloud Functions is not the right product for your use case. Cloud Functions can not be deployed on custom servers - it only works on infrastructure provided by Google.

Meteor-Up (mup) error after "mup init"

I am trying to use mup to deploy a meteor app to my DigitalOcean droplet.
What I have done so far
Followed instructions on "Meteor-Up" website http://meteor-up.com/getting-started.html.
Installed mup via "npm install --global mup"
Created ".deploy" folder in my app directory. Ran "mup init".
Configured file "mup.js" file for my app, ran "mup setup".
Here is where I ran into an error. Upon running "mup setup", I am hit with the following error. [
What I tried:
I suspected that there could have been an issue with my syntax when configuring the mup.js file. After double-checking and not finding any error, I decided to re-install mup, and try running "mup setup" without modifying the "mup.js" file. However, I still receive the same error message.
Furthermore, after running "mup init", I can no longer run "mup" either, as I receive the same error as seen above. I suspect therefore that the issue is with the mup.js file. I have attached the generic version provided by meteor-up below (which still causes the error seen above).
module.exports = {
servers: {
one: {
// TODO: set host address, username, and authentication method
host: '1.2.3.4',
username: 'root',
// pem: './path/to/pem'
// password: 'server-password'
// or neither for authenticate from ssh-agent
}
},
app: {
// TODO: change app name and path
name: 'app',
path: '../app',
servers: {
one: {},
},
buildOptions: {
serverOnly: true,
},
env: {
// TODO: Change to your app's url
// If you are using ssl, it needs to start with https://
ROOT_URL: 'http://app.com',
MONGO_URL: 'mongodb://localhost/meteor',
},
// ssl: { // (optional)
// // Enables let's encrypt (optional)
// autogenerate: {
// email: 'email.address#domain.com',
// // comma separated list of domains
// domains: 'website.com,www.website.com'
// }
// },
docker: {
// change to 'abernix/meteord:base' if your app is using Meteor 1.4 - 1.5
image: 'abernix/meteord:node-8.4.0-base',
},
// Show progress bar while uploading bundle to server
// You might need to disable it on CI servers
enableUploadProgressBar: true
},
mongo: {
version: '3.4.1',
servers: {
one: {}
}
}
};
Any help would be greatly appreciated!
Thank you
The error dialog you posted shows a syntax error at line 10, character 5.
If you take a look:
module.exports = {
servers: {
one: {
// TODO: set host address, username, and authentication method
host: '1.2.3.4',
username: 'root',
// pem: './path/to/pem'
// password: 'server-password'
// or neither for authenticate from ssh-agent
}
^^^ This character
},
It's a closing brace which JS was not expecting. So why was it unexpected, lets move back to the last valid syntax:
module.exports = {
servers: {
one: {
// TODO: set host address, username, and authentication method
host: '1.2.3.4',
username: 'root',
^^^ This character
// pem: './path/to/pem'
// password: 'server-password'
// or neither for authenticate from ssh-agent
}
},
Well, looks like a comma which isn't followed by another key-value pair. Also known as a syntax error.
Take the comma out and things should be fine again!
I faced this same issue today. The problem is that Windows is trying to execute the mup.js file as a JScript script.
Here is the solution from the Meteor Up Common Problems page:
Mup silently fails, mup.js file opens instead, or you get a Windows script error
If you are using Windows, make sure you run commands with mup.cmd instead of mup , or use PowerShell.
That is, instead of mup setup, run mup.cmd setup.

Can't get response data with Oauth2/BaseCamp API

I am an "advanced beginner" with javascript API's so my needs maybe sophomoric, but after pounding my head against the wall all night appreciate any basic guidance you can provide. I am trying to authenticate an app using Oauth2 to hit my BaseCamp site.
I am using Grant Express and have registered my app successfully such that I received client_ID, client_secret and redirect uri. For the redirect uri I added a folder called "auth" but the only thing in it is an index.html file that is blank. So the redirect url is http://example.com/auth.
On my local machine I have created a directory called oauth and within it ran:
npm install express
npm install grant-express
I created a file app.js that looks like this:
var express = require('express')
, session = require('express-session')
var Grant = require('grant-express')
var config = {
server: {
protocol: "http",
host: "127.0.0.1:3000"
},
basecamp: {
key: "key_from_basecamp",
secret: "secret_from_basecamp",
callback: "/basecamp/callback"
}
}
var app = express()
app.use(session({secret:'grant',
resave: true,
saveUninitialized: true}))
app.use(new Grant(config))
app.get("/basecamp/callback", function (req, res) {
console.log(req.query)
res.end(JSON.stringify(req.query, null, 2))
})
app.listen(3000, function () {
console.log('Express server listening on port ' + 3000)
})
The package.json file looks like this:
{
"name": "auth",
"version": "1.0.0",
"description": "",
"main": "app.js",
"dependencies": {
"express": "^4.13.4",
"grant-express": "^3.6.0"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
I go to the terminal and enter node app.js and get the response: Express server listening on port 3000. All good right?
When I go to my browser and type in http://localhost:3000/connect/basecamp the url does redirect to: https://launchpad.37signals.com/authorization/new?client_id=client_id_from_basecamp&response_type=code&redirect_uri=http%3A%2F%2F127.0.0.1%3A3000%2Fconnect%2Fbasecamp%2Fcallback&type=web_server
but the page contains this error: :error: Provided redirect_uri is not approved
If I got to: http://localhost:3000/connect/basecamp/callback
I see this error (also in the console of the server) { error: { error: 'Grant: OAuth2 missing code parameter' } }
In the Basecamp API documentation it says:
Configure your OAuth 2 library with your client_id, client_secret, and redirect_uri. Tell it to use https://launchpad.37signals.com/authorization/new to request authorization and https://launchpad.37signals.com/authorization/token to get access tokens. What is "it" and how, exactly would I tell it to use these urls? Do I add these url's into my app.js file as objects? Or do I go into another file? Do I need to add something into http://example.com/auth?
Not sure where to go from here.... Many thanks for any assistance.
The problem was my redirect url. It should be
http://localhost:3000/connect/basecamp/callback On to new errors!

Categories