Firebase messaging missing Authentication key in MongoDB trigger functions: - javascript

Please I need help. I don't know what I am doing wrong. I am trying to send push notification from http request but I keep getting this error:
The request was missing an Authentication Key. Please, refer to section "Authentication" of the FCM documentation, at https://firebase.google.com/docs/cloud-messaging/server.
I am currently doing this:
const response = await context.http.post({
url:"https://fcm.googleapis.com/fcm/send",
header:{"Content-Type": "application/json",
"Authorization":"key= Web Server Key"},
body:{
"to": usersPushToken, // From FirebaseMessaging.instance.getToken();
"notification": {
"title": "Title",
"body": "body",
"clickAction": 'FLUTTER_NOTIFICATION_CLICK',
"sound": 'default',
},
}
},
encodeBodyAsJSON: true,
});
My web server key (Cloud Messaging API (Legacy)) I also tried API key:

This was my fault (headers not header). But I will leave this answer for anyone using Flutter, MongoDB, and Firebase Messaging.
const response = await context.http.post({
url:"https://fcm.googleapis.com/fcm/send",
"headers":{"Content-Type": ["application/json"], //Must be in array
"Authorization":["key= Web Server Key"]}, //Must be in array
"body":{
"to": usersPushToken, // From FirebaseMessaging.instance.getToken();
"notification": {
"title": "Title",
"body": "body",
"clickAction": 'FLUTTER_NOTIFICATION_CLICK',
"sound": 'default',
},
}
},
encodeBodyAsJSON: true,
});

Related

Get roles of current user in Discord server

I'm trying to get the roles of the current user in a specific chat room using Discord's API (using an access_token). I've had a fair look through the docs and can't see how to do this. For example, doing a get request to https://discordapp.com/api/users/#me gives the basic user info as expected. I then tried something along the lines of the following without any luck:
https://discordapp.com/api/users/#me/guilds/${guild.id}/roles
Here's a snippet of the code I'm using:
....get access token then
.then(info => {
console.log(info)
fetch(`https://discordapp.com/api/users/#me`, {
headers: {
authorization: `${info.token_type} ${info.access_token}`,
},
}).then(response => response.json())
.then(info => {
console.log(info)
})
})
Any ideas?
To clarify, the user logs in with discord and my application receives a user access token which I'm then trying to use to get the roles of the user in a specific discord room.
From the documentation you can do this using the endpoint:
GET /guilds/{guild.id}/members/{user.id}
This will return a guild member object that contains the roles of this user.
Example guild member object:
{
"user": {},
"nick": "",
"roles": [],
"joined_at": "",
"deaf": false,
"mute": false
}
There is
GET /users/#me/guilds/{guild.id}/member
Which will get you a JSON object containing
{
"avatar": null,
"communication_disabled_until": null,
"flags": 0,
"is_pending": null,
"joined_at": "2023-01-11T23:12:34.423000+00:00",
"nick": null,
"pending": null,
"premium_since": null,
"roles": [
2888141278217623600,
5904405471246944000
],
"user": {
"id": 8285334657500223000,
"username": "your-name",
"display_name": null,
"avatar": null,
"avatar_decoration": null,
"discriminator": 4041,
"public_flags": 0
},
"mute": null,
"deaf": null
}
To use this with OAuth2, you must request the guilds.members.read OAuth2 scope, which is the one that Discord prompts users for their permissions with
Read your member info (nickname, avatar, roles, etc...) for servers you belong to
This was added in sometime in late 2021, judging from this PR.

webauthn authentication javascript formatting assistance

I have been trying to figure out how to do 2fa with webauthn and I have the registration part working. The details are really poorly documented, especially all of the encoding payloads in javascript. I am able to register a device to a user, but I am not able to authenticate with that device. For reference, I'm using these resources:
https://github.com/cedarcode/webauthn-ruby
https://www.passwordless.dev/js/mfa.register.js
And specifically, for authentication, I'm trying to mimic this js functionality:
https://www.passwordless.dev/js/mfa.register.js
In my user model, I have a webauthn_id, and several u2f devices, each of which has a public_key and a webauthn_id.
In my Rails app, I do:
options = WebAuthn::Credential.options_for_get(allow: :webauthn_id)
session[:webauthn_options] = options
In my javascript, I try to mimic the js file above and I do (this is embedded ruby):
options = <%= raw #options.as_json.to_json %>
options.challenge = WebAuthnHelpers.coerceToArrayBuffer(options.challenge);
options.allowCredentials = options.allowCredentials.map((c) => {
c.id = WebAuthnHelpers.coerceToArrayBuffer(c.id);
return c;
});
navigator.credentials.get({ "publicKey": options }).then(function (credentialInfoAssertion)
{
// send assertion response back to the server
// to proceed with the control of the credential
alert('here');
}).catch(function (err)
{
debugger
console.error(err); /* THIS IS WHERE THE ERROR IS THROWN */
});
The problem is, I cannot get past navigator.credentials.get, I get this error in the javascript console:
TypeError: CredentialsContainer.get: Element of 'allowCredentials' member of PublicKeyCredentialRequestOptions can't be converted to a dictionary
options at the time navigator.credentials.get is called looks like this:
I've tried every which way to convert my db-stored user and device variables into javascript properly encoded and parsed variables but cannot seem to get it to work. Anything obvious about what I'm doing wrong?
Thanks for any help,
Kevin
UPDATE -
Adding options json generated by the server:
"{\"challenge\":\"SSDYi4I7kRWt5wc5KjuAvgJ3dsQhjy7IPOJ0hvR5tMg\",\"timeout\":120000,\"allowCredentials\":[{\"type\":\"public-key\",\"id\":\"OUckfxGNLGGASUfGiX-1_8FzehlXh3fKvJ98tm59mVukJkKb_CGk1avnorL4sQQASVO9aGqmgn01jf629Jt0Z0SmBpDKd9sL1T5Z9loDrkLTTCIzrIRqhwPC6yrkfBFi\"},{\"type\":\"public-key\",\"id\":\"Fj5T-WPmEMTz139mY-Vo0DTfsNmjwy_mUx6jn5rUEPx-LsY51mxNYidprJ39_cHeAOieg-W12X47iJm42K0Tsixj4_Fl6KjdgYoxQtEYsNF-LPhwtoKwYsy1hZgVojp3\"}]}"
This is an example of the serialised JSON data returned by our implementation:
{
"challenge": "MQ1S8MBSU0M2kiJqJD8wnQ",
"timeout": 60000,
"rpId": "identity.acme.com",
"allowCredentials": [
{
"type": "public-key",
"id": "k5Ti8dLdko1GANsBT-_NZ5L_-8j_8TnoNOYe8mUcs4o",
"transports": [
"internal"
]
},
{
"type": "public-key",
"id": "LAqkKEO99XPCQ7fsUa3stz7K76A_mE5dQwX4S3QS6jdbI9ttSn9Hu37BA31JUGXqgyhTtskL5obe6uZxitbIfA",
"transports": [
"usb"
]
},
{
"type": "public-key",
"id": "nbN3S08Wv2GElRsW9AmK70J1INEpwIywQcOl6rp_DWLm4mcQiH96TmAXSrZRHciZBENVB9rJdE94HPHbeVjtZg",
"transports": [
"usb"
]
}
],
"userVerification": "discouraged",
"extensions": {
"txAuthSimple": "Sign in to your ACME account",
"exts": true,
"uvi": true,
"loc": true,
"uvm": true
}
}
This is parsed to an object and the code used to coerce those base64url encoded values is:
credentialRequestOptions.challenge = WebAuthnHelpers.coerceToArrayBuffer(credentialRequestOptions.challenge);
credentialRequestOptions.allowCredentials = credentialRequestOptions.allowCredentials.map((c) => {
c.id = WebAuthnHelpers.coerceToArrayBuffer(c.id);
return c;
});
Hope that helps. The JSON data is retreived via a fetch() call and the byte[] fields are encoded as base64url on the serverside.

Can I make a "Mailjet" API call using fetch?

I would like to make a request to "Mailjet" API from a react app. To do so, I would like to use fetch API.
According to the documentation, I can use curl :
curl -s \
-X POST \
--user "$MJ_APIKEY_PUBLIC:$MJ_APIKEY_PRIVATE" \
https://api.mailjet.com/v3.1/send \
-H 'Content-Type: application/json' \
-d '{
"Messages":[
{
"From": {
"Email": "toto#toto.fr",
"Name": "toto"
},
"To": [
{
"Email": "passenger1#example.com",
"Name": "passenger 1"
}
],
"TemplateID": 1074249,
"TemplateLanguage": true,
"Subject": "Hi there !",
"Variables": {}
}
]
}'
I tried with fetch the following code :
fetch('https://api.mailjet.com/v3.1/send',{
method : 'POST',
mode : 'no-cors',
headers : {
'Content-Type': 'application/json',
'client_id':'xxx111',
'client_secret':'xxx000'
},
body : {
"Messages":[
{
"From": {
"Email": "toto#toto.fr",
"Name": "Toto"
},
"To": [
{
"Email": "email#email.com"
}
],
"TemplateID": 1094249,
"TemplateLanguage": true,
"Subject": "Hi there",
"Variables": {
}
}
]
}
})
.then(resp=>resp.json())
.then(data => {
console.log('data mailjet', data);
})
.catch(err => err)
I always got a 401 error "not authorized". I am sure my API keys are not set properly, but I don't really know how I can set them with fetch.
Can I make this API call from my react-app or do I need to create my own API and request the resources with node?
Thanks a lot!!
Regarding Mailjet - use the node integration they provide ;)
import mailjet from 'node-mailjet';
Regarding fetch - add your token in your header, depending on what kind of token the API expects. This will differ whether with each API and wether your doing frontend or backend calls.
With Node, save the token as a environment variable and then inject into the Authorization header.
The API key & secret need to be added as a Basic auth header and base64-encoded (use any lib you'd like in Node)
const encoded = base64.encode(`${apiKey}:${apiSecret}`)
fetch('https://api.mailjet.com/v3.1/send', {
headers: {
Authorization: `Basic ${encoded}`
}
})
Docs: https://dev.mailjet.com/sms/reference/overview/authentication/

How can I post a container in Storage api from loopback?

I already have declared my datasource ,my model and the connector between these.
My model
{
"name": "container",
"base": "Model",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
Datasource
"storage": {
"name": "storage",
"connector": "loopback-component-storage",
"provider": "filesystem",
"root": "./server/storage"
}
My provider
{
"filesystem": {
"root": "./server/storage"
}
}
And the Connector
"container": {
"dataSource": "storage",
"public": true
}
I try posting a object like {"Object":"container1"} into path "./server/storage" but I get the following error from callback.
{
"error": {
"statusCode": 500,
"name": "TypeError",
"message": "Path must be a string. Received undefined",
"stack": "TypeError: Path must be a string. Received undefined.."
}
}
Please who can help me to find my issue? Thanks!
You can also use "name" instead of "Object" as key in your JSON object to create a new container/directory using the API.
POST /api/containers {"name":"container1"}
The way to post a container is, without using the loopback api. Create a folder that is gonna be the container into your provider path (being filesystem).
As simple as that!
If you need a programmatic way to add new containers, let's say for example you want to create a filesystem of sorts for new users. You can use the route below. "Container" is the name I called my Model, you can call yours whatever you'd like.
POST localhost:3000/api/container
Inside the body of the post request you have to have an attribute name and the value of the name can be the new container you're creating. The Strongloop/Loopback documentation, which can be found here, is not accurate and neither is the error you get back when you try to post it with their directions.
"error": {
"statusCode": 500,
"name": "TypeError",
"message": "Path must be a string. Received undefined"
}
An excerpt of the code to send a post request to create a new container is also below.
var request = require("request");
var options = {
method: 'POST',
url: 'http://localhost:3000/api/containers',
body: { name: 'someNewContainer' },
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});

Sending email notifications for Events via Google Calendar API

I'm using the calendar.events.insert API to add an Event to my Calendar via the PHP client.
The event is being inserted correctly along with appropriate values as set by the API.
The same however is not able to trigger an email invite to the attendees. I looked around to find that the request needs to set the param sendNotifications as true.
The same doesn't seem to help either.
Here is a sample code:
var request = gapi.client.calendar.events.insert({
"calendarId" : calendarData.id,
"sendNotifications": true,
"end": {
"dateTime": eventData.endTime
},
"start": {
"dateTime": eventData.startTime
},
"summary": eventData.eventName,
"attendees": jQuery.map(eventData.attendees, function(a) {
return {'email' : a};
}),
"reminders": {
"useDefault": false,
"overrides": [
{
"method": "email",
"minutes": 15
},
{
"method": "popup",
"minutes": 15
}
]
}
});
Where eventData and calendarData are appropriate objects.
Although my main problem is with email invites being sent the first time, I also tried (as can be seen above) to set a reminder (using overrides). While the popup works as expected, I didn't receive an email update in this case either.
This makes me wonder whether this may be a permission issue - something which I need to enable for my app perhaps (the user would understandably need to know if my app is sending emails on their behalf)?
In the Google API Documentation for inserting events, the "sendNotifications" option is actually a parameter. You might want to put it in the request parameters instead of the body.
In Meteor
Note: In my Meteor application, I did did the request by hand, and I'm still new to JavaScript. I'm not sure how you would do that in plain JavaScript or with the calendar API, so I'll just put the Meteor code, hope it helps although it's a bit off-topic.
var reqUrl = "https://www.googleapis.com/calendar/v3/calendars/primary/events";
var payload = {
'headers' : {
'Authorization': "Bearer " + token,
'Content-Type': 'application/json'
},
'params': {
'sendNotifications': true
},
'data': {
"summary": summary,
"location": "",
"start": {
"dateTime": start
},
"end": {
"dateTime": end
},
"attendees": [
{
"email": "*********#gmail.com"
}
]
}
};
Meteor.http.post(reqUrl, reqParams, function () {});
#linaa is correct. Just ran into this issue myself.
In JS, this would look like:
var request = gapi.client.calendar.events.insert(
sendNotifications: true,
{
// request body goes here
}
);
For this you should set the "remindOnRespondedEventsOnly" value to "true".
which means, Whether event reminders should be sent only for events with the user’s response status “Yes” and “Maybe”.
You can find this information here.
Hope that helps!
event = service.events().insert(calendarId='primary', body=event, sendUpdates='all').execute()
this will work

Categories