Firebase Phone Auth Error 400 - firebase

Just getting started with Firebase phone auth. Seems pretty slick however I've hit a wall with a bug.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalid",
"message": "SESSION_EXPIRED"
}
],
"code": 400,
"message": "SESSION_EXPIRED"
}
}
Starting with the Captcha: (standard documentation code!)
var applicationVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
'size': 'invisible',
'callback': function(response) {
},
'expired-callback': function() {
}
});
Its rendered and the captcha works well.
Next is the sign-in bit where you are sent the auth code to your phone. Works great:
$scope.signInWithPhoneNumber = function signInWithPhoneNumber() {
var phoneNumber = "*censored*";
var appVerifier = window.recaptchaVerifier;
firebase.auth().signInWithPhoneNumber(phoneNumber, applicationVerifier)
.then(function (confirmationResult) {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
window.confirmationResult = confirmationResult;
$scope.setConfirmationResult(confirmationResult);
alert('Result: ' + JSON.stringify(confirmationResult));
}).catch(function (error) {
// Error; SMS not sent
alert('Error: ' + error);
// ...
});
};
Finally its the authentication of the code that the user inputs from the text message. Here is when I get the error 400:
$scope.AuthenticateCode = function (code) {
var code = String(document.getElementById("auth_code").value);
var confirmationResult = $scope.getConfirmationResult();
alert(code);
confirmationResult.confirm(code).then(function (result) {
// User signed in successfully.
var user = result.user;
console.log('Signed In! ' + JSON.stringify(user));
// ...
}).catch(function (error) {
// User couldn't sign in (bad verification code?)
// ...
});
}//end of AuthenticateCode
The error is coming from the VerifyPhone method:
https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPhoneNumber?key=censored
Any help or ideas?
Many Thanks,
Kieran

Ok, there are 2 likely reasons:
The code expired. The user took too long to provide the SMS code and finish sign in.
The code was already successfully used. I think this is the likely reason. You need to get a new verificationId in that case. Get a new reCAPTCHA token via the invisible reCAPTCHA you are using.

You are most likely to forget the "Country Code" before the phone no.
That is why firebase throw error 400 which means invalid parameters

If it's an Ionic3 project, change the following lines:
Imports:
import { AngularFireAuth } from 'angularfire2/auth';
import firebase from 'firebase';
Create var:
public recaptchaVerifier: firebase.auth.RecaptchaVerifier;
on "ionViewDidLoad()"
this.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
on "your_method(phoneNumber: number)"
const appVerifier = this.recaptchaVerifier;
const phoneNumberString = "+" + phoneNumber;
this.fireAuth.auth.signInWithPhoneNumber(phoneNumberString, appVerifier)
.then(confirmationResult => {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
let prompt = this.alertCtrl.create({
title: 'Enter the Confirmation code',
inputs: [{ name: 'confirmationCode', placeholder: 'Confirmation Code' }],
buttons: [
{
text: 'Cancel',
handler: data => { console.log('Cancel clicked'); }
},
{
text: 'Send',
handler: data => {
confirmationResult.confirm(data.confirmationCode)
.then(result => {
// Phone number confirmed
}).catch(error => {
// Invalid
console.log(error);
});
}
}
]
});
prompt.present();
})
.catch(error => {
console.error("SMS not sent", error);
});
Reference:
Firebase Phone Number Authentication

I got into a similar situation when a POST request to google API was returning Bad Request 400. When the message was logged, it said:
All requests from this device are blocked due to Unusual Activity. Please try again later
The issue was when the ReCaptcha was sensing a bot out of my development environment and it worked well when I tried later. During the rest of the development, I turned off this feature for easy work.

Related

Issue with sending LiveChat messages via DDP in RocketChat

I am trying to use the DDP Realtime API to initiate a LiveChat conversation but I am facing issues.
https://rocket.chat/docs/developer-guides/realtime-api/livechat-api
I am doing all the steps as per the documentation. In the first API outcome, you can see that it saus numAgents: 2 and online: true. However when I try to send a message to the same department, it says: "Sorry, no online agents".
Is there a way to find out the problem?
Result of livechat:getInitialData
{ enabled: true,
title: 'xyz.com',
color: '#C1272D',
registrationForm: false,
room: null,
triggers: [],
departments:
[ { _id: 'CxCTgXL4csw3TcW6S',
enabled: true,
name: 'Support',
description: '',
numAgents: 2,
showOnRegistration: true,
_updatedAt: 2017-09-24T06:46:39.657Z } ],
allowSwitchingDepartments: true,
online: true,
offlineColor: '#666666',
offlineMessage: 'We are not online right now. Please leave us a message:',
offlineSuccessMessage: '',
offlineUnavailableMessage: '',
displayOfflineForm: true,
videoCall: true,
offlineTitle: 'Leave a message',
language: '',
transcript: false,
transcriptMessage: 'Would you like a copy of this chat emailed?' }
Result of livechat:registerGuest
{ userId: 'j65Cp5peeLJLYhWQi',
token: 'J8IpnpB1yN1AYtO0e0EzLhuaRhe0zaZkjHBAamsehSO' }
Result of Login
{ id: 'j65Cp5peeLJLYhWQi',
token: 'J8IpnpB1yN1AYtO0e0EzLhuaRhe0zaZkjHBAamsehSO',
tokenExpires: 2017-12-23T07:45:01.928Z }
Result of sendMessageLivechat
{ isClientSafe: true,
error: 'no-agent-online',
reason: 'Sorry, no online agents',
message: 'Sorry, no online agents [no-agent-online]',
errorType: 'Meteor.Error' }
These are the parameters I am sending to sendMessageLiveChat.
"_id" : "j65Cp5peeLJLYhWQi"
"rid" : "a_random_string"
"msg": "Hello"
"token" : "J8IpnpB1yN1AYtO0e0EzLhuaRhe0zaZkjHBAamsehSO"
Could someone help me?
This is how I called registerGuest.
ddpClient.call("livechat:registerGuest",[{"token":authToken,"name":"test1","email":"test2#gmail.com","department":department._id},25],function(err, info){
});
the token passed by me here is the admin's authToken
The ddpClient object is obtained using the DDP npm package.
I solved this by a combination of
setting the bot as livechat agent & manager at the same time (I've read that tip somewhere it might be nonsense)
in Admin -> Omnichannel -> routing I've set 'accept even when no agents are online' (since my bot was never online, bould it was replying when DMessaged) + 'assign bot agents to new conversations'
I've setup myself a livechat-manager + livechat-agent role, but stayed in a different department, that way I can takeover
The rocket chat live api docs are quite out of date, just got stream-room-messages working because of a random forum post. Generally, registerGuest works with very minimal parameters as well, namely a random, self generated token + a name.
Here's my code for the complete setup
async subscribeToLiveRoom(message){
var _self = this
// let initial = await this.api
// .call("livechat:getInitialData",[token])
// register
const token = this.randomString()
var guestUser = await this.api
.call(
'livechat:registerGuest',
[{
token: token,
name: _self.$auth.user.name
}]
)
.catch(console.error)
console.log('guest', guestUser.visitor.token)
this.setActiveGuest(guestUser)
var roomId = this.randomString()
this.setActiveRoom(roomId)
let msg = await this.api
.call(
'sendMessageLivechat',
[{
_id: _self.randomString(),
rid: roomId,
msg: message,
token: guestUser.visitor.token
}])
.catch(console.error)
try {
let liveStream = await this.$subscribe("stream-livechat-room",[
roomId,
{
"useCollection": true,
"args":[
{
"visitorToken": guestUser.visitor.token
}
]
}
])
this.msgLive = await this.find('stream-livechat-room')
} catch (e) {
console.log(e)
}
//
try {
var roomStream = await this.$subscribe("stream-room-messages",[
roomId,
{
"useCollection": true,
"args":[
{
"visitorToken": guestUser.visitor.token
}
]
}
])
console.log('roomstream')
var update = this.find('stream-room-messages')
} catch (e) {
console.log('an error occured', e)
}
console.log( this.msg)
},
async sendToLiveRoom(message, rId){
var _self = this
// let initial = await this.api
// .call("livechat:getInitialData",[token])
// register
let msg = await this.api
.call(
'sendMessageLivechat',
[{
_id: _self.randomString(),
rid: rId,
msg: message,
token: _self.guest.visitor.token
}])
.catch(console.error)
},
By the way, since it's not well documented, you will get room-messages in livechat rooms via subscribing to stream-room-messages while you get room status changes (like switched to another agent) by subscribing to stream-livechat-room

How to create user by Nativescript firebase plugin?

I'm using EddyVerbruggen's NativeScript firebase plugin - https://github.com/EddyVerbruggen/nativescript-plugin-firebase
Firebase has been configured properly. I ran the following code & it's working fine.
firebase.init(<any>{
persist: true, // Allow disk persistence. Default false.
url: config.apiUrl
}).then(
function (instance) {
console.log("firebase.init done");
},
function (error) {
console.log("firebase.init error: " + error);
}
);
But, when I'm trying to create user through email id & password by using following code
firebase.createUser({
email: 'eddyverbruggen#gmail.com',
password: 'firebase'
}).then(
function (result) {
// dialogs.alert({
// title: "User created",
// message: "userid: " + result.key,
// okButtonText: "Nice!"
// })
alert('User Created with user id - '+result.key);
},
function (errorMessage) {
// dialogs.alert({
// title: "No user created",
// message: errorMessage,
// okButtonText: "OK, got it"
// })
alert('No user created. Got error message insted - '+errorMessage);
}
)
I'm getting message from my console like this -
JS: --- auth state changed: com.google.android.gms.internal.zzadg#399fbe6
The main parent file is -
import {Injectable} from "#angular/core";
import {User} from "./user";
import {ConfigService} from "../config";
import firebase = require("nativescript-plugin-firebase");
#Injectable()
export class UserService {
register(user: User,config:ConfigService) {
alert("API url going to use is : "+config.apiUrl);
firebase.init(<any>{
persist: true, // Allow disk persistence. Default false.
url: config.apiUrl
}).then(
function (instance) {
console.log("firebase.init done");
},
function (error) {
console.log("firebase.init error: " + error);
}
);
firebase.createUser({
email: 'eddyverbruggen#gmail.com',
password: 'firebase'
}).then(
function (result) {
// dialogs.alert({
// title: "User created",
// message: "userid: " + result.key,
// okButtonText: "Nice!"
// })
alert('User Created with user id - '+result.key);
},
function (errorMessage) {
// dialogs.alert({
// title: "No user created",
// message: errorMessage,
// okButtonText: "OK, got it"
// })
alert('No user created. Got error message insted - '+errorMessage);
}
)
}
}
when in checking in my firebase app account user account also not reflecting.
I know, there is a small mistake, because of which it's not working. But, can't able to figure out what causing the problem.
-------Error Fixed-------
Whole time I was testign in an Emulator which has no Google Play Service installed. It required Google Play Service to work. Finally, when I tested this in my mobile device it's worked fine.

How to display ionic2 Alert after Firebase changeEmail

I have the following function to change the email on a Firebase user account. I want to display an ionic2 alert when complete, whether it was successful or there was an error. From my code below I do get the alert to display BUT it is blank. Most likely it is a timing issue on the Firebase promise but I don't know how to fix it.
private doChangeEmail(data): void {
var myAlert: {
title?: string,
subtitle?: string
} = {};
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, function(error) {
if (error) {
switch (error.code) {
case "INVALID_PASSWORD":
myAlert.title = 'Invalid Password';
myAlert.subtitle = 'The specified user account password is incorrect.';
break;
case "INVALID_USER":
myAlert.title = 'Invalid User';
myAlert.subtitle = 'The specified user account does not exist.';
break;
default:
myAlert.title = 'Error creating user';
myAlert.subtitle = error;
}
} else {
myAlert.title = 'DONE';
myAlert.subtitle = 'User email changed successfully!';
}
});
let alert = Alert.create({
title: myAlert.title,
subTitle: myAlert.subtitle,
buttons: [{
text: 'OK',
handler: () => {
}
}]
});
this.nav.present(alert);
}
put the alert code inside the promise result....
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, function(error) {
if (error){
// do error stuff..
} else {
// do success stuff..
}
// show alert here...
})
I found the following comment by Frank van Puffelen which solved my issue:
You're using this inside a callback function, where it has a different meaning. One solution is to use fat-arrow/rocket notation for the callback, which ensures this is what you expect it to be:
The correct syntax should be
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, (error) => {
if (error){
// do error stuff..
} else {
// do success stuff..
}
// show alert here...
})
and the alert shows correclty as pointed out by Aaron Saunders

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.

Empty Facebook friends list

So I'm using the "Facebook-sdk" plugin. I'm initializing Facebook like this:
FB.init({ appId: 'xxxxxxxxxxx', cookie: true, xfbml: true, oauth: true, status: true });
FB.login(function(){ // get permissions
}, {scope: 'user_friends, read_friendlists, user_photos, email, publish_actions '});
FB.getLoginStatus(function (response) { // to generate AccessToken
if (response.authResponse) {
console.log('LoginStatusResponse: ' + JSON.stringify(response, null, 4));
} else {
console.log('AuthResponse: No');
}
});
Then in response to a button click event, I'm doing:
'click #get_fb_friends' : function(event, template) {
FB.api(
"/me/friends",
function (response) {
if (response && !response.error) {
console.log('GOT them !!!' + JSON.stringify(response, null, 4));
return response;
} else {
console.log('No can do' + JSON.stringify(response, null, 4));
}
});
}
The thing is that I'm getting an empty Data variable:
GOT them !!!{
"data": []
}
PS: The query "/me" returns all information about myself, it's the "/me/friends" that doesn't work.
Can it be a permissions problem ?
Facebook has changed its api a few weeks ago,you can only access a list of your friends when they have personally accepted to use your app.. Nothing to do about it
Like #Wampie said, the API has changed, so you could try to use the v1 API (keep in mind that you'll need to request a new access token).
And you can still invite friends to your app by using the apprequests method.
FB.ui({
method: 'apprequests',
message: 'You should learn more about the Platform.'
}, function(){
console.log(arguments);
});
Example here:
https://www.fbrell.com/fb.ui/apprequests

Resources