Why is this core package being called? - meteor

I am trying to authenticate with Google through OAuth, and this is my server code
my.fetchTokens = function(code) {
var endpoint = 'https://accounts.google.com/o/oauth2/token';
var params = {
code: code,
client_id: Meteor.settings.google.CLIENT_ID,
client_secret: Meteor.settings.google.CLIENT_SECRET,
redirect_uri: Meteor.settings.google.REDIRECT_URL,
grant_type: 'authorization_code',
};
try {
response = HTTP.post(endpoint, { params: params });
} catch (err) {
throw _.extend(new Error("Failed to complete OAuth handshake with Google. " + err.message),
{response: err.response});
}
if (response.data.error) { // if the http response was a json object with an error attribute
throw new Error("Failed to complete OAuth handshake with Google. " + response.data);
}
var tokens = {
accessToken: response.data.access_token,
refreshToken: response.data.refresh_token,
expiresIn: response.data.expires_in,
idToken: response.data.id_token
};
console.log(tokens);
return tokens;
};
But when I invoke this method, I get the following warnings
W20150316-10:30:05.853(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150316-10:30:05.854(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150316-10:30:05.855(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150316-10:30:05.855(1) (oauth_server.js:398) Error in OAuth Server: Match error: Expected string, got undefined
But I dont get why oauth_server.js:71 is being referenced
any ideas?

Probably because you're calling OAuth.openSecret or OAuth._redirectUri('google', config).
I assume one of these calls parses the current URL.

Related

Unable to send notification from an Expo React Native App using Azure Notification Hub REST API

I am trying to receive notifications in an Expo React Native App.
The notifications will be sent using Azure Notification Hub REST API
I followed the steps below :
Added the Android project in Firebase Console
To get the Server Key I followed - Firebase messaging, where to get Server Key?
Configured the FCM ServerKey in Azure Notification Hub
Added the google-services.json at the root in my React Native App and modified app.json as mentioned in - https://docs.expo.dev/push-notifications/using-fcm/
To register in ANH, we first need the SAS Token - https://learn.microsoft.com/en-us/rest/api/notificationhubs/common-concepts I generated the token with the following code
const Crypto = require('crypto-js');
const resourceURI =
'http://myNotifHubNameSpace.servicebus.windows.net/myNotifHubName ';
const sasKeyName = 'DefaultListenSharedAccessSignature';
const sasKeyValue = 'xxxxxxxxxxxx';
const expiresInMins = 200;
let sasToken;
let location;
let registrationID;
let deviceToken;
function getSASToken(targetUri, sharedKey, ruleId, expiresInMins) {
targetUri = encodeURIComponent(targetUri.toLowerCase()).toLowerCase();
// Set expiration in seconds
var expireOnDate = new Date();
expireOnDate.setMinutes(expireOnDate.getMinutes() + expiresInMins);
var expires =
Date.UTC(
expireOnDate.getUTCFullYear(),
expireOnDate.getUTCMonth(),
expireOnDate.getUTCDate(),
expireOnDate.getUTCHours(),
expireOnDate.getUTCMinutes(),
expireOnDate.getUTCSeconds()
) / 1000;
var tosign = targetUri + '\n' + expires;
// using CryptoJS
//var signature = CryptoJS.HmacSHA256(tosign, sharedKey);
var signature = Crypto.HmacSHA256(tosign, sharedKey);
var base64signature = signature.toString(Crypto.enc.Base64);
//var base64signature = signature.toString(CryptoJS.enc.Base64);
var base64UriEncoded = encodeURIComponent(base64signature);
// construct autorization string
var token =
'SharedAccessSignature sr=' +
targetUri +
'&sig=' +
base64UriEncoded +
'&se=' +
expires +
'&skn=' +
ruleId;
console.log('signature:' + token);
return token;
}
I then called the create registration API - https://learn.microsoft.com/en-us/rest/api/notificationhubs/create-registration-id
The registrationID has to be extracted from the response header of the API Call
I used the following code to generate the ANH Regsitration ID
async function createRegistrationId() {
const endpoint =
'https://xxxxxx.servicebus.windows.net/xxxxxxx/registrationIDs/?api-version=2015-01';
sasToken = getSASToken(resourceURI, sasKeyValue, sasKeyName, expiresInMins);
const headers = {
Authorization: sasToken,
};
const options = {
method: 'POST',
headers: headers,
};
const response = await fetch(endpoint, options);
if (response.status !== 201) {
console.log(
'Unbale to create registration ID. Status Code: ' + response.status
);
}
console.log('Response Object : ', response);
for (var pair of response.headers.entries()) {
//console.log(pair[0] + ': ' + pair[1]);
}
location = response.headers.get('Location');
console.log('Location - ' + location);
console.log('Type - ' + response.type);
registrationID = location.substring(
location.lastIndexOf('registrationIDs/') + 'registrationIDs/'.length,
location.lastIndexOf('?api-version=2015-01')
);
console.log('Regsitration ID - ', registrationID);
return location;
}
Next step was to update this registration ID in ANH with the Native Device Token
I used expo-notifications package and the method getDevicePushTokenAsync() method to get the native device token
async function registerForPushNotificationsAsync() {
let token;
if (Device.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const {
status
} = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
token = (await Notifications.getDevicePushTokenAsync()).data;
console.log(token);
} else {
alert('Must use physical device for Push Notifications');
}
if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
return token;
}
The native device token was in the following format on Android device
c6RI81R7Rn66kWZ0rar3M2:APA91bEcbLXGwEZF-8hu1yGHfXgWBNuxr_4NY_MR8d7HEzeHAJrjoJnjUlneAIiVglCNIGUr11qkP1G4S76bx_H7NItxfQhZa_bgnQjqSlSaY4-oCoarDYWcY-Mz_ulW8rQZFy_SA6_j
I then called the updateRegistrationId API - https://learn.microsoft.com/en-us/rest/api/notificationhubs/create-update-registration
async function updateRegistraitonId() {
//IF you use registrationIDs as in returned location it was giving 401 error
const endpoint =
'https://xxxxx.servicebus.windows.net/xxxxxxx/registrations/' +
registrationID +
'?api-version=2015-01';
const endpoint1 = location;
const headers = {
Authorization: sasToken,
'Content-Type': 'application/atom+xml;type=entry;charset=utf-8',
};
//Remember to create well-formed XML using back-ticks
//else you may get 400 error
//If you use the tags element it was giving an error
const regDATA = `<entry xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<GcmRegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">
<GcmRegistrationId>${deviceToken}</GcmRegistrationId>
</GcmRegistrationDescription>
</content>
</entry>`;
const options = {
method: 'PUT',
headers: headers,
body: regDATA,
};
const response = await fetch(endpoint, options);
if (response.status !== 201) {
console.log(
'Looks like there was a problem. Status Code: ' + response.status
);
console.log('Response Object : ', response);
//return;
}
}
According to API documentation, I should get 201 response, I got 200 response code . I am not sure if this is the issue
After this I had the notification handling code to recieve the notification,similar to the code in - https://docs.expo.dev/versions/latest/sdk/notifications/
I then tried to send notification using Test Send from ANH, it failed with the error -
**
"The Token obtained from the Token Provider is wrong"
**
I checked in ANH Metrics, the error was categorized as GCM Authentication error, GCM Result:Mismatch SenderId
I tried to check for documentation to add the SenderId , but I couldnt find anyway to inlcude the SenderId also in the payload of updateRegistration call (in xml atom entry)
I tried to use the device token and send directly from Firebase Console, I did not receive it either.
I used the Direct Send API of Azure notification Hub but still did not receive anything
I am suspecting there could be some issue in the way I am handling notifiations in the client device, I can fix that later , but first I will have to resolve the error I am getting in Test Send in Azure NH
Any help to be able to successfully send using Test Send in ANH or pointers ahead for next steps will be much appreciated

Vue.js+Firebase: 401 error, 'unauthorized'

When I try to use post method in my Vue project:
this.$http.post("https://vuejs-blog-b91df.firebaseio.com/posts.json", this.blog).then(function(data) {
console.log(data);
this.submitted = true;}
the console throws me an error:
Failed to load resource: the server responded with a status of 401 (Unauthorized)
Uncaught (in promise)
Response
body: {error: "Permission denied"}
bodyText: "{↵ "error" : "Permission denied"↵}↵"
headers: Headers {map: {…}}
ok: false
status: 401
statusText: "Unauthorized"
url: "https://project-name.firebaseio.com/posts.json"
data: (...)
__proto__: Object
Where and how should I put firebase project apiKey and other authorization data to succeed?
Authentication with access_token
Based on firbase authentication documentation, I think you must change your request URL to smth like this:
const token = 'token'; // get token somewhere
this.$http
.post(`https://vuejs-blog-b91df.firebaseio.com/posts.json?access_token=${token}`, this.blog)
.then((data) => {
console.log(data);
this.submitted = true;
});
Authentication with ID token
Or you may use ID token authentication like this:
const token = 'token'; // get token somewhere
this.$http
.post(`https://vuejs-blog-b91df.firebaseio.com/posts.json?auth=${token}`, this.blog)
.then((data) => {
console.log(data);
this.submitted = true;
});
Here you can find how to get ID token on client

Github OAuth using Firebase - how to get user's username

I followed the Firebase's guide on how to authenticate with Github. https://firebase.google.com/docs/auth/web/github-auth
The return result from Firebase's signInWithRedirect method contains the user's displayName and email, etc. However, it doesn't seem to contain user's 'login' username which is the key for invoking most of Github's API calls.
I am sure there is a way to get it, but I just can't seem to find any documentation. Does anyone happen to know how to solve it?
I ended up using Github's API to get user's username with accessToken.
You should be able to get the user's GitHub username through a parameter called "username" (see more here: https://github.com/firebase/firebase-simple-login/blob/master/docs/v1/providers/github.md)
Note: firebase-simple-login was deprecated on October 3th, 2014
You can use get the authenticated user from this GitHub's api
Or if you use octokit javascript rest api client, you can do something like this
octokit = new Octokit({auth: userAccessToken })
octokit.users.getAuthenticated()
.then(result => {
console.log(result.data.login) // this is the username
})
Note: you'll get accessToken after GitHub <-> firebase login
Hope this is helpful!
You can get the username in additionalUserInfo:
const githubProvider = new firebaseClient.auth.GithubAuthProvider();
githubProvider.addScope('read:user');
githubProvider.setCustomParameters({
allow_signup: false,
});
firebaseClient.initializeApp(clientConfig);
async function submit() {
try {
const response = await firebaseClient
.auth()
.signInWithPopup(githubProvider);
console.log(response.additionalUserInfo);
} catch (error) {
alert(error);
}
}
You Can use email to do authorized requests insted username:
Username: mayGitHubEmail#mail.com
Password: accessToken
like this with Postman
body sent
Here is a sample using class func in Swift using Alamofire and SwiftyJSON pods:
import Alamofire
import SwiftyJSON
enum NetworkError: Error {
case url
case server
case auth
}
class GistServices {
class func makePostApiCall(toUrl path: String, withBody parameters: JSON, usingCredentials: Bool = false) -> Result<Data?, NetworkError> {
guard let url = URL(string: path) else {
return .failure(.url)
}
if let email = UserAuthSingleton.shared.get(), let password = UserAuthSingleton.shared.getUserToken() {
var result: Result<Data?, NetworkError>!
var request = AF.request(url, method: .post, parameters: parameters)
if(usingCredentials){
let credentialData = "\(email):\(password)".data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!
let base64Credentials = credentialData.base64EncodedString()
let headers = [HTTPHeader(name: "Authorization", value: "Basic \(base64Credentials)"),
HTTPHeader(name: "Accept", value: "application/json"),
HTTPHeader(name: "Content-Type", value: "application/json")]
request = AF.request(url, method: .post, parameters: parameters.dictionaryValue, encoder: JSONParameterEncoder.default, headers: HTTPHeaders(headers))
}
request
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.response { (response) in
switch response.result {
case .failure(_):
result = .failure(.server)
case .success(let value):
result = .success(value)
}
}
return result
}
return .failure(.auth)
}
}

invalid_grant Google OAuth

I am trying to authentiate through Google's OAuth, but I'm having problems establishing a connection to their API
My client code:
'click #addChannel': function (event) {
event.preventDefault();
var userId = Meteor.userId();
var options = {
requestPermissions: [
'https://www.googleapis.com/auth/youtube',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/youtube.force-ssl',
'https://www.googleapis.com/auth/youtube.readonly',
'https://www.googleapis.com/auth/youtube.upload',
'https://www.googleapis.com/auth/youtubepartner',
'https://www.googleapis.com/auth/youtubepartner-channel-audit',
],
requestOfflineToken: true
};
Google.requestCredential(options, function(token) {
Meteor.call('userAddOauthCredentials', userId, token, function(error, result) {
if (error) {
throw error;
}
console.log(result);
});
});
My server code:
userAddOauthCredentials: function(userId, token) {
check(userId, String);
check(token, String);
var config = ServiceConfiguration.configurations.findOne({service: 'google'});
if (!config) {
throw new ServiceConfiguration.ConfigError();
}
console.log(token, config);
var endpoint = 'https://accounts.google.com/o/oauth2/token';
var params = {
code: token,
client_id: config.clientId,
client_secret: OAuth.openSecret(config.secret),
redirect_uri: OAuth._redirectUri('google', config),
grant_type: 'authorization_code',
};
try { <------------------------------------------------------ this fails
response = HTTP.post(endpoint, { params: params });
} catch (err) {
throw _.extend(new Error("(first) Failed to complete OAuth handshake with Google. " + err.message),
{response: err.response});
}
if (response.data.error) { // if the http response was a json object with an error attribute
throw new Error("(second) Failed to complete OAuth handshake with Google. " + response.data);
} else {
return {
accessToken: response.data.access_token,
refreshToken: response.data.refresh_token,
expiresIn: response.data.expires_in,
idToken: response.data.id_token
};
}
The above throws a [400] { "error" : "invalid_grant" } error.
Most of the above code I got from how the meteor accounts-google packages logs in a user (which works fine in my application). Link to that:
https://github.com/meteor/meteor/blob/87e3c6499d5eacce62f10faefe9ce49c77bb03ee/packages/google/google_server.js
Any advice on how to proceed from here?
Much appreciated
UPDATE1:
I get these warnings in my log
W20150318-09:11:42.532(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150318-09:11:42.532(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150318-09:11:42.533(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150318-09:11:42.534(1) (oauth_server.js:398) Error in OAuth Server: Match error: Expected string, got undefined
You have to parse your var params to application/x-www-form-urlencoded. Please find the below code to parse as i done in php
$fields_string="";
foreach($params as $key=>$value)
{
$fields_string .= $key.'='.$value.'&';
}
rtrim($fields_string, '&');
Now the $filed_string will contained the parse of params array.

Meteor.js and Custom OpenId Connect server

How to do authentication via custom token server in Meteor.js?
Is there any package like accounts-google for custom token server which handles authentication by just taking token endpoints, client id, secrete, and scope as configuration parameter.
I don't know of a generic oauth package. But it shouldn't be too difficult to write a package for your particular server, as there are a number of examples to look at.
Using accounts-github as an example, here's the code for making the connection on the client. Note the endpoint URL, client id, scope, etc. This will handle the popup for you, but you'll probably want to include custom CSS:
var loginUrl =
'https://github.com/login/oauth/authorize' +
'?client_id=' + config.clientId +
'&scope=' + flatScope +
'&redirect_uri=' + OAuth._redirectUri('github', config) +
'&state=' + OAuth._stateParam(loginStyle, credentialToken);
OAuth.launchLogin({
loginService: "github",
loginStyle: loginStyle,
loginUrl: loginUrl,
credentialRequestCompleteCallback: credentialRequestCompleteCallback,
credentialToken: credentialToken,
popupOptions: {width: 900, height: 450}
});
And here's a snippet from the server side, completing the process to get an access token:
var getAccessToken = function (query) {
var config = ServiceConfiguration.configurations.findOne({service: 'github'});
if (!config)
throw new ServiceConfiguration.ConfigError();
var response;
try {
response = HTTP.post(
"https://github.com/login/oauth/access_token", {
headers: {
Accept: 'application/json',
"User-Agent": userAgent
},
params: {
code: query.code,
client_id: config.clientId,
client_secret: OAuth.openSecret(config.secret),
redirect_uri: OAuth._redirectUri('github', config),
state: query.state
}
});
} catch (err) {
throw _.extend(new Error("Failed to complete OAuth handshake with Github. " + err.message),
{response: err.response});
}
if (response.data.error) { // if the http response was a json object with an error attribute
throw new Error("Failed to complete OAuth handshake with GitHub. " + response.data.error);
} else {
return response.data.access_token;
}
};
And utilizing the token to get the user identity:
var getIdentity = function (accessToken) {
try {
return HTTP.get(
"https://api.github.com/user", {
headers: {"User-Agent": userAgent}, // http://developer.github.com/v3/#user-agent-required
params: {access_token: accessToken}
}).data;
} catch (err) {
throw _.extend(new Error("Failed to fetch identity from Github. " + err.message),
{response: err.response});
}
};
The github and the accounts-github packages should be very helpful as references.

Resources