I am trying to complete an oauth-1 handshake. My backend is hosted on Google Functions. I'll walk through the flow quickly for context:
It seems to me like at every invocation a new session is being made, regardless of whether there already is a session in existence. If I examine the session at step 1 and step 2, the timestamps on them are different, making me think that rather than retrieving the session from step 1, step 2 is making a new one -- which could very well be because of how I am doing app.use(session)
.
List of the technologies I am using:
Here is my backend implementation for this:
const url = require('url');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const express = require("express");
const app = express();
const cors = require("cors")
const session = require('express-session')
const FirebaseStore = require('connect-session-firebase')(session);
// Etsy OAuth
// For Etsy OAuth
const etsyjs = require('etsy-js');
const client = etsyjs.client({
key: process.env.ETSY_KEY,
secret: process.env.ESTY_SECRET,
callbackURL: '<location>/authorize'
});
const ref = admin.initializeApp({
credential: admin.credential.cert(json), //json retrieved and put here
databaseURL: 'https://<app>.firebaseio.com'
});
app.use(cors())
app.use(session({
store: new FirebaseStore({
database: ref.database(),
}),
secret: 'My secret',
resave: true,
saveUninitialized: true,
name: '__session',
cookie: {
maxAge : 60000,
secure: false,
httpOnly: false
}
}
));
// Step 1 for backend of OAuth
app.get('/begin-oauth', (req, res) => {
res.setHeader('Cache-Control', 'private'); // I read somewhere this needs to be set, but I am not seeing a difference either way with it.
return client.requestToken((err, response) => {
if (err) {
return console.log(err);
}
req.session.token = response.token;
req.session.sec = response.tokenSecret;
res.status('200').send(response) // returning url to send the user there via frontend.
});
});
// Step 2 for backend of OAuth
app.get('/authorize', (req, res) => {
let query, verifier;
query = url.parse(req.url, true).query;
verifier = query.oauth_verifier;
// session at this point should have token and sec stored from before but are not present.
return client.accessToken(req.session.token, req.session.sec, verifier, (err, response) => {
if (err) {
console.log(err);
}
req.session.token = response.token;
req.session.sec = response.tokenSecret;
// Finish up.
});
});
Okay this is now all working. There were a few things that made it work.
return await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
}).then(...)
var corsOptions = {
credentials: true,
origin: true
}
app.use(cors(corsOptions))
And here is what I changed to fix this:
app.use(function(req, res, next) {
var allowedOrigins = ['http://localhost:3000', 'http://localhost:5000', 'https://www.<site>.com', 'https://<app-location>.cloudfunctions.net', 'https://<app>.firebaseio.com']
var origin = req.headers.origin;
functions.logger.log('Checking headers:')
functions.logger.log(origin)
functions.logger.log(req.headers)
if(allowedOrigins.indexOf(origin) > -1){
res.setHeader('Access-Control-Allow-Origin', origin);
}
res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', true);
return next();
});
and I updated the cookie to be:
cookie: {
maxAge: 30*24*60*60*1000,
secure: true,
httpOnly: false,
sameSite: 'none'
}
^ in particular, I set secure: true
and sameSite: 'none'