Error 403 "The caller does not have permission" - android

I am trying to fetch data from dynamic links stastics API, and I have already sent bearer token inside the header. But it shows the error of permission denied.
final response = await http
.get(Uri.parse("https://patelmatch-api.herokuapp.com/getStat"));
final encodedLink = Uri.encodeComponent(currentAppuser.value.url!);
if (response.statusCode == 200) {
LinkStat linkStat = LinkStat.fromJson(jsonDecode(response.body));
print(linkStat.accessToken);
final responseData = await http.get(
Uri.parse(
"https://firebasedynamiclinks.googleapis.com/v1/${encodedLink}/linkStats?durationDays=7"),
headers: {'Authorization': 'Bearer ' + linkStat.accessToken!});
print(responseData.body);
} else {
print("Error");
}
isLoading.toggle();
index.js
const express = require('express')
const cors = require('cors')
const app = express()
app.use(express.json())
app.use(cors())
var { google } = require("googleapis");
const port = process.env.PORT || 5000
// Load the service account key JSON file.
var serviceAccount = require("./path/to/serviceAccountKey.json");
// Specify the required scope.
var scopes = [
"https://www.googleapis.com/auth/firebase"
];
app.get('/getStat', async(req, res) => {
var jwtClient = new google.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
scopes
);
// Use the JWT client to generate an access token.
jwtClient.authorize(function(error, tokens) {
if (error) {
console.log("Error making request to generate access token:", error);
} else if (tokens.access_token === null) {
console.log("Provided service account does not have permission to generate access tokens");
} else {
var accessToken = tokens.access_token;
console.log(tokens.access_token)
console.log(accessToken.length)
res.send({accessToken});
// Include the access token in the Authorization header.
}
});
})
app.listen(port, () => console.log("up & running on 4000"))
Here I have generated access token from nodejs and fetching data from flutter, but I am having error of permission. How to solve this issue?

Related

Flutter while refreshToken getting old refresh token

I making refresh token with dio interceptors. Its working well but while i have multiple request in same time its trying using old refresh token. What can i do for fix it ? I tried use QueuedInterceptorsWrapper too but it has same result. Let me show you my codes first :
My Interceptor on constructor.
_dio.interceptors.add(
InterceptorsWrapper(onResponse: (Response<dynamic> response, ResponseInterceptorHandler handler) {
return handler.next(response);
}, onError: (DioError error, ErrorInterceptorHandler handler) async {
if (error.response?.statusCode == 401) {
var options = error.response!.requestOptions;
if ("Bearer $accessToken" != options.headers[HttpHeaders.authorizationHeader]) {
options.headers[HttpHeaders.authorizationHeader] = "Bearer $accessToken";
_dio.fetch(options).then((value) => handler.resolve(value), onError: (err) {
log("error on fetchiN!!!!");
});
// log("$accessToken ////// ${_dio.options.headers["Authorization"]}");
}
final refToken = await UserSecureStorage.getField("refreshToken");
if (refToken != null) {
log("hata alındı ${error.requestOptions.path}");
await refreshToken(refToken);
return handler.resolve(await _retry(error.requestOptions));
}
}
return handler.next(error);
}, onRequest: (RequestOptions options, RequestInterceptorHandler handler) async {
log("request atıldı ${options.path} ---Ref token => ${await UserSecureStorage.getField("refreshToken")}");
if (accessToken == null) {
accessToken = await UserSecureStorage.getField("token");
}
options.headers["Authorization"] = "Bearer $accessToken";
return handler.next(options);
}),
);
Refresh token function
Future<void> refreshToken(String? refreshToken) async {
final refToken = await UserSecureStorage.getField("refreshToken");
//In first request its changing and its working fine. But while it have multiple request in same time while in second request its trying use old refreshtoken
//token dio is another instance of dio so it hasnt any interceptor.Its only has baseurl.
final response = await tokenDio.get("/Auth/RefreshTokenLogin?
refreshToken=${Uri.encodeQueryComponent(refToken!)}");
if (response.statusCode == 200) {
final RefreshTokenResponseModel? model =
RefreshTokenResponseModel.fromJson(response.data);
accessToken = model!.data!.token;
log("refreshlendi! Yenisi => ${model.data!.refreshToken}");
await UserSecureStorage.setField("token", model.data!.token);
await UserSecureStorage.setField("refreshToken", model.data!.refreshToken);
_dio.options.headers[HttpHeaders.authorizationHeader] = "Bearer ${model.data!.token}";
}
}
Some screenshoots for make it clear.
Request sent to notification.
Request sent to therapist
Get error on notification
Request sent to PurchasedPackages
Get error on PurchasedPackages
Token refreshed. New token +pVX....
Error on another instance of dio for refresh token without any interceptor.
Refreshtoken instance tried refresh it with old refresh token.Ke.... So its gaving DioError on refreshtoken instance.
What can i do for fix it ? Thanks for response!

Upload image to the server with the form data in flutter

i using the ImagePicker package in the dart when i pick the image i want to upload this to the server with the form data but when i try to send this i give this error
" Unhandled Exception: FileSystemException: Cannot retrieve length of file, path = 'File: '/storage/emulated/0/Android/data/com.example.aloteb/files/Pictures/scaled_image_picker3594752094355545880.jpg'' "
and this is my code for sending to the server
var request = http.MultipartRequest('POST', Uri.parse(url));
request.fields.addAll({
'data': '$map'
});
request.files.add(await http.MultipartFile.fromPath('image',picproviderformdate.getPAth.toString()));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
and this is my ImagePickercode
picprovider pic = Provider.of<picprovider>(context,listen: false);
File image = await ImagePicker.pickImage(
source: ImageSource.gallery, imageQuality: 50);
setState(() {
_image = image;
});
print(_image);
pic.setpathe(_image);
can any one help me for solve this problem?
I had a similar problem a while ago, and i used the Dio dependency instead of the classical Http link.
The code is very similar, and i can gave you an example.
final File file = File("${documentDirectory.path}/picture.png");
final httpDio = dio.Dio();
final formData = dio.FormData.fromMap({
"data": "{}",
"files.image": await dio.MultipartFile.fromFile(
"${documentDirectory.path}/picture.png",
filename: "picture.png",
contentType: MediaType('image', 'png'))
});
try {
final dio.Response response = await httpDio.post(
"ApiEndpoint/avatars",
data: formData,
options: dio.Options(headers: {"Authorization": "Bearer yourTokenIfNeeded"}));
if (response.statusCode == 200) {
// Success
}
} on dio.DioError catch (e) {
if (e.response != null) {
// Error
print(e.response.data);
return;
}
}
Don't forgot to update the API endpoint and route as well as your auth authorization if you need one.

Script for making firebase user to user notifications

(Sorry for bad English)
I'm looking for a way to make user to user notifications in Android.
The system have to catch a new child event in the Database, read the data and send the notification to destination.
The struct of the DB is this:
notificationRequests
$pushid
message: "You have a new request! Open the app"
userId: "sadbijasuobru112u4124u21b" //user destination id
By doing some researches in the web I've found the possibility to use topic messages.
So, i've added this in my LoginActivity befor calling the MainActivity:
FirebaseMessaging.getInstance().subscribeToTopic("users_topic$uid")
.addOnCompleteListener {
Log.d("LoginActivity", "User registered")
}
The code works. I can send notifications from the console
Like I said before, i need automatic messages.
I've found this code on the web, but it doesn't work.
var firebase = require('firebase-admin');
var request = require('request');
var API_KEY = "Firebase Cloud Messaging Server API key"
// Fetch the service account key JSON file contents
var serviceAccount = require("./serviceAccountKey.json");
// Initialize the app with a service account, granting admin privileges
firebase.initializeApp({
credential: firebase.credential.cert(serviceAccount),
databaseURL: "https://appname.firebaseio.com/"
});
ref = firebase.database().ref();
function listenForNotificationRequests() {
var requests = ref.child('notificationRequests');
requests.on('child_added', (requestSnapshot) => {
var request = requestSnapshot.val();
sendNotificationToUser(
request.userId,
request.message,
() => {
requestSnapshot.ref.remove();
}
);
}, (error) => {
console.error(error);
});
}
function sendNotificationToUser(userID, message, onSuccess) {
request({
url: 'https://fcm.googleapis.com/fcm/send',
method: 'POST',
headers: {
'Content-Type' :' application/json',
'Authorization': 'key='+API_KEY
},
body: JSON.stringify({
notification: {
title: message
},
to : '/topics/users_topic'+userID
})
}, (error, response, body) => {
if (error) { console.error(error); }
else if (response.statusCode >= 400) {
console.error('HTTP Error: '+response.statusCode+' - '+response.statusMessage);
}
else {
onSuccess();
}
});
}
// start listening
listenForNotificationRequests();
I've implemented this code in the index.js for deployng. I've also write the entire file instead of requiring it, but it's always the same.
const functions = require('firebase-functions');
exports.sendNotifications = functions.https.onRequest((request, response) => {
require('./sendNotifications.js')
})
Any suggestions?
Thanks for the kelp!
EDIT
Does this need a billing account configurated? If yes, how can i make it with the free plan?
Does this need a billing account configurated? If yes, how can i make it with the free plan?
See https://firebase.google.com/support/faq#functions-runtime, but in short: from Node 10 you will need to enter billing information to use Cloud Functions.
You can use Node 8 until early next year without entering billing information.
Note that entering billing information does not necessarily mean you'll have to pay, as Cloud Functions has a pretty significant free tier.
The problem was that I was calling an external site. I solved it doing this:
const functions = require('firebase-functions');
var firebase = require('firebase-admin');
// Fetch the service account key JSON file contents
var serviceAccount = require("./serviceAccountKey.json");
// Initialize the app with a service account, granting admin privileges
firebase.initializeApp({
credential: firebase.credential.cert(serviceAccount),
databaseURL: "https://appname.firebaseio.com/"
});
exports.sendNotifications = functions.database.ref('/notificationRequest/{pushId}')
.onCreate( (change, context) => {
var uid = change.child('userId').val()
var notificationMessage = change.child('message').val()
var userTopic = 'users_topic'+uid
var payload = {
data: {
message: notificationMessage
}
};
var options = {
priority: 'high',
timeToLive: 60 * 60 * 24,
collapseKey: 'notification'
};
firebase.messaging().sendToTopic(userTopic, payload, options)
// eslint-disable-next-line promise/always-return
.then((response) => {
console.log('Done', response);
})
.catch((error) => {
console.log('Error: ', error);
});
return change.ref.remove();
});

Firebase Trigger Razorpay Intergration for Android

I am creating an App Where user can buy coins and for that I have been trying to integrate Razorpay into my Android App since a long time now. Razorpay can directly be used in Android. It sends Success or Failure results for payment and I can act accordingly (adding points to database in this case). But the problem with this approach is that I have to write points (after success) to database from the app. Which means I have to give write access for points node to user app which is not a good idea. So I wanted to use Razorpay with Firebase Cloud Functions and searching for a long time I came across this tutorial which is for web. I am quite new to Cloud Functions and hence wanted a little help for Android.
Here is the Index.js code but For Web
const functions = require("firebase-functions");
var express = require("express");
var cors = require("cors");
var request = require("request");
const crypto = require("crypto");
const key = "----insert yout key here----";
const key_secret = "----- insert key secret here ----";
var app = express();
app.use(cors({ origin: true }));
app.post("/", (req, res) => {
const amount = req.body.amount;
//Allow Api Calls from local server
const allowedOrigins = [
"http://127.0.0.1:8080",
"http://localhost:8080",
"https://-------YourFirebaseApp-----.firebaseapp.com/"
];
const origin = req.headers.origin;
if (allowedOrigins.indexOf(origin) > -1) {
res.setHeader("Access-Control-Allow-Origin", origin);
}
var options = {
method: "POST",
url: "https://api.razorpay.com/v1/orders",
headers: {
//There should be space after Basic else you get a BAD REQUEST error
Authorization:
"Basic " + new Buffer(key + ":" + key_secret).toString("base64")
},
form: {
amount: amount,
currency: "INR",
receipt:
"----- create a order in firestore and pass order_unique id here ---",
payment_capture: 1
}
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
res.send(body);
});
});
app.post("/confirmPayment", (req, res) => {
const order = req.body;
const text = order.razorpay_order_id + "|" + order.razorpay_payment_id;
var signature = crypto
.createHmac("sha256", key_secret)
.update(text)
.digest("hex");
if (signature === order.razorpay_signature) {
console.log("PAYMENT SUCCESSFULL");
res.send("PAYMENT SUCCESSFULL");
} else {
res.send("something went wrong!");
res.end();
}
});
exports.paymentApi = functions.https.onRequest(app);
I think this will help you.
In my case, I am accessing items(Array of Product IDs) from the user's cart and reading the current price of the items then passing it as an argument to SendOrderId function which will return an OrderId to proceed.
The important thing to keep in mind is that you must have added razorpay in your dependencies inside package.json. You can do that by simply running
npm i razorpay
inside your functions folder (Which include index.js) which will automatically add the dependency to your project
const functions = require("firebase-functions");
const admin = require('firebase-admin');
const Razorpay = require('razorpay')
const razorpay = new Razorpay({
key_id: 'Your_razorpay_key_id',
key_secret: 'your_secret'
})
admin.initializeApp();
function SendOrderId(amountData, response) {
var options = {
amount: amountData, // amount in the smallest currency unit
currency: "INR",
};
razorpay.orders.create(options, function(err, order) {
console.log(order);
response.send(order);
});
}
exports.getOrderId = functions.https.onRequest((req, res) => {
return admin.firestore().collection('Users').doc(req.query.uid).get().then(queryResult => {
console.log(queryResult.data().Cart);
admin.firestore().collectionGroup("Products").where('ProductId', 'in', queryResult.data().Cart).get().then(result => {
var amount = 0;
result.forEach(element => {
amount += element.data().price;
});
SendOrderId(amount * 100, res);
})
})
});

Cloud Function Not Working

I want to add notifications to an online android chatting app I have made. I am new to cloud functions, so I tried using the code given here https://firebase.googleblog.com/2016/08/sending-notifications-between-android.html
My index.js file
var firebase = require('firebase-admin');
var request = require('request');
var API_KEY = "xyz"; // Your Firebase
Cloud Messaging Server API key
// Fetch the service account key JSON file contents
var serviceAccount = require("firebase.json");
// Initialize the app with a service account, granting admin privileges
firebase.initializeApp({
credential: firebase.credential.cert(serviceAccount),
databaseURL: "https://firebaseio.com/"
});
ref = firebase.database().ref();
function listenForNotificationRequests() {
var requests = ref.child('notificationRequests');
requests.on('child_added', function(requestSnapshot) {
var request = requestSnapshot.val();
sendNotificationToUser(
request.username,
request.message,
function() {
console.log('notificationrecived, sent and removed- ' +
request.username + ' '+ request.message,);
requestSnapshot.ref.remove();
}
);
}, function(error) {
console.error(error);
});
};
function sendNotificationToUser(username, message, onSuccess) {
request({
url: 'https://fcm.googleapis.com/fcm/send',
method: 'POST',
headers: {
'Content-Type' :' application/json',
'Authorization': 'key='+API_KEY
},
body: JSON.stringify({
notification: {
title: message
},
to : '/topics/'+username
})
}, function(error, response, body) {
if (error) { console.error(error); }
else if (response.statusCode >= 400) {
console.error('HTTP Error: '+response.statusCode+' - '
+response.statusMessage);
}
else {n
onSuccess();
}
});
}
// start listening
listenForNotificationRequests();
I have successfully deployed this code to the server using node.js command line.
But this does not show up on the console and nor the logs that I added to debug
and the code doesn't seem to work. I have done everything given in the link i mentioned. I could use some help on how to fix my code
I don't know how big of a difference this makes, but in the Firebase admin set up page https://firebase.google.com/docs/admin/setup, it is mentioned that for Cloud Functions, the following line is sufficient for initialisation:-
var firebase = require('firebase-admin');
firebase.initializeApp(functions.config().firebase);
So, if you're going by the book, you may replace the initialisation line in your code with the one above and try running it again.
I didn't export my function listenForNotificationRequests() but called it only once at the end of the script.
Which is why it didn't show up on the Firebase Console.
I fixed this by simply exporting the function like this
exports.sendFollowerNotification = listenForNotificationRequests;

Categories

Resources