Error 403 Forbidden. No permission to access the URL - node.js

I am trying to migrate to firebase. But before that I gave it a small try by performing the following one. I have successfully added and deployed cloud function but am getting a error
Error: Forbidden
Your client does not have permission to get URL /app/lol from this server.
This is occurring on execution of following code:
const functions = require('firebase-functions');
const express = require('express');
const app = express()
// tried adding this as middleware
// const cors = require('core'({origin: true}))
var admin = require('firebase-admin');
// app.use(cors)
var serviceAccount = require("./ServiceAccount.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<my-app>.firebaseio.com/"
});
app.get('/lol', (req, res) => {
res.send(`${Date.now()}`);
})
exports.site = functions.https.onRequest(app);
my firebase.json is as following:
{
"database": {
"rules": "database.rules.json"
},
"hosting": {
"public": "public",
"rewrites" :[{
"source" : "**",
"function" : "app"
}],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
when i go to the route, it takes me to the google auth and after signing through correct account. I get the error.
Whats the issue here!

2 alternative ways to solve:
you should change
exports.site = functions.https.onRequest(app);
to
exports.app = functions.https.onRequest(app);
you could modify firebase.json
from
"rewrites" :[{
"source" : "**",
"function" : "app"
}],
to
"rewrites" :[{
"source" : "**",
"function" : "site"
}],

Related

Local debugging endpoint with localhost and remote endpoint with custom domain are not consistent

I have a Firebase + Cloud Function API + Express API with the following files:
/functions/index.js
const functions = require('firebase-functions');
const express = require('express');
const app = express();
app.get('/api/echo', (req, res) => {
res.status(200).json({
message: req.query.message,
});
});
exports.api = functions.https.onRequest(app);
/firebase.json
{
"hosting": {
"rewrites": [
{
"source": "/api/**",
"function": "api",
"region": "us-central1"
}
]
},
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log"
]
}
]
}
To test the app on LOCAL I run the following command:
$ firebase emulators:start --inspect-functions
To access the endpoint on LOCAL I go to the following url:
[1] http://localhost:5001/[my-project]/us-central1/api/api/echo/?message=Hello+World
To deploy the app to Firebase (REMOTE) I run the following command:
$ firebase deploy --only hosting,functions
To access the endpoint with Google domain I go to the following url:
[2] https://us-central1-[my-project].cloudfunctions.net/api/api/echo/?message=Hello+World
To access the endpoint with my custom domain I go to the following url:
[3] https://www.[mydomain.tld]/api/echo/?message=Hello+World
With all 3 urls above I get the following (expected) output:
{"message":"Hello World"}
My problem is: On urls: [1] and [2] I need to specify /api twice (please check above). I would like to configure things around in order to just need to specify: /api once on urls: [1], [2], [3]. It doesn't look good to me having to specify: /api twice.
It is a requirement for me to access the endpoints after: /api/ because on the parent level I have a web app that uses the endpoints.
Any idea on how to do this?
Thanks!

Production React App Failing With 429 Error

I have built a react app webpage, i use node, express and react. I serve it within an ec2 ubuntu server with nginx, i also installed ssl and configured DNS but when I load the page, the first time it gives no problems, but when reloaded, i get this Server responded with 429 status code
The page is very simple itself, but stills failing and i can't solve the problem, i have read a lot of posts and blogs to fix it but none has worked (this only happens in production, in dev environment i get no error when running my node app).
Some of those said that you had to lazy load images and i did it, i have also tried loading components in timeout so requests are made every 1.5 seconds...
The main files that give me problems are the manifest.json and favicon.ico, they are accesible by url so i can't understand why (another 429 example).
Node server.js
Routes has nothing, just console logs
require('dotenv').config();
const express = require("express");
const app = express();
const path = require("path");
const cors = require("cors");
const allowedOrigins = [`http://localhost:${process.env.PORT}`];
var corsOptions = {
origin: function (origin, callback) {
if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
};
app.use(cors(corsOptions));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use(express.static(path.join(__dirname, "/public")));
app.use("/", require("./routes/routes"));
app.get("*", (_, res) => res.redirect("/"))
app.listen(process.env.PORT, function () {
console.log(`Listening on port ${process.env.PORT}`);
});
App directory structure
This is my folders structure, public folder is the build that react script npm run build returns.
React app directory structure
Here you can see the structure, nothing special to what you get when run npx create-react-app. As you can see, there's a favicon.ico and manifest.json.
Manifest.json
{
"short_name": "Proximedica Bajío",
"name": "Proximedica Bajío - Oxígeno Medicinal",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
This is all, if you need me to provide some other file it would be a pleasure.
Thanks!

Express app on Firebase Functions locally

I created an Express app using Firebase Functions and am hosting the files on Firebase Hosting.
index.js (Firebase Functions):
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require('express');
const parse = require('body-parser');
const cors = require('cors');
admin.initializeApp();
const app = express();
app.use(cors({ origin: true }));
app.use(parse.json());
app.use(parse.urlencoded({ extended: false }));
app.post('/create-url', (req, res) => {
console.log(req.body);
res.send(req.body);
});
exports.app = functions.https.onRequest(app);
firebase.json:
{
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"function": "app"
}
]
},
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint"
]
},
"emulators": {
"functions": {
"port": 5001
},
"firestore": {
"port": 8080
},
"hosting": {
"port": 5000
},
"ui": {
"enabled": true,
"port": 4000
}
}
}
When I make an HTTP request to http://localhost:5000/create-url, req.body is emtpy, but when I make a request to http://localhost:5001/PROJECT_NAME_HERE/us-central1/app/create-url (I've hidden the project name), it works properly. I'm using Postman to make the requests, but it isn't working with my front-end code either :(. If I deploy to Hosting and Functions and access the app through the web.app domain, it works. I'm running firebase emulators:start to run locally.
Thanks in advance for your help!
Check out the bottom section of this page https://firebase.google.com/docs/emulator-suite/install_and_configure. 'Generate an auth token (Hosting emulator only)'.
Basically you have to generate an auth token and pass it as a flag in your build script or add it to your ci environment variables.
Let me know if it helps!

How do I mount an node-oidc-provider against a mountPath using ExpressJS?

I am using the node-oidc-provider (v6.29.3) library to build a simple OIDC Connect mock-service and am having issues trying to mount the provider against a specific mountPath. It all works fine if mounted against / but trying to mount against /oidc is not working as the internals of the node-oidc-provider ignore the mountPath.
My setup is roughly like this:
const path = require('path')
const express = require('express')
const { Provider } = require('oidc-provider')
const configuration = require('src/utils/oidc')
const Account = require('src/account')
configuration.findAccount = Account.findAccount
const app = express()
app.set('views', path.join(__dirname, '..', 'views'))
app.set('view engine', 'ejs')
const mountPath = '/oidc'
const issuer = 'http://localhost:3000' + mountPath
const provider = new Provider(issuer, configuration)
app.use(mountPath, provider.callback)
app.listen(3000).then(() => {
console.log('started')
})
I am able to connect to http://localhost:3000/oidc/.well-known/openid-configuration and receive
{
"authorization_endpoint":"http://localhost:3000/oidc/auth",
"device_authorization_endpoint":"http://localhost:3000/oidc/device/auth",
"claims_parameter_supported":false,
"claims_supported":[
"sub",
"email",
"givenName",
"surname",
"memberOf",
"publishers",
"sid",
"auth_time",
"iss"
],
"code_challenge_methods_supported":["S256"],
"end_session_endpoint":"http://localhost:3000/oidc/session/end",
"grant_types_supported":[
"implicit","authorization_code",
"refresh_token",
"urn:ietf:params:oauth:grant-type:device_code"
],
"id_token_signing_alg_values_supported":["HS256", "PS256", "RS256", "ES256"],
"issuer":"http://localhost:3000/oidc",
"jwks_uri":"http://localhost:3000/oidc/jwks",
"response_modes_supported":["form_post","fragment","query"],
"response_types_supported":["code id_token","code","id_token","none"],
"scopes_supported":["openid","offline_access","email","profile"],
"subject_types_supported":["public"],
"token_endpoint_auth_methods_supported":[
"none",
"client_secret_basic",
"client_secret_jwt",
"client_secret_post",
"private_key_jwt"
],
"token_endpoint_auth_signing_alg_values_supported":["HS256", "RS256", "PS256", "ES256", "EdDSA"],
"token_endpoint":"http://localhost:3000/oidc/token",
"request_object_signing_alg_values_supported":["HS256", "RS256", "PS256", "ES256", "EdDSA"],
"request_parameter_supported":false,
"request_uri_parameter_supported":true,
"require_request_uri_registration":true,
"userinfo_endpoint":"http://localhost:3000/oidc/me",
"userinfo_signing_alg_values_supported":["HS256","PS256","RS256","ES256"],
"introspection_endpoint":"http://localhost:3000/oidc/token/introspection",
"introspection_endpoint_auth_methods_supported":[
"none",
"client_secret_basic",
"client_secret_jwt",
"client_secret_post",
"private_key_jwt"
],
"introspection_endpoint_auth_signing_alg_values_supported":["HS256", "RS256", "PS256", "ES256", "EdDSA"],
"revocation_endpoint":"http://localhost:3000/oidc/token/revocation",
"revocation_endpoint_auth_methods_supported":[
"none",
"client_secret_basic",
"client_secret_jwt",
"client_secret_post",
"private_key_jwt"
],
"revocation_endpoint_auth_signing_alg_values_supported":["HS256", "RS256", "PS256", "ES256", "EdDSA"],
"claim_types_supported":["normal"]
}
Using a simple test all I log in and my logs show (correctly)
GET /oidc/auth
but then, internally, it redirects to:
GET /interaction/znBzRfhyoBTCg1cFcLult
I need the internal redirect to go to
GET /oidc/interaction/znBzRfhyoBTCg1cFcLult
How do I tell the OIDC Provider to redirect via the given mountPath instead of /?
You will have to configure the interactions.url helper. See documentation for more details.
Later on you will have to build your own end-user interactions and with it you will have to configure this helper anyway.

Firebase-hosting can't get to api routes node

I have a route for '/' but it serves the public html index file instead, I tried changing the root directory of my api to /api/** but it gives me a 404 error.
it works quiet well when I run it locally but when I deploy it I run into the issue of only having the index.html file.
here is the firebase.json file
{
"hosting": {
"public": "public",
"rewrites":[
{
"source":"/api/**",
"functions":"app"
}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
and the index.js folder
const functions = require('firebase-functions')
const express = require('express')
\\.
\\.
\\requiring routes and middleware
app.use(helmet())
app.use(express.json())
app.use(cookieParser())
app.use(cors({
origin:"*",
credentials:true
}))
app.get('/',(req,res)=>{
res.status(200).send("works");
})
app.use(locationActions)
app.use(filterActions)
app.use('/auth',userAuth)
app.use('/adm',AdminRoutes)
app.use('/prod',prodActions)
app.use('/user',userActions)
exports.app = functions.https.onRequest(app);
.send() doesn't seem to work quiet well with firebase I just have to say something like response.json({message}), this will actually send the response. also mongoose connection is prohibited as I was using a free account so any connection outside firebase is rejected.

Resources