I am new to firebase and wanting to use their HTTP cloud functions. When I try to go to any endpoint (not using the emulator - eg https://us-central1-xxxxxxxx.cloudfunctions.net/app/api/admin/studio) I am getting CORS errors.
Here is an example of my code. I have no security rules set currently (still in development). The code below works perfect when using the firebase emulator. Just not using the "live" .cloudfunctions link.
Is there a permission or set up I am missing? This endpoint works if you access this directly via the browser or POSTMAN, just not from the react app.
An example of the error from the react app is:
Origin https://xxxxxxxxxxx is not allowed by Access-Control-Allow-Origin.
Fetch API cannot load https://us-central1-xxxxxxxx.cloudfunctions.net/app/api/admin/studio due to access control checks.
index.js
const functions = require("firebase-functions")
const express = require("express")
const app = express()
const cors = require("cors")({ origin: true })
app.use(cors)
const studio = require("./http/studio.js")
app.post("/api/admin/studio", studio.add)
exports.app = functions.https.onRequest(app)
db.js
const admin = require("firebase-admin")
admin.initializeApp()
module.exports = admin.firestore()
http/studio.js
const db = require("../db")
const error = require("./error")
exports.add = (req, res) => {
const { data } = req.body
if (!data) {
return error.no_data(res)
}
return db
.collection("data")
.doc("studio")
.update({ values: admin.firestore.FieldValue.arrayUnion(data) })
.then(res.status(200).send("Data updated successfully"))
.catch(err => error.updating(res, err))
}
I was able to fix with updating my index.js code to include a list of allowed origins.
const functions = require("firebase-functions")
const express = require("express")
const app = express()
const cors = require("cors")({ origin: true })
var allowedOrigins = ["https://domainone", "https://domaintwo"]
app.use(
cors({
origin: function(origin, callback) {
if (!origin) return callback(null, true)
if (allowedOrigins.indexOf(origin) === -1) {
var msg = "The CORS policy for this site does not " + "allow access from the specified Origin."
return callback(new Error(msg), false)
}
return callback(null, true)
}
})
)
const studio = require("./http/studio.js")
app.post("/api/admin/studio", studio.add)
exports.app = functions.https.onRequest(app)
Related
Cookies are not set in browser. I am use the node as backend. I am try to search problem some person tell that's cookies will not setting because of I am using react as front and node as backed both are run on same virtual server that is localhost. That why it happen.
this is my code please help.
User.js
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const RegisterModel = require("../Model/RegisterModel")
const signIn = async (req,res)=>{
try {
const data = await RegisterModel.findOne({Email:req.body.email})
const passwordMatch = await bcrypt.compare(req.body.password,data.Password)
const token = await jwt.sign({Email : data.Email}, process.env.SECRET)
if(!data) return res.status(404).json({islogin:false, message: "User doesn't exist" })
if(!passwordMatch) return res.status(400).json({islogin:false,message: "Incorrect Password"})
if(passwordMatch){
res.cookie('newToken',token, { maxAge: 900000, httpOnly: false});
res.status(200).send({id:data._id,email:data.Email,name:data.Name,islogin:true,token:token})
}
} catch (error) {
res.status(404).json({islogin:false,message:"User doesn't exist"})
console.log(error)
}
}
module.exports = {signIn,signUp};
app.js
const express = require('express');
var cookieParser = require('cookie-parser')
const app = express();
app.use(cookieParser())
const dotenv = require('dotenv');
dotenv.config()
var cors = require('cors')
const PORT = process.env.PORT ;
const router = require("./Router/Router")
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({extended:false}));
app.use(router);
require("./Connection/Connection")
app.listen(PORT,()=>{
console.log(`Listen at Port ${PORT}` )
})
for set credentials data into browser it is necessary to run both side on same domain backend should be run on localhost or 127.0.0.1 and frontend should be run on localhost or 127.0.0.1 respectively.
or
backend and frontend run on =localhost or
backend and frontend run on =127.0.0.1
if you are not sure then issue error's show on console. here
browser suggest you error regarding cookies.
also set cors policy on backend side like =
cors({origin:"http:localhost:frontendPORT", credentials:true})
frontend side on http request, must be set with credentials= true
this method work for me after spending 4 days.
I'm wondering if anyone could help me. I have built a custom NextJS app on Heroku intended to be embedded on my Shopify storefront using Shopify's app proxy. It's mostly working, so it is showing my app when I go to the proxy url within my Shopify store however all of the CSS & JS filepaths have been changed to my Shopify URL rather than remaining as my Heroku app URL.
I have seen someone else have this exact same problem: https://community.shopify.com/c/Shopify-APIs-SDKs/App-Proxy-Sending-index-html-throws-404-on-the-JS-and-CSS-files/td-p/586595
However when I try to implement this solution it keeps breaking the app. I'm relatively new to Node.js/Next.js so while I'm still learning I largely depend on documentation to follow to set up or resolve this type of issue. However, I cannot find any tutorials or documentation specific to this issue.
Is anyone able to advise what I need to do within my server.js to make the '/_next/static/...' files remain to be pulled from my Heroku app URL rather than the Shopify URL when being viewed from the proxy URL? I have included the contents of my server.js file below.
require('isomorphic-fetch');
const dotenv = require('dotenv');
const Koa = require('koa');
const next = require('next');
const { default: createShopifyAuth } = require('#shopify/koa-shopify-auth');
const { verifyRequest } = require('#shopify/koa-shopify-auth');
const { default: Shopify, ApiVersion } = require('#shopify/shopify-api');
const Router = require('koa-router');
dotenv.config();
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SHOPIFY_API_SCOPES.split(","),
HOST_NAME: process.env.SHOPIFY_APP_URL.replace(/https:\/\//, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const ACTIVE_SHOPIFY_SHOPS = {};
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
createShopifyAuth({
apiKey: process.env.SHOPIFY_API_KEY,
secret: process.env.SHOPIFY_API_SECRET,
scopes: ["read_products"],
afterAuth(ctx) {
const { shop, scope } = ctx.state.shopify;
ACTIVE_SHOPIFY_SHOPS[shop] = scope;
ctx.redirect(`/?shop=${shop}`);
},
}),
);
const handleRequest = async (ctx) => {
console.log('ctx.req.url', ctx.req.host);
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
};
router.get("/", async (ctx) => {
const shop = ctx.query.shop;
ACTIVE_SHOPIFY_SHOPS[shop] = ctx.query.shop;
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
});
router.get("/_next/*", handleRequest);
router.get("(.*)", verifyRequest(), handleRequest);
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
Many thanks
A Proxy is simply a callback to your App, where as a response you provide either Liquid, or JSON. If you are trying to return links to assets such as CSS or JS, links are just strings. So can just send them as JSON key:value pairs.
A simple workaround is to use assetPrefix on next.config.js.
The assetPrefix will be prefixed for the /_next/ path automatically, so the assets are refered with absolute URL.
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
assetPrefix: isProd ? 'https://yourappdomain.com' : '',
}
https://nextjs.org/docs/api-reference/next.config.js/cdn-support-with-asset-prefix
We have a front end react app that has MSAL login that uses aws api gateway api endpoints for backend operations. After the login process I would like to send the bearer Token to the api and get it authenticated. From what I have read online you do this by using node.js and passport.authenticate(). Problem is trying to make this work in aws api gateway. So I came up with a scheme to do the authentication through a Authorizer lambda. 1) Use aws-serverless-express to run express as api proxy in lambda 2) Use passport-azure-ad module to set bearerstrategy. 3) run passport.authenticate() to authenticate token. 4) upon valid token return allow policy from lambda 5) The api request will continue on
I just placed the following files and required node modules into a node.js lambda. So this essentially is a middlewear between client and api. If token is valid will allow request to go through.
During my tests I am getting this error when it applies the bearerstrategy:
{
"name": "AzureAD: Bearer Strategy",
"hostname": "169.254.43.173",
"pid": 8,
"level": 30,
"msg": "authentication failed due to: token is not found",
"time": "2020-08-24T23:48:35.497Z",
"v": 0
}
Would be great if there is a simpler way to authenticate a Bearer token.
Lambda index.js file:
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app')
const server = awsServerlessExpress.createServer(app)
exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context)
config.js
'use strict';
const config = {
identityMetadata: "https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration",
clientID: "xxxxxxxxxxxxxxxxxxxx",
validateIssuer: true,
loggingLevel: 'info',
passReqToCallback: false,
ignoreExpiration: true
};
module.exports = config
app.js file
'use strict'
const express = require('express')
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
const passport = require("passport");
const config = require('./config');
const BearerStrategy = require('passport-azure-ad').BearerStrategy;
const bearerStrategy = new BearerStrategy(config, (token, done) => {
// Send user info using the second argument
done(null, {}, token);
}
);
const app = express();
app.use(passport.initialize());
const router = express.Router()
passport.use(bearerStrategy);
router.use(awsServerlessExpressMiddleware.eventContext())
var generatePolicy = function(effect, resource) {
var authResponse = {};
authResponse.principalId = 'user';
if (effect && resource) {
var policyDocument = {};
policyDocument.Version = '2012-10-17'; // default version
policyDocument.Statement = [];
var statementOne = {};
statementOne.Action = 'execute-api:Invoke'; // default action
statementOne.Effect = effect;
statementOne.Resource = "*";
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
return authResponse;
}
var generateAllow = function(resource) {
return generatePolicy('Allow', resource);
}
router.get('/', passport.authenticate('oauth-bearer', {session: false}),
(req, res) => {
res.send(generateAllow(req.apiGateway.event.methodArn))
}
);
// The aws-serverless-express library creates a server and listens on a Unix
// Domain Socket for you, so you can remove the usual call to app.listen.
// app.listen(3000)
app.use('/', router)
// Export your express server so you can import it in the lambda function.
module.exports = app
I will explain the problems in more detail.
I'm trying to do a really simple little practice. Through a link, the ID of an Instagram post is passed as a parameter.
After this, '? __ a = 1' is added to the URL for subsequent data processing once the JSON object has been obtained.
On localhost this works fine and I get the JSON object. But once deployed as a function in Firebase, although it accepts the request without errors, it does not return a JSON object. Instead it returns HTML content, like this:
"<!DOCTYPE html>\n<html lang=\"en\" class=\"no-js not-logged-in client-root\">\n <head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\n <title>\nLogin • Instagram\n</title>\n\n
....
Does anyone know what is causing this problem?
...
Localhost:
Deployed like a Firebase Function:
I briefly attach the code of my application.
index.js
const functions = require('firebase-functions');
const server = require("./src/server");
const d = functions
.runWith({
memory: "2GB",
timeoutSeconds: 120
})
.https
.onRequest(server);
module.exports = {d};
server/index.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
app
.use(cors({origin: true}))
.use(bodyParser.json())
.use(bodyParser.urlencoded({extended: false}))
.use("/", require("./route"))
.get('*', (_, res) =>
res.status(404)
.json({success: false, data: "Endpoint not found"}));
module.exports = app;
server/route.js
const router = require("express").Router();
const controller = require("./controller");
router.get("/:url", controller.getImageVideo);
module.exports = router;
server/controller.js
'use strict'
const axios = require('axios');
async function getImageVideo(req, res) {
const URL_id = req.params.url;
const URL = 'https://www.instagram.com/p/' + URL_id + '?__a=1';
const metadata = await axios.get(URL);
const test = metadata.data;
return res
.json({
test
});
}
module.exports = {
getAllLanguages,
getImageVideo
}
I'm new to server development and trying to get my cloud firebase function working. I'm getting a res.send() is not a function on my firebase Log when my stripe webhook fires and I'm not too sure why. I'm pretty sure I'm missing something. The only conclusion I can come up with is that it is because I'm not using App from const app = express(); but I'm seeing it used elsewhere.
Any and all help/direction is appreciated
I'm getting the following:
res.send() is not a function
res.end() is not a function
res.json() is not a function
Anything that is dealing with res seems to be an issue.
Here is my code:
const admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
const Chatkit = require('#pusher/chatkit-server');
const stripeToken = require('stripe')(functions.config().stripe.token);
const stripeWebhooks = require('stripe')(functions.config().keys.webhooks);
const express = require('express');
const cors = require('cors');
const endpointSecret = functions.config().keys.signing;
const request = require('request-promise');
const app = express();
app.use(cors({ origin: true }));
exports.stripeCreateOathResponseToken = functions.https.onRequest(cors((req, res) => {
const endpointSecret = "whsec_XXXXXXXXXXXXXXXXXXX";
// Get the signature from the request header
let sig = req.headers["stripe-signature"];
let rawbody = req.rawBody;
// res.send("testing res.send()"); // doesnt work. cant use res.send() here
console.log("rawbody: " + rawbody);
console.log("request.body: " + req.body);
console.log("request.query.code: " + req.query.code);
console.log("request.query.body: " + req.query.body);
console.log("request.query.state: " + req.query.state);
// console.log("res.body: " + res.json({received: true}));
stripeWebhooks.webhooks.constructEvent(req.rawBody, sig, endpointSecret);
res.end("testing res.end()"); // doesnt work. cant use res.end() here
}));
That doesn't look like the correct way to use the cors module with Cloud Functions for Firebase. Try this instead:
exports.stripeCreateOathResponseToken =
functions.https.onRequest((req, res) => {
return cors(req, res, () => {
// put your function code here
});
});
Cribbed from an official sample.