I'm trying to create a stripe connect account using my firebase functions backend when the user signs up but keep getting this error Express accounts may only be created via the OAuth flow I know the error seems self-explanatory that I need to use the standard OAuth registration method but in the Documentation it states that custom types can be created by the API and presenting the OAuth for every user who just wants to send funds and not receive is just annoying am I doing something wrong for the API not to create it? Or is there a workaround to not have to show the OAuth for users who just want to send funds?
exports.createStripeCustomer = functions.auth.user().onCreate(async (user) => {
const customer = await stripe.customers.create({email: user.email});
const account = await stripe.accounts.create({type: 'custom', business_type: 'individual', individual: {email: user.email}, requested_capabilities: ['card_payments', 'transfers'], email: user.email});
return admin.firestore().collection('stripe_customers').doc(user.uid).set({account_id: account.id, customer_id: customer.id});
});
Express Accounts and Custom Accounts are distinct types of accounts when using Connect. You can create Custom Accounts using the API, but Express Accounts must be created via OAuth.
The main difference is that Express Accounts have access to the Stripe Dashboard and can be updated in some ways by the end user, while Custom Accounts are entirely managed by the platform.
The issue seems to be being caused by me not specifying the Country in the stripe.accounts.create function. Once I did it created the account.
Related
I'm attempting to create a new external bank account on a stripe connected account like so:
await stripe.accounts.createExternalAccount(existingAccount.id, {
default_for_currency: true,
external_account: {
routing_number: bsb,
account_number: accountNumber,
account_holder_name: accountName,
country: 'AU',
currency: 'AUD',
object: 'bank_account',
account_holder_type: 'individual'
}
})
Where existingAccount.id is the id of the connected account.
This creates the error:
This application does not have the required permissions for this endpoint on account 'acct_[Account ID].
The connected account is an express account, when first created I give it a bank account and want the connected account user to be able to change/update it from within the app.
I'm not sure why this is creating permission issues and can't find any setings around permissions, the key I used to create the account is the same one I'm using to add a new external account to the created account.
You're receiving that error because you cannot create an external account for Express accounts. For context, Express accounts are expected to manage their own bank accounts from their Stripe Express Dashboard.
I'm trying to get a list of reviews of my Google business through the API to display them on my website. But I can't figure out how to authenticate the API server side. The documentation only mentions OAuth2.0 authentication from the client side with redirect URLs, but there won't be a client going to a confirmation page in this case.
I just want to be able to perform this request in Node.js:
GET https://mybusiness.googleapis.com/v4/accounts/{accountId}/locations/{locationId}/reviews
I've already submitted the application and been approved for a Business API and enabled the various APIs in my account. I have created OAuth2.0 credentials. I'm just not sure how to move forward from here.
How can I authenticate Google Business API requests on the server?
I ended up putting together an answer through lots of searching. Google documentation is all over the place.
A basic example of getting reviews is below. But to get it to work there are a few steps first.
You'll need to add a Service Account in your API credentials page
The name, ID, and description aren't particularly important. Just something that makes sense to you
Go to the service account details -> keys -> add key -> create new key -> JSON
This will download a key file to your computer. Keep it private.
Grant domain wide delegation for your service account
To do this, you'll need to be an admin of the account if you're part of an organisation
It will ask for a Client ID, but it is called Unique ID in the service account details. They're the same thing.
Add whatever scopes you need for the services you want to access. For reviews, the scope listed in the example below is enough.
The subject field in google.auth.JWT needs to be an admin of the account. I used my own email.
That should be it! You should now be able to fill out the values in the example below and access the API from a server. Other services may require different scopes.
You can get account and location info from the API docs. The endpoints and data formats are fairly well documented. Just authentication isn't very well explained it seems.
import axios from 'axios';
import {google} from 'googleapis';
import key from './key.json' assert {type: 'json'};
main();
async function main(){
const reviews=await getReviews();
}
async function getReviews(){
const token=await authenticate();
const accountId='YOUR ACCOUNT ID';
const locationId='YOUR LOCATION ID';
const url=`https://mybusiness.googleapis.com/v4/accounts/`+
`${accountId}/locations/${locationId}/reviews`;
const resp=await axios.get(url, {
headers: {
authorization: `Bearer ${token}`
}
});
return resp.data.reviews;
}
async function authenticate(){
const scopes=[
'https://www.googleapis.com/auth/business.manage'
];
const jwt=new google.auth.JWT({
email: key.client_email,
key: key.private_key,
subject: 'ADMIN EMAIL',
scopes
});
const resp=await jwt.authorize();
return resp.access_token.replace(/\.{2,}/g, '');
}
I'm creating Google Actions Builderaction console and I'm having some doubt in Account Linking. Should be like, need to authenticate account linking based on my database data.
Example:
While Account Linking if I wanted to pass a email (abc#gmail.com), that email should be active and only on that case Account Linking should be allow. So for this I want to write custom Node Js function.
So that I have used Link Type as oAuth and Authorization, Token URL I set with as my custom Node Js functions.
My doubt:
how to pass email id while link Account Linking.
After validate email how can I link account in Google Actions Builder.
My Node Js Code
Here I want to write function inside auth call back function inside if(result).
const express = require('express');
const port = 5003;
const app = express();
app.get('/', (req, res) =>{
res.send(`Welcome to Test App Nodejs`);
})
app.get('/auth', (req, res) =>{
var email = req.query.email;
userModel.findAll({
where: {
emailId: email,
status:1
}
}).then((result) =>{
if(result){
// Allow to account link
} else{
// to return Thanks for trying to account linking
}
}).catch((err)=>{
res.send(err);
})
});
app.listen(port, (req, res)=>{
console.log(`Test App runing with ${port}`)
})
There are a number of things about your question that don't fit with how Account Linking is meant to work, so it might make sense to get a brief overview of how Account Linking works.
The purpose of Account Linking is to provide a way that a user record that you maintain for your service gets associated with an Assistant account. This is done (broadly speaking) by the user authorizing Google to access basic information about the user's records in your system. This is done using OAuth2.
There are variants (authorizing using a mobile app, or authorizing the Google account to give you the user record), but they generally work the same way:
You authorize Google to get access to information
Google provides this information as part of the request sent to your webhook
So it does not exactly make sense for you to provide to your webhook an email address and expect it to link somehow. That isn't how this works. If anything - it makes it so you don't need to ask the user for their email address, you can just get it from the linked account.
If you are trying to build a webhook that does the authorization part, you'll need to have it handle OAuth2. This is a lot more than "pass an email address", however, and while it is not difficult, it can be tricky to get some security elements correct. This is usually best left to tools such as Auth0 or other identity providers.
You can also learn more about Account Linking and how it works in general with Action Builder.
Also, keep in mind that conversational actions will be shut down on June 13 2023.
I've seen that when using ADAL.js, you cannot get group membership claims due to some URL limitation.
https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/239
I am using oauth-bearer authentication from the frontend, that is, the frontend triggers a login via the AD login page.
The client then pass the access token to the backend.
What I want to do:
I want to filter some data in my backend endpoints depending on group membership.
e.g. if you are a member of group "London" in AD, you should only see things related to London in our DB queries.
Super simple using e.g. Okta or Auth0, not so much with Azure AD.
I also want to accomplish the same thing on the frontend, that is, show and hide menu items depending on group membership.
(All access is still checked on backend also)
The documentation is sparse and not very helpful.
"You should use Graph API".
How?, how do I talk to graph api using the token I get from the frontend?
This is the setup I have for my Node+Express endpoints:
app.use(
"/contacts",
passport.authenticate("oauth-bearer", { session: true }),
contacts
);
How, where and when should I call the graph API here?
Our system is super small so I don't mind using session state.
Can I fetch this information when the user logs in?
How should that flow be? client logs in, once logged in, call the backend and request the groups?
When you get the access token from Azure AD after the user logged in, you can find the group membership of the user by doing a GET request to https://graph.microsoft.com/v1.0/me/memberOf with the access token like this:
function getGroupsOfUser(accessToken, callback) {
request
.get('https://graph.microsoft.com/v1.0/me/memberOf')
.set('Authorization', 'Bearer ' + accessToken)
.end((err, res) => {
callback(err, res);
});
}
This sample assumes you are using the NPM package superagent.
And the required permissions to call this API are listed here.
Specifically, I'd like to use the Gmail API to access my own mail only. Is there a way to do this without OAuth and just an API key and/or client id and secret?
Using an API key like:
require('googleapis').gmail('v1').users.messages.list({ auth: '<KEY>', userId: '<EMAIL>') });
yields the following error:
{ errors:
[ { domain: 'global',
reason: 'required',
message: 'Login Required',
locationType: 'header',
location: 'Authorization' } ],
code: 401,
message: 'Login Required' }
I suppose that message means they want a valid OAuth "Authorization" header. I would do that but I suppose that's not possible without presenting a webpage.
The strict answer to "Is there a way to do this without OAuth and just an API key and/or client id and secret?" is no.
However, you can achieve what you are looking for using OAuth. You simply need to store a Refresh Token, which you can then use any time to request an Auth Token to access your gmail.
In order to get the refresh token, you can either write a simple web app to do a one time auth, or follow the steps here How do I authorise an app (web or installed) without user intervention? (canonical ?) which allows you to do the whole auth flow using the Oauth Playground.
The question is rather old, but the problem is not. For now Google API has an option to create service accounts. I think it suits for everybody who wants "just connect application to its own google workspace" and not to do some actions on users behalf. Google documentation writes about it:
Typically, an application uses a service account when the application uses Google APIs to work with its own data rather than a user's data. For example, an application that uses Google Cloud Datastore for data persistence would use a service account to authenticate its calls to the Google Cloud Datastore API.
Here is the example in Java (there was no JS, but the meaning is clear):
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
.createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));
SQLAdmin sqladmin =
new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
SQLAdmin.Instances.List instances =
sqladmin.instances().list("exciting-example-123").execute();