Invalid credentials error in Angularfire2 oauth login - javascript

I'm trying to login to my Ionic 2 app using Facebook native and Angularfire2 (2.0.0-beta.2), but even though I am successfully getting an access token, no matter how I try to pass it in to angularfire's auth.login function it still throws an invalid credentials error.
Here is my config:
firebaseAuthConfig({
provider: AuthProviders.Facebook,
method: AuthMethods.OAuthToken,
remember: "default",
scope: ["email"]
})
And here is my login function:
login() {
Facebook.login(["public_profile", "email", "user_friends"])
.then((success) => {
console.log("Facebook success: " + JSON.stringify(success));
this.af.auth.login(success.authResponse.accessToken, { provider: AuthProviders.Facebook })
.then((success) => {
console.log("Firebase success: " + JSON.stringify(success));
})
.catch((error) => {
console.log("Firebase failure: " + JSON.stringify(error));
});
})
.catch((error) => {
console.log("Facebook failure: " + JSON.stringify(error));
});
}
And here is the error I get in my console.log:
Facebook failure: {"code":"auth/argument-error","message":"signInWithCredential failed: First argument \"credential\" must be a valid credential."}
It's interesting that it's being caught at the Facebook level instead of the catch I have set up for the auth.login. I have tried passing it in several different ways including as an object { token: success.authResponse.accessToken } and I'm at a loss now. Can anyone help me see what I'm doing wrong? Thanks!
Also, I don't think this is related, but just in case it is I am also receiving a "operation has timed out error" that's not being caught but seems to be thrown by my this.af.auth.subscribe call. The app keeps running fine but perhaps that could be what's making the login fail?

import {Component} from '#angular/core';
import {Platform, ionicBootstrap} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {HomePage} from './pages/home/home';
import {Facebook} from 'ionic-native';
import {
FIREBASE_PROVIDERS, defaultFirebase,
AngularFire, firebaseAuthConfig, AuthProviders,
AuthMethods
} from 'angularfire2';
declare let firebase: any; // <== THERE IS AN ERROR IN THE .d.ts file
#Component({
template: '<ion-nav [root]="rootPage"></ion-nav>',
providers: [
FIREBASE_PROVIDERS,
// Initialize Firebase app
defaultFirebase({}),
firebaseAuthConfig({})
]
})
export class MyApp {
rootPage: any = HomePage;
constructor(platform: Platform, public af: AngularFire) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Facebook.login(['email'])
.then((_response) => {
console.log(_response)
// IMPORTANT STEP !!
let creds = firebase.auth.FacebookAuthProvider.credential(_response.authResponse.accessToken)
this.af.auth.login(creds,
{
provider: AuthProviders.Facebook,
method: AuthMethods.OAuthToken,
remember: 'default',
scope: ['email'],
})
.then((success) => {
console.log("Firebase success: " + JSON.stringify(success));
alert(JSON.stringify(success))
})
.catch((error) => {
console.log("Firebase failure: " + JSON.stringify(error));
alert(JSON.stringify(error))
});
})
.catch((_error) => { console.log(_error) })
});
}
}
ionicBootstrap(MyApp);
https://github.com/aaronksaunders/AngularFire2-Ionic2-Facebook

Related

How to push notification with firebase FCM to all users of my App with Ionic?

I need to notify all users with latest news , i did only notification
method with token of user but notification shown only on the device of
this user ,i need to notify all users
of my application , this code is for send notification by token of user only , how to send to group of users or all users ,
thanks for help
app.component.ts :
import { Component, OnInit } from '#angular/core';
import { CrudService } from './crud.service';
import { Platform } from '#ionic/angular';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { Router } from '#angular/router';
import {
ActionPerformed,
PushNotificationSchema,
PushNotifications,
Token,
} from '#capacitor/push-notifications';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss'],
})
export class AppComponent implements OnInit {
constructor(public crud: CrudService , private platform: Platform,
private statusBar: StatusBar,
public router:Router){
this.initializeApp();
crud.databaseConn();
crud.getUsersList();
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.router.navigateByUrl('splash');
});
}
ngOnInit() {
console.log('Initializing HomePage');
// Request permission to use push notifications
// iOS will prompt user and return if they granted permission or not
// Android will just grant without prompting
PushNotifications.requestPermissions().then(result => {
if (result.receive === 'granted') {
// Register with Apple / Google to receive push via APNS/FCM
PushNotifications.register();
} else {
// Show some error
}
});
PushNotifications.addListener('registration', (token: Token) => {
alert('Push registration success, token: ' + token.value);
console.log("token"+token.value)
});
PushNotifications.addListener('registrationError', (error: any) => {
alert('Error on registration: ' + JSON.stringify(error));
});
PushNotifications.addListener(
'pushNotificationReceived',
(notification: PushNotificationSchema) => {
var audio = new Audio("assets/bip_bip.mp3");
audio.play();
alert('Push received: ' + JSON.stringify(notification));
},
);
PushNotifications.addListener(
'pushNotificationActionPerformed',
(notification: ActionPerformed) => {
alert('Push action performed: ' + JSON.stringify(notification));
},
);
}
}
To send push notifications to multiple devices over FCM you need to use topics and subscribe certain group of users to the same topic.
For example:
import { PushNotifications } from "#capacitor/push-notifications";
import { FCM } from "#capacitor-community/fcm";
Import { Capacitor } from “#capacitor/core”;
// set up base push notifications with Capacitor
await PushNotifications.requestPermissions();
await PushNotifications.register();
let topic;
if (Capacitor.getPlatform() === ‘ios’) {
topic = ‘apple’
} else if (Capacitor.getPlatform() === ‘android’) {
topic = ‘google’
}
// set up Firebase Cloud Messaging topics
FCM.subscribeTo({ topic })
.then(r => console.log(`subscribed to topic “${topic}”`))
.catch(err => console.log(err));
Then on FCM console you can test it out with sending notification to those topics:
Like shown on this image
If you want to unsubscribe from topic you just use FCM.unsubscribeFrom()..

SvelteKit: 500: Module "stream" has been externalized for browser compatibility

I'm trying to setup a authenticated connection to Firebase using WebKit.
The below code "works" in a sense that I receive the data from Firebase Realtime Database as expected.
index.svelte
<script context="module">
// import serviceAccount from '../private/my-firebase-private-key.json'
import { google } from 'googleapis'
let firebaseAccessToken
const serviceAccount = {
"type": "service_account",
"project_id": "my-test-project-xxxxxx",
"private_key_id": "0d33XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"private_key": "-----BEGIN PRIVATE KEY-----\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-xxxxx#my-test-project-xxxxxx.iam.gserviceaccount.com",
"client_id": "9999999999999999999999",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-xxxxxx%40my-test-project-xxxxxx.iam.gserviceaccount.com"
}
async function firebaseAuth() {
let scopes = [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/firebase.database',
]
let jwtClient = new google.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
scopes
)
return new Promise((
resolve,
reject
) =>
jwtClient.authorize((error, tokens) => {
if (error) {
console.log('Error making request to generate access token:', error)
reject(error)
} else if (tokens.access_token === null) {
console.log(
'Provided service account does not have permission to generate access tokens'
)
reject(error)
} else {
firebaseAccessToken = tokens.access_token
resolve(tokens.access_token)
}
})
)
}
// export async function load({ page, fetch, session, context }) {
export async function load({ fetch }) {
await firebaseAuth()
// console.log(`firebaseAccessToken: ${firebaseAccessToken}`)
const res = await fetch(
'https://myfirebasedatabase.app/jsondb.json',
{
headers: { 'Authorization': `Bearer ${firebaseAccessToken}` },
}
)
const data = await res.json()
if (!res.ok) {
return {
status: res.status,
error: new Error('Could not fetch data'),
}
}
return { props: { myData : data } } <-- DATA is RECEIVED
}
</script>
<script>
export let myData
onMount(() => {
console.log(myData) <---------------- NEVER EXECUTED
})
</script>
The problem is that the UI shows the following error ...
500: Module "stream" has been externalized for browser compatibility and cannot be accessed in client code.
... handled by this __error.svelte file
<script context="module">
export function load({ error, status }) {
return {
props: {
title: `${status}: ${error.message}`
}
};
}
</script>
<script>
export let title;
</script>
<h1>{title}</h1>
I feel like it has something to do with Vite or another configuration stuff but I have too little experience with svelte to be sure. Did you have this kind of error previously?
Thanks for your help.
Side note: the code codes from NodeJs Authenticate REST Requests Documentation from Google and uses the Google APIs NodeJS Library
I have the same error only writen only this line of code
import { google } from 'googleapis'
get the same error 500.
But when add this config for vite server in svelte.config.js file
//svelte.config.js
vite: {
optimizeDeps: {
exclude: ['googleapis']
}
}
get this error:
The requested module '/node_modules/googleapis/build/src/index.js?v=9d844668' does not provide an export named 'google'
I've seen in the browser/devtools network option, when i use exclude de size of index.js file is 70 Kb, but when is use include the size is 46 Mb.
I think is purely error of vite server to try load node_modules in webbrowser of client side.
If i found a solution for this error surely share the solution
Regards!.

firebaseAuth.onAuthStateChanged return user null

I'm trying to implement authentification using firebase auth, the things is that when it comes to persistance i'm stuck.
I tried to use local storage as you can see below :
AuthService.ts :
import {HttpClient} from '#angular/common/http';
import { Injectable } from '#angular/core';
import {AngularFireAuth} from '#angular/fire/auth';
import {Router} from '#angular/router';
import firebase from 'firebase/app';
#Injectable({
providedIn: 'root'
})
export class AuthService {
userData: any;
constructor(private http: HttpClient, private firebaseAuth: AngularFireAuth, private router: Router) {
this.firebaseAuth.useEmulator('http://localhost:9099');
this.firebaseAuth.authState.subscribe(user => {
if (user) {
this.userData = user;
localStorage.setItem('user', JSON.stringify(this.userData));
JSON.parse(localStorage.getItem('user'));
} else {
localStorage.setItem('user', null);
JSON.parse(localStorage.getItem('user'));
}
});
this.firebaseAuth.onAuthStateChanged( user => {
console.log(user);
});
}
signIn(email: string, password: string): void {
this.firebaseAuth.setPersistence(firebase.auth.Auth.Persistence.LOCAL).then(() => {
this.firebaseAuth.signInWithEmailAndPassword(email, password)
.then(result => {
this.router.navigate(['/dashboard/accueil']);
console.log('Nice, it worked!');
})
.catch(error => {
console.log('Something went wrong:', error.message);
});
}).catch(error => {
console.log('Something went wrong:', error.message);
});
}
signOut(): void {
this.firebaseAuth.signOut().then(() => {
localStorage.removeItem('user');
this.router.navigate(['/dashboard/connexion']);
});
}
forgetPassword(email: string): void {
this.firebaseAuth.sendPasswordResetEmail(email).then(() => {
window.alert('Password reset email sent, check your inbox.');
}).catch((error) => {
window.alert(error);
});
}
get isLoggedIn(): boolean {
const user = JSON.parse(localStorage.getItem('user'));
return (user !== null) ? true : false;
}
}
But the problem is that firebaseAuth.onAuthStateChanged return null after refreshing the page with F5 even authState. It's like onAuthStateChange is losing his last state after refresh.
Note that i'm using firebase Emulator.
app.module.ts
Firebase module has been well import
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
You can take a look at the confing here :
environnement.ts
firebase: {
apiKey: 'xxxxxxxxxxxx',
projectId: 'xxxx'
}
Maybe it's link to this error that i'm getting in the web console when i'm refreshing the page :
POST https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=xxxxxxx 400
Note that key is equal to my apiKey state in the config.
When i look closer here what the error say :
{
"error": {
"code": 400,
"message": "INVALID_ID_TOKEN",
"errors": [
{
"message": "INVALID_ID_TOKEN",
"domain": "global",
"reason": "invalid"
}
]
}
}
Any help would be greatly appreciate.
EDIT
Here what i get after refresh my page from onAuthStateChanged :
There is no 2 calls, only 1 that return false.
Firebase Auth will persist the login state by default, so you don't have to manually save the token into local storage. As Frank said, onAuthStateChanged will fire will user being null initially, but if the user is signed in, it will fire again shortly after that with the actual user value.
Following to the comment section of the accepted answer, I decided to highlight the fact that this appears to be en emulator issue.
This was driving me crazy. No matter what I did, even jumping up and down, the currentUser was always null. I saw the same behavior: onAuthStateChanged() got called only once and all I got was a null-user.
After removing my provider for the Auth-emulator, everything started to work without issues.
providers: [
// ...
{ provide: REGION, useValue: envFirebase.region},
// THE PROBLEM:
{
provide: USE_AUTH_EMULATOR,
useValue: envFirebase.useEmulators ? ['http://localhost:9099'] : undefined
},
],

Firebase Authentication "auth/invalid-email" and "The email address is badly formatted."

I am trying to implement Firebase login/registration into my app using Angular and Ionic 4. I have the registration of my account working and forgetting the password working I can see the accounts in my firebase console. The issue I am having is when I try to log into that account I created. In the developer console I get https://imgur.com/a/WzRiwtn :
code: "auth/invalid-email"
message: "The email address is badly formatted."
Its saying the issue lies in my tab3.page.ts:22
Here is the code from that page
import { Component } from '#angular/core';
import { AlertController } from '#ionic/angular';
import { LoadingController, ToastController } from '#ionic/angular';
import { Router } from '#angular/router';
import { AngularFireAuth } from '#angular/fire/auth';
#Component({
selector: 'app-tab3',
templateUrl: 'tab3.page.html',
styleUrls: ['tab3.page.scss']
})
export class Tab3Page {
email: string = '';
password: string = '';
error: string = '';
constructor(private fireauth: AngularFireAuth,
private router: Router,
private toastController: ToastController,
public loadingController: LoadingController,
public alertController: AlertController) {
}
async openLoader() {
const loading = await this.loadingController.create({
message: 'Please Wait ...',
duration: 2000
});
await loading.present();
}
async closeLoading() {
return await this.loadingController.dismiss();
}
login() {
this.fireauth.auth.signInWithEmailAndPassword(this.email, this.password)
.then(res => {
if (res.user) {
console.log(res.user);
this.router.navigate(['/home']);
}
})
.catch(err => {
console.log(`login failed ${err}`);
this.error = err.message;
});
}
async presentToast(message, show_button, position, duration) {
const toast = await this.toastController.create({
message: message,
showCloseButton: show_button,
position: position,
duration: duration
});
toast.present();
}
}
I have been staring at this since Friday trying multiple different methods and guides online and every method I try I am getting this error any help would be VERY much appreciated. This code came from following this https://enappd.com/blog/email-authentication-with-firebase-in-ionic-4/38/ tutorial and even looking at his github and following it exactly I still come to this issue.
Here is your error type
https://firebase.google.com/docs/auth/admin/errors
Hopefully email which you are passing having issue. It should be proper string only.
From what you're showing here, email has an initial value of an empty string:
email: string = '';
And, from what I can see, it never changes value. So you're passing an empty string to signInWithEmailAndPassword, which isn't valid.
Firebase Authentication "auth/invalid-email" and "The email address is badly formatted."
Use an email format like:
test#test.com
test123#gmail.com
change ' ' to null.
better still update to
const [email, setEmail] = useState(null);

Cannot make a simple http GET call in Angular2

I am trying to make a simple http GET request from my Angular2 app:
this.http.get("https://mybaseurl.com/hello")
.map(res => res.json())
.subscribe(
function(response) { console.log("Success Response" + response)},
function(error) { console.log("Error happened" + error)},
function() { console.log("the subscription is completed")}
);
The Node.js server is configured this way:
app.get('/hello', function(req, res) {
res.send("hellow world");
});
When I make the call I keep getting this error:
caused by: unable to parse url 'https://mybaseurl.com/hello'; original error: Cannot read property 'split' of undefined
at InMemoryBackendService.parseUrl (in-memory-backend.service.ts:518)
at InMemoryBackendService.handleRequest (in-memory-backend.service.ts:279)
at InMemoryBackendService.createConnection (in-memory-backend.service.ts:240)
Any idea what am I doing wrong?
edit: pasting the entire class code:
import {Component} from '#angular/core';
import {Auth} from './auth.service';
import {AuthHttp} from 'angular2-jwt';
import {Http} from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'ping',
templateUrl: 'app/ping.template.html'
})
export class ApiService {
API_URL: string = 'https://myapp.herokuapp.com';
message: string;
constructor(private auth: Auth, private http: Http, private authHttp: AuthHttp) {}
public ping() {
this.http.get(`${this.API_URL}/hello`)
.map(res => res.json())
.subscribe((response) => {
console.log("Success Response" + response)
},
(error) => { console.log("Error happened" + error)},
() => { console.log("the subscription is completed")}
);
}
}
=====>
This looks like a HUGE bug in Angular2 - all http requests return null, or an error message describing it is not in the required pattern.
I someone has a working demo of HTTP GET I would love to see
It looks like using InMemoryWebApiModule.forRoot(InMemoryDataService) in #NgModule simultaneously with Http.get causes uncovered urls to return null and error.
Setting it this way worked for me:
InMemoryWebApiModule.forRoot(InMemoryDataService, {passThruUnknownUrl: true})
Maybe it is beacause of your answer from server - you send string to client, but in map function you try to call res.json(). Can you comment map function call?
Check by using arrow function for success and error as below :
this.http.get("https://mybaseurl.com/hello")
.map(res => res.json())
.subscribe((response) => { console.log("Success Response" + response)},
(error) => { console.log("Error happened" + error)},
() => { console.log("the subscription is completed")}
);

Categories