"Invalid API Key provided" using the stripe extension in firebase cloud functions - google-cloud-firestore

having a problem that when I try to run my cloud function where my secret key is being perceived as invalid. I am 99.99% sure that it is the same as is in the Stripe dashboard and have copied and pasted 100 times so I think it is something else.
{success: false, error: Invalid API Key provided: sk_test_**********************************************************************************************************************************************************************************************************}
If anyone could help that would be fantastic.

Can you double check if there's any extra empty space characters being added to the API key that you specified in the cloud function? Or if you are reading the API key from a config file, try hardcode it directly to the code and see if it solves the problem.

Initial thoughts...
Ensure you have setup a restricted key with the specified security.
Could this be an issue with the secret manager, invalidating your key here and reconfiguring https://console.cloud.google.com/security/secret-manager?referrer=search&project={your-project-id} may fix the issue.
If you install a new instance, do you still have the same issue?
If you can run locally, does the key work ok in small nodejs project for example, depending on which extension you are using:
import Stripe from 'stripe';
// invoices extension: apiVersion: '2020-03-02',
// payments extension: apiVersion = '2020-08-27';
const stripe = new Stripe('sk_test_...', {
apiVersion: '2022-11-15',
});
const createCustomer = async () => {
const params: Stripe.CustomerCreateParams = {
description: 'test customer',
};
const customer: Stripe.Customer = await stripe.customers.create(params);
console.log(customer.id);
};
createCustomer();

Related

Is there yet an idiomatic way to make native calls to AWS Lambda or API Gateway from a Flutter application?

Goal: Make a signed request (SigV4) to AWS Lambda or API Gateway from a Flutter application (iOS, for the sake of this question).
For context, AWS introduced support for "native calls to AWS backends in [...] Flutter or Dart applications" back in May of 2022. There is an example of how to sign a request to Cognito to gather information about a User Pool, but I have not seen any application of this concept for Lambda or API Gateway calls, yet.
I'm wondering if anyone else has had success using AWS's official Dart packages to send signed requests or knows of another way to securely call AWS from a Flutter application.
EDIT:
I was able to accomplish the goal. Here's how I did it:
The code (all-caps denotes placeholders for your own values):
import 'dart:convert';
import 'package:aws_common/aws_common.dart';
import 'package:aws_signature_v4/aws_signature_v4.dart';
const signer = AWSSigV4Signer(
credentialsProvider: AWSCredentialsProvider.dartEnvironment(),
);
const region = 'REGION';
Future<void> yourFunction() async {
final scope = AWSCredentialScope(
region: region,
service: AWSService.apiGatewayV2,
dateTime: AWSDateTime(DateTime.now()),
);
final request = AWSHttpRequest(
method: AWSHttpMethod.post,
uri: Uri.https('HOST.execute-api.REGION.amazonaws.com','/STAGE_NAME'),
headers: const {
AWSHeaders.contentType: 'application/x-amz-json-1.1',
},
body: json.encode({
'EVENT_KEY':'EVENT_VALUE',
}).codeUnits,
);
final signedRequest = await signer.sign(
request,
credentialScope: scope,
);
final resp = await signedRequest.send();
final respBody = await resp.decodeBody();
print('\n\n${signedRequest.headers}\n\n${respBody}\n\n${resp.statusCode}\n\n');
}
Within a single AWS region (except where n/a):
create IAM user with execute-api:Invoke permission and programmatic access; store keys securely for later use.
create a Lambda function (can be the default, for testing).
create API in API Gateway:
REST (not private)
Regional endpoint
Add method (for me, POST)
IAM authorization type
Integration type is Lambda
select the target Lambda function, but
do not use Lambda proxy
deploy the newly created API to a new stage (give it a name)
Edit your dart file to include the new resources, including the stage name.
Test your API within API Gateway (I was getting 502 until I unchecked "Lambda proxy integration").
Run the following in your terminal after a successful API test; be sure to insert the keys for the IAM user you created.
flutter run --dart-define=AWS_ACCESS_KEY_ID=... --dart-define=AWS_SECRET_ACCESS_KEY=...
Summary:
In my case, I have a button that executes this function. If you keep the print statement in the above dart code, you should hopefully see {"statusCode": 200, "body": "\"Hello from Lambda!\""} as the response body.
Hope this helps others. Cannot make any guarantees that my approach will work in another environment. I also may have forgotten to include something relevant in the steps above. Still open to questions and suggestions.
Thank you.

How to solve the {code: UNAUTHENTICATED, details: null, message: UNAUTHENTICATED}) error using Google Cloud Functions?

I am currently facing the above mentioned error when using the cloud_functions dependency on my Flutter app. My function https call is as follows:
final HttpsCallable callable = CloudFunctions(region: "region name").getHttpsCallable(functionName: 'function-name')..timeout = const Duration(seconds:30);
And my function invocation within the code is as given below:
onPressed: () async {
try {
dynamic resp = await callable.call(<String, dynamic>{
'message':'hello!',
'url': urlController.text,
});
setState(() {
imgurl = resp.data['image'];
time = resp.data['timestamp'];
});
I have added the ID I am using for authentication to my function via the console IAM. Unfortunately, I still keep receiving the following error:
PlatformException(functionsError, Cloud function failed with exception., {code: UNAUTHENTICATED, details: null, message: UNAUTHENTICATED})
How can I resolve that?
Thanks for your help in advance.
If you have deployed your function in "private mode", I mean, allow only authenticated user, you have to add a valid identity_token in the header of your request.
You have an example here, mostly on end user because it's your use case. Don't use a service account key file because your flutter app is public and you will share your secret publicly.
You can also use Cloud Endpoint with Firebase authentication mode. I wrote an article for setting up an authentication with API key. Simply update the authentication mode and it will works.

How do I generate a content hash using sha256 hash of the request body content, using the private api key with Wix Corvid

I am seeking any information attainable in reference to creating a content hash. I am very new to the coding world and would appreciate any feedback. I have searched the Wix API Documentation and am unable to find any information pertaining to this in the forum either.
You need to install npm package into Wix. For example:
js-sha256
Then you can use this code only in backend side:
var sha256 = require('js-sha256');
export async function testSha256(param) {
let p = await sha256.sha256(param);
return p;
}
Then call this script from frontend, like as:
let hashed = await testSha256('test');

CognitoClientException{statusCode: null, code: NetworkError, name: null, message: Failed host lookup: 'cognito-idp.us-east-1.amazonaws.com'}

Im using flutter with the Amazo Cognito Identiy Dart Plugin
I am new to AWS and followed the sample code provided on the plugin's github page to create a new user but I keep getting the following error message:
CognitoClientException{statusCode: null, code: NetworkError, name: null, message: Failed host lookup: 'cognito-idp.us-east-1.amazonaws.com'}
I have read through a good chunck of the complete sample app and can't seem to find what I am overlooking. I thought that maybe I needed to include the android permission for internet (although the documentation didn't mention it); however I still got the same error code.
Below is the code for the method to sign up a new user. The variables cognitoUserPoolId and cognitoClientId are from a secret.dart file, and reference my user pool. The user pool allows users to sign up with a name, email address, and password. Besides that it uses the default settings.
final userPool = new CognitoUserPool(cognitoUserPoolId, cognitoClientId);
signUpUser(String name, String email, String password) async {
final userAttributes = [
new AttributeArg(name: 'name', value: name),
];
var data;
try {
print('attempting to sign user up');
data = await userPool.signUp(email, password, userAttributes: userAttributes);
} catch (e) {
print(e);
}
}
Edit: turns out what I was reading was the source code of the plugin, and not the example app. According to the example it seems that the uses-internet permission is actually required. Unfortunately as I stated earlier adding it did not fix the problem.
Update: I have found the solution. It turns out the emulator I was runnning was having issues connecting to the network. Stack Overflow question detailing how to fix that issue
I simply used a physical device and all seems to be working great!

using postman to access firebase REST API

I'm trying to use postman to do REST API calls to firebase. I've managed to read from firebase when my security rule is to permit all users including unauthorized ones.
but when I use this rule :
{"rules":{".read": "auth != null", ".write": "auth != null"}}
I get 'error' : 'permission denied' from postman.
I did the request token for google's web oauth2.0 client and got the authorization_code token back.
I tried to use token in the URL and in the header, tried it with GET & POST request and still get denied.
please help.
Thanks in advance
The answers above did not work for me.
What did work for me was going to
Project Settings (top left corner gear) -> Service Accounts (far right tab) -> Database Secrets (left menu) -> Scroll down, hover over the bulltets and click Show
Use this as the auth key, i.e. .../mycollection.json?auth=HERE
For me it worked like this:
https://your-database-url/users.json?auth=YOUR_AUTH_KEY
Where can you get this AUTH_KEY?
you get this key from your Project Settings -> Database -> Secret Key
Try something like this
https://your-database-url/users.json?auth=YOUR_AUTH_KEY
Respone is a JSON of your USERS node
I created a Postman pre-request script for helping create a Authentication: Bearer JWT. Should save a lot of copy pasting when testing APIs with Firebase Auth. https://gist.github.com/moneal/af2d988a770c3957df11e3360af62635
Copy of script at time of posting:
/**
* This script expects the global variables 'refresh_token' and 'firebase_api_key' to be set. 'firebase_api_key' can be found
* in the Firebase console under project settings then 'Web API Key'.
* 'refresh_token' as to be gathered from watching the network requests to https://securetoken.googleapis.com/v1/token from
* your Firebase app, look for the formdata values
*
* If all the data is found it makes a request to get a new token and sets a 'auth_jwt' environment variable and updates the
* global 'refresh_token'.
*
* Requests that need authentication should have a header with a key of 'Authentication' and value of '{{auth_jwt}}'
*
* Currently the nested assertions silently fail, I don't know why.
*/
pm.expect(pm.globals.has('refresh_token')).to.be.true;
pm.expect(pm.globals.has('firebase_api_key')).to.be.true;
var sdk = require('postman-collection'),
tokenRequest = new sdk.Request({
url: 'https://securetoken.googleapis.com/v1/token',
method: 'POST',
body: {
mode: 'urlencoded',
urlencoded: [{
type: 'text',
key: 'key',
value: pm.globals.get('firebase_api_key')
},
{
type: 'text',
key: 'grant_type',
value: 'refresh_token'
},
{
type: 'text',
key: 'refresh_token',
value: pm.globals.get('refresh_token')
},
]
}
});
pm.sendRequest(tokenRequest, function(err, response) {
pm.test('request for access token was ok', function() {
pm.expect(response).to.be.ok();
});
const json = response.json();
pm.expect(json).to.an('object');
pm.test('response json has needed properties', function() {
pm.expect(json).to.have.own.property('access_token');
pm.expect(json).to.have.own.property('token_type');
pm.expect(json).to.have.own.property('refresh_token');
const accessToken = json.access_token;
const tokenType = json.token_type;
const refreshToken = json.refresh_token;
pm.environment.set('auth_jwt', tokenType + ' ' + accessToken);
pm.globals.set('refresh_token', refreshToken);
});
});
Note: Adding this answer as all Options listed here is either deprecated or not working(mostly due to missing steps).
Best way to make it work with Postman is to use Google OAuth2 access tokens. The provided link described in full length but I have added quick steps.
Step 1: Download Service-Accounts.json
Step 2: Generate Access token in Java (provided link described support in other language for this)
make sure to include this dependency:
implementation 'com.google.api-client:google-api-client:1.25.0'
OR
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.25.0</version>
</dependency>
Run this code to generate token(Copied from google's javadocs)
// Load the service account key JSON file
FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountKey.json");
GoogleCredential scoped = GoogleCredential
.fromStream(serviceAccount)
.createScoped(
Arrays.asList(
"https://www.googleapis.com/auth/firebase.database",
"https://www.googleapis.com/auth/userinfo.email"
)
);
// Use the Google credential to generate an access token
scoped.refreshToken();
String token = scoped.getAccessToken();
System.out.println(token);
Step 3: Use the token in Postman
It is very simple to fetch data via Postman:
Here is how I did it
1 Your DB URL
https://YOUR_PROJECT_URL.firebaseio.com/YOUR_STRUCTURE/CLASS.json
2 Add API key in header as auth
auth = Value of your API_KEY
example:
We can use Firebase with postman for rest APIs
How we use Firebase in postman?
Copy your Firebase database URL
Paste it into your postman URL
Add .json at the last like shown in the image
Then play with your firebase database and make REST API