Stripe Connect Express account refreshURL and returnURL are undefined - api

I'm using Stripe Connect Express (new to it, following this STRIPE API DOCS). I am currently trying to create the AccountLink after successfully creating the Stripe Express Account.
However, I am not able to create the AccountLink as I'm getting an error when creating the AccountLink since the account.refresh_url and account.return_url appear to be undefined
exports.onCreateAuthUser = functions.auth.user().onCreate(async (user) => {
// Set your secret key. Remember to switch to your live secret key in production.
// See your keys here: https://dashboard.stripe.com/account/apikeys
const strip = require('stripe')('sk_test_key_input_here');
const account = await strip.accounts.create({
type: 'express',
});
let refURL = account.refresh_url
let retURL = account.return_url
console.log("account log stuff -->", account, retURL, refURL, account.uid, account.userId, account.userRef, account.user, account.id, account.ref, account.pushId, account.customer_id)
const accountLinks = await stripe.accountLinks.create({
account: account.id,
refresh_url: refURL,
return_url: retURL,
type: 'account_onboarding',
});
});
The console.log prints:
account log stuff --> undefined undefined undefined undefined undefined acct_1IbJSgPMwPhmaSsD undefined undefined undefined
Does anyone know why these attributes are undefined... and how I may fix it or what's wrong?

The return and refresh URLs aren't URLs generated by Stripe, they are URLs you provide to Stripe so they can redirect your users to your website.
The return_url is where Stripe will redirect your user when they've finished the onboarding flow.
As for the refresh_url:
The URL the user will be redirected to if the account link is expired, has been previously-visited, or is otherwise invalid. The URL you specify should attempt to generate a new account link with the same parameters used to create the original account link, then redirect the user to the new account link’s URL so they can continue with Connect Onboarding. If a new account link cannot be generated or the redirect fails you should display a useful error to the user.
https://stripe.com/docs/api/account_links/create#create_account_link-refresh_url

Related

How to keep cookie when redirecting to different domain?

I am trying to make use of the Spotify API in an express.js application. I am running into some issues when following the authorization flow that can be found on the Spotify Api docs.
Spotify actually links this guide for authentication using express that I have mainly been following.
I have been able to successfully request and gain authorization with the following route:
app.get('/login', function(req, res) {
var state = generateRandomString(16); // state parameter I provide Spotify API
console.log('Original state (generated in /login): ', state); // Original state (generated in /login): UzLczCmKIKuzvIMP
let options = {
maxAge: 24 * 60 * 60 * 1000,
sameSite: 'lax',
overwrite: true,
}
res.cookie('spotify_auth_state', state, options);
console.log(`Cookie before redirecting to Oauth: ${JSON.stringify(res.cookies)}`); // Cookie before redirecting to Oauth: undefined
// your application requests authorization
var scope = 'user-read-private user-read-email';
res.redirect('https://accounts.spotify.com/authorize?' +
querystring.stringify({
response_type: 'code',
client_id: client_id,
scope: scope,
redirect_uri: redirect_uri,
state: state
}));
});
Make note of the state variable that I am storing in the cookies as spotify_auth_state.
Once authorization has been granted, the Spotify API redirects the client to a link that you provide in the Developer portal. In this case I use localhost:3000/request_tokens to redirect the client to my route to request tokens to actually make use of the API.
This is the following route that the Spotify Oauth redirects to:
app.get('/request_tokens', function(req, res) {
console.log();
// your application requests refresh and access tokens
// after checking the state parameter
var code = req.query.code || null;
var state = req.query.state || null;
var storedState = req.cookies ? req.cookies['spotify_auth_state'] : null;
console.log(`State sent from spotify (should match): ${state}`); // State sent from spotify (should match): UzLczCmKIKuzvIMP
console.log(`Saved state (as cookie): ${storedState}`); // Saved state (as cookie): undefined
console.log(`Cookies when redirected to /request_tokens: ${JSON.stringify(req.cookies)}`); // Cookies when redirected to /request_tokens: {}
if (state === null || state !== storedState) {
res.redirect('/#' +
querystring.stringify({
error: 'state_mismatch',
state: state,
stored_state: storedState
}));
} else {
My issue is that I never get the `else' statement which is the goal. This is because, per Spotify documentation, my app should compare the state parameter that it received in the redirection URI with the state parameter it originally provided to Spotify in the authorization URI. If there is a mismatch then your app should reject the request and stop the authentication flow
The guide saves the 'state' variable in a cookie in the /login route when it is generated and then pulls it from the cookies once Spotify redirects to my /request_tokens route. However, when trying to find the cookie with I keep finding that it is undefined.
I assume it gets cleared because I am redirecting to a different domain (Spotify's authorization) so it is no longer there when Spotify redirects back to my local host. Can this 'state' variable be saved and checked via cookies or is there a better way to do this?

Botkit slackbot error "Could not load team while processing webhook"

I have created a simple express server and added a /slack/receive route to handle webhook requests from the Slack events API:
// routes.js (which is used by my app defined in server.js)
...
let slack = require('./controllers/slack');
router.post('/slack/receive', slack.receive);
...
I then use Botkit to create a simple Slack application:
// controllers/slack.js
'use strict';
const logger = require('../config/winston');
// initialise firebase storage for botkit
const admin = require('firebase-admin');
var serviceAccount = require('../config/firebase.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
var db = admin.firestore();
db.settings({
timestampsInSnapshots: true
})
// initialise botkit for slack
const botkit = require('botkit');
const controller = botkit.slackbot({
storage: require('botkit-storage-firestore')({ database: db }),
clientId: process.env.SLACK_CLIENT_ID,
clientSecret: process.env.SLACK_CLIENT_SECRET,
clientSigningSecret: process.env.SLACK_SIGNING_SECRET,
redirectUri: process.env.SLACK_REDIRECT,
disable_startup_messages: true,
send_via_rtm: false,
debug: true,
scopes: ['bot', 'chat:write:bot'],
})
controller.hears('Hello', 'direct_mention,direct_message', (bot, message) => {
logger.info(message);
bot.reply(message, 'I heard a message!');
})
exports.receive = (req, res, next) => {
res.sendStatus(200);
logger.debug(req.body);
controller.handleWebhookPayload(req, res);
};
The server initialises correctly, but as soon as the slack webhook receives a request the following error happens:
Could not load team while processing webhook: Error: could not find team T5VDRMWKX
at E:\Documents\upper-revolutions\node_modules\botkit\lib\SlackBot.js:169:24
at firebaseRef.doc.get.then.catch.err (E:\Documents\upper-revolutions\node_modules\botkit-storage-firestore\src\index.js:86:13)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:118:7)
So far I have found that:
Having/not having storage in the botkit slackbot makes no difference
The error happens within the handleWebhookPayload method as code within controller.hears() does not get executed
This error occurs because botkit needs some form of storage where it can store all the teams (channels and users too) and retrive it later on.
So, When your method handleWebhookPayload gets executed it calls another method called
findAppropriateTeam that will query for the specified team record in the storage provided by you (It might be mongoDB or a JSON file or other). The error is saying that you do not have any record in the storage with the id provided.
So this might implicate two things:
You did not provide a storage for botkit to work
You did not save the team id in the storage
The solution to the first problem is quite simple. You just need to install mongodb in your machine and then pass to botkit the MONGO_URL.
NOTE: I see that you are using the botkit simple storage and this might be the problem since I also have experieced some troubles with this kind of storage not saving records.
const controller = botkit.slackbot({
storage: 'mongodb//localhost:27017:/yourdb',
})
//OR
const controller = botkit.slackbot({
storage: process.env.MONGO_URL,
})
The possible solution to the second problem:
I will assume you are using botkit locally, so you must be using some tunneling like ngrok or localtunnel. In that case make sure:
You provided the redirect URL to Slack (Ex, https://your_url/oauth)
You accessed the https://your_url/login page
Botkit saves your team id on the provided storage when you access the /login route and authorizes the app. So if you skipped that part then botkit won't save your team id and therfore will throw an error when you receive events later on.
Check this like [https://github.com/howdyai/botkit/issues/938] for discutions on the topic
I hope this helps!

node-bigcommerce Get and Post Routes

I'm using the npm package, 'node bigcommerce', and I have all my API's setup but whenever I try to make a GET route, the error, Error: Request returned error code: 404 and body: The route is not found, check the URL, shows up. I don't know how or where to specify the url to find. Also, I have the same problem with POST Routes. The code is here. Thanks ahead!
var express = require('express'),
BigCommerce = require('node-bigcommerce');
var bigCommerce = new BigCommerce({
clientId: '* Client ID *',
secret: '* Secret *',
callback: 'https://store-xxi13.mybigcommerce.com',
responceType: 'json',
accessToken: '* Access Token *',
storeHash: 'xxi13'
});
bigCommerce.get('/happy', (data) =>{
console.log(data);
});
The path supplied in your get request, '/happy' is not a BigCommerce API endpoint--that's why you're getting a 404 not found. If you made a request to /products for example, it should work to pull product data.
Also, the callback would usually be a path on your app, not the store URL. For example, callback: 'https://myapplication.com/auth', would be the path on your app where you want the BigCommerce auth service to send your temporary code and Oauth token during the installation flow:
https://developer.bigcommerce.com/api/#app-installation-and-update-sequence
You can find examples of configuring the client and making requests in the README for the node-bigcommerce client:
https://github.com/getconversio/node-bigcommerce

Using node-spotify-web-api to grant user access and fetch data

So I'm new to using OAuth and I honestly got quite lost trying to make this work. I looked up the documentation for Spotify's Authorization code and also found a wrapper for node which I used.
I want to be able to log in a user through spotify and from there do API calls to the Spotify API.
Looking through an example, I ended up with this code for the /callback route which is hit after the user is granted access and Spotify Accounts services redirects you there:
app.get('/callback', (req, res) => {
const { code, state } = req.query;
const storedState = req.cookies ? req.cookies[STATE_KEY] : null;
if (state === null || state !== storedState) {
res.redirect('/#/error/state mismatch');
} else {
res.clearCookie(STATE_KEY);
spotifyApi.authorizationCodeGrant(code).then(data => {
const { expires_in, access_token, refresh_token } = data.body;
// Set the access token on the API object to use it in later calls
spotifyApi.setAccessToken(access_token);
spotifyApi.setRefreshToken(refresh_token);
// use the access token to access the Spotify Web API
spotifyApi.getMe().then(({ body }) => {
console.log(body);
});
res.redirect(`/#/user/${access_token}/${refresh_token}`);
}).catch(err => {
res.redirect('/#/error/invalid token');
});
}
});
So above, at the end of the request the token is passed to the browser to make requests from there: res.redirect('/#/user/${access_token}/${refresh_token}');
What if insted of redirecting there, I want to redirect a user to a form where he can search for artists. Do I need so somehow pass the token around the params at all time? How would I redirect a user there? I tried simply rendering a new page and passing params there but it didn't work.
you could store the tokens in a variety of places, including the query parameters or cookies - but I'd recommend using localstorage. When your frontend loads the /#/user/${access_token}/${refresh_token} route, you could grab the values and store them in localstorage (e.g. localstorage.set('accessToken', accessToken)) and retrieve them later when you need to make calls to the API.

Not able to redirect to client side with token from server(express) side route

I am using 'googleapis' npm package to do token based google authentication.
I am redirected to '/api/auth/success/google' route inside express after google provided authentication and redirects us to the uri stated in google app credentials.
The problem I am facing is that ,I have retrieved the tokens on server side,but I am unable to send those tokens to client side for them to be saved in cookies.
The problem I am facing is because,'/api/auth/success/google' is redirected from google side and not an ajax call from client side.So if I send the tokens back in res,where will it redirect.Also please suggest a way to redirect from server side to client side,along with access_token.
server side code.
//Route reached after google successful login/authentication
app.get('/api/auth/success/google',function(req,res){
console.log("inside redirect");
var code = req.query.code;
oauth2Client.getToken(code, function(err, tokens) {
// Now tokens contains an access_token and an optional refresh_token. Save them.
if(!err) {
oauth2Client.setCredentials(tokens);
}
res.sendFile('./index.html');
});
})
Client side call
//Google login requested from this function
googleLogin(){
event.preventDefault();
$.ajax({
type : 'POST',
url : baseURL + 'api/authenticate/google',
success: (function(data) {
if (data.redirect) {
document.location.href = data.redirect;
}
}).bind(this)
});
}
//Route handling request of google access
app.post('/api/authenticate/google',function(req,res){
// generate a url that asks permissions for Google+ and Google Calendar scopes
var scopes = [
googlecredentials.SCOPE[0],
googlecredentials.SCOPE[1]
];
var url = oauth2Client.generateAuthUrl({
access_type: 'offline', // 'online' (default) or 'offline' (gets refresh_token)
scope: scopes // If you only need one scope you can pass it as string
});
res.send({ redirect: url });
})
//Google App Credentials
var OAuth2 = google.auth.OAuth2;
var oauth2Client = new OAuth2(googlecredentials.CLIENT_ID, googlecredentials.CLIENT_SECRET, googlecredentials.REDIRECT_URL);
googlecredentials.CLIENT_ID - 858093863410-j9ma1i7lgapupip1ckegc61plrlledtq.apps.googleusercontent.com
REDIRECT_URL - http://localhost:3000/api/auth/success/google where localhost:3000 runs server side
If you send the redirect URL back in the res, the client-side should be able to check for the presence of the redirect URL in the response, and if it exists, push your user to that URL.