Identity Toolkit unrecognized config parameter - google-identity-toolkit

The following error shows up when I run the gitkit widget:
[ 0.004s] [identitytoolkit] Invalid config: "callbackUrl"rj # gitkit.js:236pj.addLogRecord # gitkit.js:236Li.log # gitkit.js:219Q # gitkit.js:236zl # gitkit.js:273(anonymous function) # gitkit.js:306(anonymous function) # gitkit-widget.html?mode=select:29
My code is the following:
var config = {
signInSuccessUrl: "/",
apiKey: "AIzaSyAt3gELMqBCdn9U8FLSXbtCJbizHSX3kng",
siteName: "Google Apps Training",
signInOptions: ["google","facebook", "microsoft"],
//idps: ["google", "facebook", "microsoft"],
/*callbacks: {
signInSuccess: function(tokenString, accountInfo, signInSuccessUrl) {
console.log("callback");
console.log(tokenString);
console.log(accountInfo);
console.log(signInSuccessUrl);
return true;
}
},*/
callbackUrl: "http://localhost:8080/signin"
};
// The HTTP POST body should be escaped by the server to prevent XSS
window.google.identitytoolkit.start(
'#gitkitWidgetDiv', // accepts any CSS selector
config);
Here is the gitkit documentation sample available at https://developers.google.com/identity/toolkit/web/setup-frontend
var config = {
apiKey: 'AIza...',
signInSuccessUrl: '/',
signInOptions: ["google", "password"],
oobActionUrl: '/',
siteName: 'this site',
// Optional - function called after sign in completes and before
// redirecting to signInSuccessUrl. Return false to disable
// redirect.
// callbacks: {
// signInSuccess: function(tokenString, accountInfo,
// opt_signInSuccessUrl) {
// return true;
// }
// },
// Optional - key for query parameter that overrides
// signInSuccessUrl value (default: 'signInSuccessUrl')
// queryParameterForSignInSuccessUrl: 'url'
// Optional - URL of site ToS (linked and req. consent for signup)
// tosUrl: 'http://example.com/terms_of_service',
// Optional - URL of callback page (default: current url)
// callbackUrl: 'http://example.com/callback',
// Optional - Cookie name (default: gtoken)
// NOTE: Also needs to be added to config of the ‘page with
// sign in button’. See above
// cookieName: ‘example_cookie’,
// Optional - UI configuration for accountchooser.com
/*acUiConfig: {
title: 'Sign in to example.com',
favicon: 'http://example.com/favicon.ico',
branding: 'http://example.com/account_choooser_branding'
},
*/
// Optional - Function to send ajax POST requests to your Recover URL
// Intended for CSRF protection, see Advanced Topics
// url - URL to send the POST request to
// data - Raw data to include as the body of the request
//completed - Function to call with the object that you parse from
// the JSON response text. {} if no response
/*ajaxSender: function(url, data, completed) {
},
*/
};
// The HTTP POST body should be escaped by the server to prevent XSS
window.google.identitytoolkit.start(
'#gitkitWidgetDiv', // accepts any CSS selector
config,
'JAVASCRIPT_ESCAPED_POST_BODY');
So, if the most recent sample code shows "callbackUrl" as an available optional parameter, why gitkit js does not recognizes it as valid?
Is there a place where I can check all the available parameters?
Regards.

The callbackUrl is no longer a valid field. The documentation is incorrect and will be updated promptly. We apologize for that and we thank you for bringing this up to us. The widget current url will be automatically used as the IDP callback url so be sure to add your widget url in your IDP (google, facebook, etc) oauth client setup (callback url).

Related

oak on Deno - How do I build a URL to a route?

I come from a land of ASP.NET Core. Having fun learning a completely new stack.
I'm used to being able to:
name a route "orders"
give it a path like /customer-orders/{id}
register it
use the routing system to build a URL for my named route
An example of (4) might be to pass a routeName and then routeValues which is an object like { id = 193, x = "y" } and the routing system can figure out the URL /customer-orders/193?x=y - notice how it just appends extraneous key-vals as params.
Can I do something like this in oak on Deno?? Thanks.
Update: I am looking into some functions on the underlying regexp tool the routing system uses. It doesn't seem right that this often used feature should be so hard/undiscoverable/inaccessible.
https://github.com/pillarjs/path-to-regexp#compile-reverse-path-to-regexp
I'm not exactly sure what you mean by "building" a URL, but the URL associated to the incoming request is defined by the requesting client, and is available in each middleware callback function's context parameter at context.request.url as an instance of the URL class.
The documentation provides some examples of using a router and the middleware callback functions that are associated to routes in Oak.
Here's an example module which demonstrates accessing the URL-related data in a request:
so-74635313.ts:
import { Application, Router } from "https://deno.land/x/oak#v11.1.0/mod.ts";
const router = new Router({ prefix: "/customer-orders" });
router.get("/:id", async (ctx, next) => {
// An instance of the URL class:
const { url } = ctx.request;
// An instance of the URLSearchParams class:
const { searchParams } = url;
// A string:
const { id } = ctx.params;
const serializableObject = {
id,
// Iterate all the [key, value] entries and collect into an array:
searchParams: [...searchParams.entries()],
// A string representation of the full request URL:
url: url.href,
};
// Respond with the object as JSON data:
ctx.response.body = serializableObject;
ctx.response.type = "application/json";
// Log the object to the console:
console.log(serializableObject);
await next();
});
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());
function printStartupMessage({ hostname, port, secure }: {
hostname: string;
port: number;
secure?: boolean;
}): void {
if (!hostname || hostname === "0.0.0.0") hostname = "localhost";
const address =
new URL(`http${secure ? "s" : ""}://${hostname}:${port}/`).href;
console.log(`Listening at ${address}`);
console.log("Use ctrl+c to stop");
}
app.addEventListener("listen", printStartupMessage);
await app.listen({ port: 8000 });
In a terminal shell (I'll call it shell A), the program is started:
% deno run --allow-net so-74635313.ts
Listening at http://localhost:8000/
Use ctrl+c to stop
Then, in another shell (I'll call it shell B), a network request is sent to the server at the route described in your question — and the response body (JSON text) is printed below the command:
% curl 'http://localhost:8000/customer-orders/193?x=y'
{"id":"193","searchParams":[["x","y"]],"url":"http://localhost:8000/customer-orders/193?x=y"}
Back in shell A, the output of the console.log statement can be seen:
{
id: "193",
searchParams: [ [ "x", "y" ] ],
url: "http://localhost:8000/customer-orders/193?x=y"
}
ctrl + c is used to send an interrupt signal (SIGINT) to the deno process and stop the server.
I am fortunately working with a React developer today!
Between us, we've found the .url(routeName, ...) method on the Router instance and that does exactly what I need!
Here's the help for it:
/** Generate a URL pathname for a named route, interpolating the optional
* params provided. Also accepts an optional set of options. */
Here's it in use in context:
export const routes = new Router()
.get(
"get-test",
"/test",
handleGetTest,
);
function handleGetTest(context: Context) {
console.log(`The URL for the test route is: ${routes.url("get-test")}`);
}
// The URL for the test route is: /test

How to generate billing portal link for Stripe NextJS with Firebase extension?

I'm using the Stripe extension in Firebase to create subscriptions in a NextJS web app.
My goal is to create a link for a returning user to edit their payments in Stripe without authenticating again (they are already auth in my web app and Firebase recognizes the auth).
I'm using the test mode of Stripe and I have a test customer and test products.
I've tried
The Firebase Stripe extension library does not have any function which can just return a billing portal link: https://github.com/stripe/stripe-firebase-extensions/blob/next/firestore-stripe-web-sdk/markdown/firestore-stripe-payments.md
Use the NextJS recommended import of Stripe foudn in this Vercel blog
First I setup the import for Stripe-JS: https://github.com/vercel/next.js/blob/758990dc06da4c2913f42fdfdacfe53e29e56593/examples/with-stripe-typescript/utils/get-stripejs.ts
export default function Settings() {
import stripe from "../../stripe_utils/get_stripejs"
async function editDashboard() {
const dashboardLink = await stripe.billingPortal.sessions.create({
customer: "cus_XXX",
})
}
console.log(dashboardLink.url)
return (
<Button
onClick={() => editDashboard()}>
DEBUG: See payments
</Button>
)
}
This would result in an error:
TypeError: Cannot read properties of undefined (reading 'sessions')
Use the stripe library. This seemed like the most promising solution but from what I read this is a backend library though I tried to use on the front end. There were no errors with this approach but I figure it hangs on the await
import Stripe from "stripe"
const stripe = new Stripe(process.env.STRIPE_SECRET)
...
const session = await stripe.billingPortal.sessions.create({
customer: 'cus_XXX',
return_url: 'https://example.com/account',
})
console.log(session.url) // Does not reach here
Use a pre-made Stripe link to redirect but the user will have to authenticate on Stripe using their email (this works but I would rather have a short-lived link from Stripe)
<Button component={Link} to={"https://billing.stripe.com/p/login/XXX"}>
Edit payment info on Stripe
</Button>
Using POST HTTPS API call found at https://stripe.com/docs/api/authentication. Unlike the previous options, this optional will register a Stripe Dashboard Log event.
const response = await fetch("https://api.stripe.com/v1/billing_portal/sessions", {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
'Authorization': 'bearer sk_test_XXX',
'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *client
body: JSON.stringify(data), // body data type must match "Content-Type" header
})
The error is I'm missing some parameter parameter_missing -customer. So I'm closer to a resolution but I feel as if I should still be able to make the solution above work.
You should use Stripe library to create a billing portal session (your 2nd approach), and you might want to check your Dashboard logs and set the endpoint to /v1/billing_portal/sessions so that you can see if there are any errors during portal session creation.
Given my case, I chose to call the API itself instead of the libraries provided:
export default async function Stripe(payload, stripeEndpoint) {
const _ENDPOINTS = [
"/v1/billing_portal/sessions",
"/v1/customers",
]
let contentTypeHeader = "application/json"
let body = JSON.stringify(payload)
if _ENDPOINTS.includes(stripeEndpoint)) {
contentTypeHeader = "application/x-www-form-urlencoded"
body = Object.keys(payload).map(
entry => entry + "=" + payload[entry]).join("&")
}
try {
// Default options are marked with *
const stripeResponse = await fetch("https://api.stripe.com" + stripeEndpoint, {
method: "POST", // *GET, POST, PUT, DELETE, etc.
headers: {
"Authorization": "bearer " + STRIPE_PRIVATE_KEY,
"Content-Type": contentTypeHeader,
},
redirect: "follow", // manual, *follow, error
referrerPolicy: "no-referrer", // no-referrer, *client
body: body, // body data type must match "Content-Type" header
})
return await stripeResponse.json()
} catch (err) {
console.error(err)
}
}

Pass cookie to CloudFront origin but prevent from caching

I am using CloudFront as cache in front of my Symfony web application. To get a cache based on a user's role (admin, customer,...) I generate a user role based hash in a Lambda#Edge Viewer Request trigger. I pass that hash on as a request header to my origin as X-User-Context-Hash.
My problem is now that I need to pass the PHPSESSID cookie on to my origin to get the right response for caching, but I do not want to base the cache on the value of PHPSESSID. I do only need my cached response to be based on the value of X-User-Context-Hash but not on my session cookie.
The image below should explain my problem in detail
Is there any possibility to accomplish that?
Would appreciate any help.
Here's my Lambda#Edge Viewer Request trigger:
'use strict';
function parseCookies(headers) {
const parsedCookie = {};
if (headers.cookie) {
console.log(`${headers.cookie[0].value}`);
headers.cookie[0].value.split(';').forEach((cookie) => {
if (cookie) {
const parts = cookie.split('=');
parsedCookie[parts[0].trim()] = parts[1].trim();
}
});
}
return parsedCookie;
}
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
const https = require('https');
// Read session cookie
const parsedCookies = parseCookies(headers);
let cookie = '';
if (parsedCookies) {
if(parsedCookies['PHPSESSID']) {
cookie = `PHPSESSID=${parsedCookies['PHPSESSID']}`;
}
}
console.log(`Cookie: ${cookie}`);
// Send request to origin host at /_fos_user_context_hash
// passing the original session cookie
const options = {
hostname: `${request.headers.host[0].value}`,
port: 443,
path: '/_fos_user_context_hash',
method: 'HEAD',
headers: {
'Cookie': cookie,
'Accept': 'application/vnd.fos.user-context-hash',
'Vary' : 'Cookie'
}
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
// Read the X-User-Context-Hash from the hash endpoint
const headerName = 'X-User-Context-Hash';
let hash = 'anonymous';
if (res.headers[headerName.toLowerCase()]) {
hash = res.headers[headerName.toLowerCase()];
}
// Append X-User-Context-Hash before passing request on to CF
request.headers[headerName.toLowerCase()] = [{ key: headerName, value: hash }];
callback(null, request);
}).on('error', (e) => {
console.error(e);
// Forward request anyway
callback(null, request);
});
req.end();
}
;
Here's how I finally solved my problem:
CloudFront behavior
I configured the behavior not to forward any cookies to the origin, but only cache based on the headers Host and X-User-Context-Hash (see screenshot).
The following image explains my lambda#edge process:
In the "Viewer Request" trigger I read the user-based cookies named PHPSESSID and REMEMBERME and pass those values via the X-Session-Cookies header on.
If the there's a match for my request url and the given Host and X-User-Context-Hash headers, Cloud-Front returns the cached item and stops here.
If there's no match the "Origin Request" trigger is fired. When that event fires the custom header X-Session-Cookies is available. So I take the value from the X-Session-Cookies header and set the value of request.headers.cookie to that value. This step ensures that the PHPSESSID and REMEMBERME cookie are both passed to the origin before the page gets cached.
My Lambda#Edge functions:
The Viewer Request trigger:
'use strict';
function parseCookies(headers) {
const parsedCookie = {};
if (headers.cookie) {
console.log(`${headers.cookie[0].value}`);
headers.cookie[0].value.split(';').forEach((cookie) => {
if (cookie) {
const parts = cookie.split('=');
parsedCookie[parts[0].trim()] = parts[1].trim();
}
});
}
return parsedCookie;
}
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
const https = require('https');
let sessionId = '';
// Read session cookie
const parsedCookies = parseCookies(headers);
let cookie = '';
if (parsedCookies) {
if(parsedCookies['PHPSESSID']) {
cookie = `PHPSESSID=${parsedCookies['PHPSESSID']}`;
}
if(parsedCookies['REMEMBERME']) {
if (cookie.length > 0) {
cookie += ';';
}
cookie += `REMEMBERME=${parsedCookies['REMEMBERME']}`;
}
}
console.log(`Cookie: ${cookie}`);
// Send request to origin host at /_fos_user_context_hash
// passing the original session cookie
const options = {
hostname: `${request.headers.host[0].value}`,
port: 443,
path: '/_fos_user_context_hash',
method: 'HEAD',
headers: {
'Cookie': cookie,
'Accept': 'application/vnd.fos.user-context-hash',
'Vary' : 'Cookie'
}
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
// Read the X-User-Context-Hash from the hash endpoint
const headerName = 'X-User-Context-Hash';
let hash = 'anonymous';
if (res.headers[headerName.toLowerCase()]) {
hash = res.headers[headerName.toLowerCase()];
}
// Append X-User-Context-Hash before passing request on to CF
request.headers[headerName.toLowerCase()] = [{ key: headerName, value: hash }];
const sessionHeaderName = 'X-Session-Cookies';
request.headers[sessionHeaderName.toLowerCase()] = [{ key: sessionHeaderName, value: cookie }];
callback(null, request);
}).on('error', (e) => {
console.error(e);
// Forward request anyway
callback(null, request);
});
req.end();
}
;
The Origin Request trigger:
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const sessionHeaderName = 'X-Session-Cookies';
let cookie = '';
if (request.headers[sessionHeaderName.toLowerCase()]) {
console.log(request.headers[sessionHeaderName.toLowerCase()]);
cookie = request.headers[sessionHeaderName.toLowerCase()][0].value;
}
request.headers.cookie = [{ key : 'Cookie', value : cookie }];
callback(null, request);
};
AWS recently introduced cache and origin request policies, allowing more customization.
You can now set cache behavior based on "All-except" list of cookies/query string params by setting appropriate cache policy and set origin request policy to forward only necessary data:
The fundamental problem:
If you configure CloudFront to forward cookies to your origin, CloudFront caches based on cookie values. This is true even if your origin ignores the cookie values in the request...
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Cookies.html
This is by design. Cookies you forward are always part of the cache key.
There is no clean/simple/obvious workaround.
You could add the session cookie to the query string in the viewer request trigger, and configure that parameter to forward but not be used for caching, and then your origin would need to find it there and interpret it as a cookie. Query string parameters, unlike cookies, can be configured for forwarding, but not caching.
You could potentially replace the cookie in the actual request with a dummy/placeholder value, one per user class, so that it would be forwarded to the origin and used for caching, and then use a viewer-response trigger to prevent any Set-Cookie response from the origin (or cache) from exposing that magic cookie to any viewers.
Really, though, it sounds as if you may be trying to solve a problem in one place that really needs to be solved in another. Your application has a limitation in its design that is not cache friendly for certain resources. Those resources need to be designed to interact in a cache-friendly way, which is of course a fundamentally tricky proposition when access to the resource requires authenticated identification of a user, role, group, permission, etc.
Something similar I did to be able to forward cookies to an ALB configured for sticky sessions without cloudfront using the cookies to cache. The reason for this is because cloudfront will use the cookies and their values when matching requests and cached responses but because the ALB creates a new session cookie on each response, the request never matches the cache since the viewer always has a new cookie value set.
I too moved the cookie to a custom header in the viewer request and then pulled it out of the header and placed in back in the cookie in the origin request. I used the same lambda function for the viewer request and origin request and just checked the config property to determine which trigger it was. I prefer this pattern so that I can follow the logic from viewer request to origin request when reading/writing the code since the callback response from the viewer requests becomes the event request for the origin request and I could run my tests on a single function. The logic is based on three flows:
where there is no AWSALB cookie or customer header at all - in that case do nothing
where there is the AWSALB cookie but no other cookies in the request
where this is the AWSALB cookie along with other cookies
Using these three use cases the function was able to work properly.
Here's the function:
exports.handler = (event, context, callback) => {
// TODO implement
const util = require('util');
const COOKIE_TO_FORWARD = 'AWSALB';
let hasTheHeader = (request, headerKey) => {
if (request.headers[headerKey]) {
return true;
}
else return false;
}
//Returns the cookie key name from the value of the cookie header in the request
//let getCookieKey = cookieString => cookieString.slice(0,cookieString.indexOf("="));
const request = event.Records[0].cf.request
if(event.Records[0].cf.config.eventType == 'viewer-request') {
console.log('Viewer Request');
console.log(`viewer request – ${util.inspect(event, {showHidden: false, depth: null})}`);
hasTheHeader(event.Records[0].cf.request, 'cookie') ? console.log(`This request has cookies`) : console.log(`This request does NOT have cookies`);
// First check – If no cookies in Viewer Request, do nothing
if (!hasTheHeader(request, 'cookie')) {
console.log('viewer request first check evaluated - no cookies');
//pass request onto cloudfront cacheing layer or origin request
callback(null, request);
return;
}
// else there is a cookie header so get the list of cookies and put them in an array
let cookieList = request.headers.cookie[0].value.split('; ');
console.log(cookieList);
// Second check - If only the COOKIE_TO_FORWARD cookie exists and no other cookies, move it to a custom header and delete the cookie header
if ( (cookieList.length == 1) && (cookieList[0].startsWith(COOKIE_TO_FORWARD)) ) {
console.log('viewer request second check evaluated - only the COOKIE_TO_FORWARD cookie exists, no other cookies')
//move awsalb to custom header - format is important
request.headers.awsalbkey = [{'key': 'awsAlbKey', 'value': cookieList[0]}];
//remove cookie header
delete request.headers.cookie;
console.log(util.inspect(request, {showHidden: false, depth: null}));
//pass request onto cloudfront cacheing layer or origin request
callback(null, request);
return;
}
// Third check - If there are multiple cookies including the COOKIE_TO_FORWARD cookie, move only the COOKIE_TO_FORWARD cookie to a custom header and delete the cookie COOKIE_TO_FORWARD cookie
// get awsAlb cookie
const indexOfAwsALbCookie = cookieList.findIndex(element => element.startsWith('AWSALB='));
if ( (cookieList.length > 1) && (indexOfAwsALbCookie > -1) ) {
console.log('viewer request third check evaluated - the COOKIE_TO_FORWARD cookie exists along with other cookies')
//put awsAlb cookie value to custom header - format is important
request.headers.awsalbkey = [{'key': 'awsAlbKey', 'value': cookieList[indexOfAwsALbCookie]}];
//remove awsAlb cookie from list off cookies in request
cookieList.splice(indexOfAwsALbCookie,1);
let cookieListString = cookieList.join('; ');
request.headers.cookie[0].value = cookieListString;
console.log(util.inspect(request, {showHidden: false, depth: null}));
//pass request onto cloudfront cacheing layer or origin request
callback(null, request);
return;
}
}
else if(event.Records[0].cf.config.eventType == 'origin-request') {
console.log('Origin Request');
console.log(`origin request – ${util.inspect(event, {showHidden: false, depth: null})}`);
hasTheHeader(request, 'cookie') ? console.log(`This request has cookies`) : console.log(`This request does NOT have cookies`);
// First check – If no cookies in Viewer Request AND no awsalbkey header, do nothing as this is the first request to the origin
if (!hasTheHeader(request, 'cookie') && !hasTheHeader(request, 'awsalbkey')) {
console.log('origin request first check evaluated - no cookies and no awsalbkey header');
//send request to origin
callback(null, request);
return;
}
//Second check, if no cookie header AND COOKIE_TO_FORWARD customer header exists, then add the cookie header and cookie and remove the COOKIE_TO_FORWARD custom header
if (!hasTheHeader(request, 'cookie') && hasTheHeader(request, 'awsalbkey')) {
console.log('origin request second check evaluated - no cookies and has the awsalbkey header')
//add the cookie header and the cookie obtained from the custom header
request.headers.cookie = [];
var length = request.headers.cookie.push({'key': 'Cookie', 'value': request.headers.awsalbkey[0].value});
//remove the custom header
delete request.headers.awsalbkey;
console.log(util.inspect(request, {showHidden: false, depth: null}));
//send request to origin
callback(null, request);
return;
}
//else cookie list exists
let cookieListOrigin = request.headers.cookie[0].value.split('; ');
console.log(cookieListOrigin);
// Third check - If there are multiple cookies excluding the COOKIE_TO_FORWARD cookie and there's an COOKIE_TO_FORWARD custom header, move the COOKIE_TO_FORWARD custom header to the list of cookies and remove the COOKIE_TO_FORWARD custom header
let originIndexAwsAlbCookie = cookieListOrigin.findIndex(element => element.startsWith(COOKIE_TO_FORWARD));
if ( (originIndexAwsAlbCookie < 0) && (cookieListOrigin.length > 0) && (request.headers.awsalbkey) ) {
console.log('origin request third check evaluated - cookies exist without the awsalb cookie and has the awsalbkey header')
//add the awsalb customer header value to a new cookie in the cookie array
var length = cookieListOrigin.push(request.headers.awsalbkey[0].value);
let cookieListOriginString = cookieListOrigin.join('; ');
request.headers.cookie[0].value = cookieListOriginString;
//remove the custom header
delete request.headers.awsalbkey;
console.log(util.inspect(request, {showHidden: false, depth: null}));
//send request to origin
callback(null, request);
return;
}
}
callback(null, request);
};

app.post on parse heroku server is unauthorized

I am trying to post to my server from twilio, but I am getting a 403 error. Basically my parse-heroku serve is rejecting any request from twilio. I am working with TWIMLAPP and masked numbers. I am having trouble posting to a function in my index file when a text goes through. In my TWIMLAPP my message url is https://parseserver.herokuapp.com/parse/index/sms Any help is appreciated. These are the errors in twilio
var app = express();
app.use(require('body-parser').urlencoded());
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'https://www.twilio.com');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader("X-Parse-Master-Key", "xxxxxxx");
res.setHeader("X-Parse-Application-Id", "xxxxxx");
// Pass to next layer of middleware
next();
});
app.post('/sms', twilio.webhook({ validate: false }), function (req, res) {
console.log("use-sms")
from = req.body.From;
to = req.body.To;
body = req.body.Body;
gatherOutgoingNumber(from, to)
.then(function (outgoingPhoneNumber) {
var twiml = new twilio.TwimlResponse();
twiml.message(body, { to: outgoingPhoneNumber });
res.type('text/xml');
res.send(twiml.toString());
});
});

node.js, passport-wordpress: The required "redirect_uri" parameter is missing

Trying to create a demo using passport-wordpress
https://www.npmjs.org/package/passport-wordpress
passport-wordpress allows you to login to a node.js app using your credentials at wordpress.com
I set up my Wordpress app at developer.wordpress.com/apps:
OAuth Information
Client ID <removed>
Client Secret <removed>
Redirect URL http://greendept.com/wp-pass/
Javascript Origins http://wp-node2.herokuapp.com
Type Web
Request token URL https://public-api.wordpress.com/oauth2/token
Authorize URL https://public-api.wordpress.com/oauth2/authorize
Authenticate URL https://public-api.wordpress.com/oauth2/authenticate
In my node.js app:
var CLIENT_ID = <removed>;
var CLIENT_SECRET = <removed>;
passport.use(new WordpressStrategy({
clientID: CLIENT_ID,
clientSecret: CLIENT_SECRET
},
function(accessToken, refreshToken, profile, done) {
User.findOrCreate({ WordpressId: profile.id }, function (err, user) {
return done(err, user);
});
}
When I try to authorize, it goes to this URL (as one line, I've divided into two here for readability):
https://public-api.wordpress.com/oauth2/authorize?
response_type=code&redirect_uri=&client_id= removed
I can see that the redirect_uri is missing in that URL, so it's not surprising that I get this error:
Invalid request, please go back and try again.
Error Code: invalid_request
Error Message: The required "redirect_uri" parameter is missing.
Not sure where or how in my code I should be submitting the redirect_uri.
You need to pass a callback url as option.
From passport-wordpress
The strategy requires a verify callback, which accepts these credentials and
calls done providing a user, as well as options specifying a client ID,
client secret, and callback URL.
And from lib/strategy.js
Examples:
passport.use(new WordpressStrategy({
clientID: '123-456-789',
clientSecret: 'shhh-its-a-secret',
callbackURL: 'https://www.example.net/auth/wordpress/callback'
},
function(accessToken, refreshToken, profile, done) {
User.findOrCreate(..., function (err, user) {
done(err, user);
});
}
));

Resources