angularfire login with a previously issued firebase token - angularjs

I am using a separate server that authenticates my angular app. As part of that process the server has already authenticated the user with firebase and has received an auth_token back. Once the angular app is served, I re-request the token from my server and now I want to issue an angularFireAuth.login().
I have tried this but get a "Reference Error unrecognized auth". Am I missing something very fundamental? Shouldn't I be able to login with a pre-existing firebase auth_token??
Here is the code:
var profileController = function ($rootScope, $scope, $log, $location, angularFire, angularFireAuth, profileService) {
init();
function init() {
$scope.profile = {};
profileService.getFirebaseToken(function success(data) {
$scope.auths = data;$
$scope.auth = $rootScope.auth;
var id = {'id': data['_id']};
auth=angularFireAuth.login(data['access_token'],id);
$scope.auth = auth;
}, function error(err) {
console.log('error', err);
});
** Note: data['_id'] = string id that is the userid in my firebase and used as auth.id in my security rules
data['access_token'] = string token. this is not a dictionary or object. just the string token returned from: token = create_token(SECRET, custom_data, options). Which runs successfully on my python tornado server using the: firebase_token_generator module.

Ok. I figured it out. The error I was receiving because the login request is asynchronous. So the "Reference Error: auth" was because the variable auth was referenced before assigned.
I did not ultimately use this exact code above. So I do not know if it was/would work. Instead I switched to the construct that is on the firebase site:
fbLoginService.getFirebaseToken(function success(data) {
var dataRef = new Firebase('xxxxxx.firebaseio.com')
dataRef.auth(data['firebase']['access_token'], function(error) {
if(error) {
console.log("Login Failed!", error);
alert("Login Failure. Unable to login to database(firebase)");
} else {
console.log("Firebase Login Succeeded!");
$rootScope.firebaseAuth=true;
}
});
}, function error(err) {
console.log('error', err);
alert('error', err);
});
I have now created a loginController and loginService that I fire on initial load of index.html with the inclusion of the ng-controller="fbLoginController". All looks good so far.

Related

Getting response code 401 causes skipping code blocks

I'm writing an ionic v1/express/mongo/node app. When checking if the user is authenticated i have the following piece of code:
checkAuthentication: function(token) {
console.log(token);
return $http.get("http://validUrl/test", {
headers: {
'testingAuth': token
}
}).then(function(result) {
return result.data;
});
}
and am calling it like this:
checkAuthentication(token).then(function(response) {
console.log("testing response: " + response);
// if a valid token is already in storage = response contains "Success"(?), just $state.go to main page, else call the login() function
if (response.content === "Success") {
// $state.go main page
} else {
console.log("could not log in");
}
})
The problem is, when I get back code 401 from the server, I somehow skip the then block in the checkAuthentication function. Execution doesn't stop at a breakpoint at "return result.data", or "console.log("could not log").
Am I doing something obviously wrong? Is there something i need to do to force going into that block? Thanks for any advice.
The issue is with your error handling ! I took the liberty to modify your code and the way to do a $http call. Here is the working plunker for the same.
If you observe the $scope.login() function I've injected the service object and invoked the checkAuthentication() function which does the HTTP call.As you are using .then for http calls, angular provides provision to use two functions for success and error callbacks where your HTTP errors go when HTTP calls fail.
Here is the angular doc for the same.
In your example you don't have error callback method hence it doesn't go into your if else conditions.
var app = angular.module("App", []);
app.controller('AppCtrl', ['$rootScope', '$scope', '$http', 'Service', function($rootScope, $scope, $http, Service) {
$scope.login = function(token) {
//call the injected service in the function for HTTP call..
Service.checkAuthentication(token).then(function(response) {
console.log("testing response: " + response);
// if a valid token is already in storage = response contains "Success"(?), just $state.go to main page, else call the login() function
if (response.content === "Success") {
// $state.go main page
}
},function(error){
console.log(error);
console.log("could not log in due to error...");
});
};
}]);
//use angular services to do a http call for better code maintainability...
app.service('Service', ['$http', '$rootScope', function($http, $rootScope) {
return {
checkAuthentication: function(token) {
return $http.get("http://validUrl/test", {
headers: {
'testingAuth': token
}
});
}
};
}]);

On Auth State changed AngularFire

Trying to authenticate an user using firebase. Started my app using firebase 2.xx but even after upgrading to Firebase 3.xx, throwing
error "onAuthStateChanged is not a function".
This is how my login function looks like-
.controller('HomeCtrl', ['$scope','$location','CommonProp','$firebaseAuth', '$firebaseObject',function($scope,$location,CommonProp,$firebaseAuth,$firebaseObject) {
var firebaseObj = $firebaseObject(rootRef);
var loginObj = $firebaseAuth(firebaseObj);
$scope.SignIn = function($scope, user) {
event.preventDefault(); // To prevent form refresh
var username = user.email;
var password = user.password;
loginObj.$signInWithEmailAndPassword({
email: username,
password: password
})
.then(function(user) {
// Success callback
console.log('Authentication successful');
$location.path("/welcome");
CommonProp.setUser(user.password.email);
}, function(error) {
// Failure callback
console.log(error);
});
}
}]);
Your problem is that you are passing a $firebaseObject to $firebaseAuth().
So make sure you are initializing your [$firebaseAuth][1] object like the following and then your code should work properly.
var loginObj = $firebaseAuth();
Working jsFiddle for demonstrating.
You can check here the documentation for AngularFire2

Firebase V3 and Social Login with Ionic

I am just trying to create a simple social login (e.g.: google, Facebook,...) inside a Ionic App and using Firebase V3 as backend. Unfortunately all the example and tutorial that I found on the internet seems to be broken and do not work with the new API v3.
For example I tried to follow this tutorial (https://firebase.googleblog.com/2016/01/social-login-with-ionic_77.html?showComment=1465144743780#c7688518627861813273)
but apparently I am not able to access the global variable Firebase that was previously available and therefore from this snippet of my app.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services', 'firebase'])
.constant('FirebaseUrl', 'https://ionicle.firebaseio.com/')
.service('rootRef', ['FirebaseUrl', Firebase])
I get the following error
ReferenceError: Can't find variable: Firebase, http://localhost:8103/js/app.js, Line: 12
facebookAuth: function () {
ngFB.login({ scope: 'email' }).then(
function (response) {
if (response.status === 'connected') {
console.log('Facebook login succeeded', response);
var credential = firebase.auth.FacebookAuthProvider.credential(
response.authResponse.accessToken);
firebase.auth().signInWithCredential(credential).catch(function (error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
} else {
alert('Facebook login failed');
}
});
},
more details here: http://www.clearlyinnovative.com/firebase-3-0-ionic-facebook-login

Firebase Angular OAuth with Google email scope, auth.$authWithOAuthPopup vs ref.authWithOAuthPopup

I'm successfully using Firebase's angular library to auth users against Facebook and Google, but I'm having troubling retrieving the user's email when using firebaseAuth's $authWithOAuthPopup.
Here's my login function.
var ref = new Firebase(FIREBASE_URL);
var auth = $firebaseAuth(ref);
loginGoogle: function () {
console.log('Logging in Google.');
return auth.$authWithOAuthPopup('google', function(error, user){
//TODO: Handle Failed login better
console.log('Google login failed');
console.log(error);
},{
scope: 'email'
});
};
This will pop up the google auth window and log in successfully. But, in the access permissions window, it doesn't request the 'email' scope access.
If I use ref.authWinOAuthPopup(...) instead of auth.$authWithOAithPopup(...) it does properly request the email perms, and delivers that info after auth.
Am I doing something wrong here? Or, is it an Angularfire bug that I should be reporting?
Angularfire v0.9.2.
After digging in further I found that the $firebaseAuth.$authWithOAuthPopup takes only two arguments (provider and options), whereas the Firebase.authWithOAuthPopup takes three (provider, onComplete callback, options). So, using refactoring to use the returned promise instead of passing in a callback function fixed the issue.
To be more clear, I'd like to add my snippets to show how to pass the e-mail scope to google oAuth.
As you mentioned, if you're using the promise to do the authentication instead of the callback you can pass the option for the email scope to the auth. call as second parameter and then the e-mail address will be available in the payload.
Please have a look at the following snippet:
$scope.loginGoogle = function() {
Auth.$authWithOAuthPopup("google", {scope: ['email']}).then(function(authData) {
// handle authData in onAuth handler in app.js in run method with Auth.$onAuth(function(authData) { ... });
console.log("Authenticated successfully with payload:", authData);
$location.path(REDIRECT_ROUTE);
})
.catch(function(err) {
$scope.err = errMessage(err);
});
};
function errMessage(err) {
var msg = "";
//return angular.isObject(err) && err.code? err.code : err + '';
switch (err.code) {
case "INVALID_EMAIL":
case "INVALID_PASSWORD":
case "INVALID_USER":
console.log("The specified user account email is invalid.");
msg = "E-mail or password is invalid.";
break;
/*
case "INVALID_PASSWORD":
console.log("The specified user account password is incorrect.");
break;
case "INVALID_USER":
console.log("The specified user account does not exist.");
break;
default:
// password or email empty;
console.log("Error logging user in:", err);*/
};
return msg;
}
angular.module('firebase.auth', ['firebase', 'firebase.utils'])
.factory('Auth', ['$firebaseAuth', 'fbutil', function($firebaseAuth, fbutil) {
return $firebaseAuth(fbutil.ref());
}]);
This is what I did and it worked for me
.config(function ($firebaseRefProvider) {
$firebaseRefProvider.registerUrl('https://****.firebaseio.com/');
})
Then in controller
loginWithGoogle: function(){
var ref = $firebaseRef.default;
ref.authWithOAuthPopup("google", function(error, authData) {
if (error) {
...
} else {
console.log(authData.google.email);
}
},{scope: 'email'});
}

Set RestAngular default request parameters after login

I'm hitting an API which requires all authenticated actions to include an auth token in the request, however, I do not have the auth token until I login.
I've only seen examples of setting default request parameters in Restangular in app.config.
Is it possible to set this until after the user has logged in and User.auth_token is set?
So basically instead of:
app.config(function(RestangularProvider) {
RestangularProvider.setDefaultRequestParams({
auth_token: 'thisistheauthenticationtoken'
});
});
I need:
app.config(function(RestangularProvider) {
RestangularProvider.setDefaultRequestParams({
auth_token: User.auth_token
});
});
Why would you set token as part of the response versus in the header? Like so.
Restangular.setDefaultHeaders({ authentication: 'bearer ' + token.authentication });
I know this is an old thread but this SO question kept appearing when I was Googling (yes, I just used Google as a verb... deal with it :P) for a resolution, so I thought I should provide my solution. Hopefully it will help the OP or anyone else that may come across this page.
angular.module("app").factory("UserService", [
"$rootScope",
"$state",
"$q",
"Restangular",
function ($rootScope, $state, $q, Restangular) {
var UserSvc = {};
var Identity;
/*
This creates a scoped copy of Restangular
Normally this is where you would use setDefaultRequestParams,
but it would only affect this scope and not ALL API requests in your app
*/
var UsersAPI = Restangular.withConfig(function (RestangularConfigurer) {
RestangularConfigurer.setBaseUrl("api/1.0/users");
});
UserSvc.login = function (credentials) {
var $defer = $q.defer();
UsersAPI.all("start-session").post(credentials).then(function(respData){
if (respData.apikey) {
Identity = respData.plain();
/*
User is authenticated and API key is obtained from server response
Note how I do NOT use the setDefaultRequestParams function:
If we do the withConfig/setDefaultRequestParams, it only affects local scope, not global
This method modifies the ROOT Restangular object and
will then propegate through all future use of Restangular in your app
*/
Restangular.configuration.defaultRequestParams.common.apikey = Identity.apikey;
if ($rootScope.toState && $rootScope.toState.name != "login") {
$state.go($rootScope.toState.name, $rootScope.toStateParams || {});
} else {
$state.go("app.dashboard");
}
$defer.resolve(Identity);
}
else {
Identity = undefined;
$defer.reject(Identity);
}
},function (respData) {
$defer.reject(respData);
});
return $defer.promise;
};
return UserSvc;
}
]);
In my case, I use
Restangular.setDefaultRequestParams({token: localstorage.get('token')});
This works with me. Please have a look my snippet here.
https://github.com/fugokidi/ng-snippets/blob/master/rest.js
If you want to do something like this, you need to remove your code from app.cofig and move to when you find user is logged in.
You can set defaultRestParams for restangular at any point of application using Restangular service.
For more info refer https://github.com/mgonto/restangular#setdefaultrequestparams.
A more Angular-ish example from a project that I've been working on:
angular.module('app', [ 'restangular' ])
.factory('API', function(Restangular){
return Restangular.withConfig(function(config){
config
.setBaseUrl('https://api.example.com')
// etc etc etc
; // END config
});
})
.factory('Auth', function(API){
return {
login: function(credentials){
// Assuming I just POST /session/new to get an OAuth token,
// which is totally not a thing that OAuth should do.
API.one('session').post('new', credentials)
.then(function(auth){ // Assuming `auth = { access_token: '...' }`
API.setDefaultHeaders({
Authorization: 'bearer ' + auth.access_token
// Assuming OAuth Bearer Token
});
})
},
logout: function(){ /* . . . */ }
};
})
.controller('MainController', function(API, Auth){
var self = this;
self.user = { };
this.login = function(credentials){
Auth.login(credentials).then(function(){
self.user = API.one('user').$object;
});
});
})
; // END module(app)
The following code will read the token from storage for every request.
app.config(function(RestangularProvider) {
//Injext $cookies manually (there might be better ways to do this)
var $cookies;
angular.injector(['ngCookies']).invoke(['$cookies', function(_$cookies_) {
$cookies = _$cookies_;
}]);
RestangularProvider.setDefaultHeaders({
Authorization: function() {
return $cookies.get('token');
}
});
});
I too struggled with this.
Instead of using
RestangularProvider.setDefaultRequestParams({
auth_token: 'thisistheauthenticationtoken'
});
try using
Restangular.setDefaultRequestParams({auth_token:'thisistheauthenticationtoken'});

Resources