Twitter OAuth problems with angularfire Yeoman generator - angularjs

AngularFire Yeoman generator works like a charm providing OAuth authentication for Facebook and Google, but I'm not able to get it working with Twitter :(
Login view/controller created by the generator works as follows:
Call oauthLogin('twitter') from view.
oauthLogin is just a wrapper of simpleLogin.login:
$scope.oauthLogin = function(provider) {
$scope.err = null;
simpleLogin.login(provider, {rememberMe: true}).then(redirect, showError);
};
simpleLogin.login is a wrapper of $authWithOAuthPopup:
login: function(provider, opts) {
return auth.$authWithOAuthPopup(provider, opts);
}
So, at the end of the day, it is just a call to $authWithOAuthPopup provided by firebase.js.
As I mentioned before, Facebook and Google works fine, but when I tried with Twitter, I got this error:
{"error":{"code":"ROUTE_NOT_FOUND","message":"Route not found."}}
This is because I end the OAuth process in a wrong callback URL: https://auth.firebase.com/v2/MYAPP/auth/twitter instead of https://auth.firebase.com/v2/MYAPP/auth/twitter/callback, and I don't know how to fix this.
Any hint about this callback URL issue with Twitter OAuth in AngularFire?
Thanks in advance ;)

Related

twitter login integration in reactjs

I am trying to integrate twitter login in my webapge. I am using react-twitter-auth for this.I am not understanding what I have to pass in place of loginurl and request token url. can you please let me know what I have to use in this place.
ex:
<TwitterLogin loginUrl="http://localhost:4000/api/v1/auth/twitter"
onFailure={this.onFailed}
onSuccess={this.onSuccess}
requestTokenUrl="http://localhost:4000/api/v1/auth/twitter/reverse"
showIcon={true}
customHeaders={customHeader}>
<b>Custom</b>
Twitter
<i>Login</i> content
</TwitterLogin>
You have to have a backend to validate the authentication of twitter. The following tutorial show's how the implementation is done.
Twitter Implementation
loginurl - URL that will be used to finish 3rd step of authentication process
and
request token url - URL that will be used to get request token
check this github repo -- https://github.com/alien35/social-auth-example
it helped me.

Using Firebase Auth to access the Google Calendar API

I am building a web application using AngularJS, Firebase (SDK v3) and Google Calendar API. I'm authenticating users using Google OAuth. My purpose is to be able to create calendar events from database nodes in Firebase. So far I've managed to request access to the calendar scope with:
_authProvider = new firebase.auth.GoogleAuthProvider();
// Get permission to manage Calendar
_authProvider.addScope("https://www.googleapis.com/auth/calendar");
_fbAuthObject.signInWithRedirect(_authProvider);
I'm authenticating with the redirect flow so the authentication redirect is available as:
_fbAuthObject.getRedirectResult()
.then(function _readToken(result) {
if (result.credential) {
_googleToken = result.credential.accessToken;
var authHeader = 'Bearer '+ _googleToken;
// Just a test call to the api, returns 200 OK
$http({
method: 'GET',
headers: {
'Authorization': authHeader
},
url: 'https://www.googleapis.com/calendar/v3/users/me/calendarList/primary'
})
.then(function success(response) {
console.log('Cal response', response);
},
function error(response) {
console.log('Error', response);
});
However, it seems like outside the initial login it's not possible to get the Google access token through the Firebase SDK. It seems only possible to access the Firebase JWT token, no use with the Calendar API. I could store the access token, but this wouldn't resolve the problems when refreshing the token, etc. Is there any way to get the current Google Access token with Firebase SDK and if not, what other solutions is there to the problem without having to authenticate the user twice?
UPDATE 1:
Seems like someone else has struggled with similar problems with Facebook authentication. On that question there was a link to the Firebase documentation stating that Firebase Authentication no longer persists the access token. So how can I handle token refreshes? Is there really no answer to this?
UPDATE 2:
So, I contacted Firebase Support with a feature request about this problem and they gave me the following answer:
Thanks for taking your time to write us.
I've got your point here, this is indeed a good suggestion. We're definitely aware that many users, such as yourself, would like OAuth feature that will access token upon refresh. We're exploring potential solutions, but I cannot guarantee if this will be available anytime soon. We'll keep your feedback in consideration moving forward though. Continuous improvement is very important for our community, so thanks for bringing this up!
Keep an eye out on our release notes for any further updates.
So It seems like the access tokens are not available through the Firebase SDK at the moment. I'm still trying to find a workaround, so if anyone has ideas about a valid solution I'd be glad to hear them. And of course, I'll be posting it here if I ever find a working solution myself.
I finally got around this problem by handling the authentication outside Firebase with the Google APIs JavaScript client. This solution requires including the Google auth client as documented here. Manually handling the Firebase sign-in flow is documented here.
gapi.auth2.getAuthInstance().signIn()
.then(function _firebaseSignIn(googleUser) {
var unsubscribe = firebase.auth().onAuthStateChanged(function(firebaseUser) {
unsubscribe();
// Check if we are already signed-in Firebase with the correct user.
if (!_isUserEqual(googleUser, firebaseUser)) {
// Build Firebase credential with the Google ID token.
var credential = firebase.auth.GoogleAuthProvider.credential(
googleUser.getAuthResponse().id_token);
// Sign in with credential from the Google user.
return firebase.auth().signInWithCredential(credential)
.then(function(result) {
// other stuff...
});
The _isUserEqual function:
function _isUserEqual(googleUser, firebaseUser) {
if (firebaseUser) {
var providerData = firebaseUser.providerData;
for (var i = 0; i < providerData.length; i++) {
if (providerData[i].providerId === firebase.auth.GoogleAuthProvider.PROVIDER_ID &&
providerData[i].uid === googleUser.getBasicProfile().getId()) {
// We don't need to reauth the Firebase connection.
return true;
}
}
}
return false;
}
Now I can reference the access token like this:
var user = gapi.auth2.getAuthInstance().currentUser.get();
return user.getAuthResponse().access_token;
This still isn't the ideal solution for me, but it works for now, and I'm able to authenticate to both Firebase and the Calendar API.

Firebase $onAuth has wrong authData after $authWithOAuthRedirect from Facebook

I am trying to authenticate users of my Firebase (Angularfire) app with Facebook Login.
Everything works as expected when I authenticate with a pop-up window, but to support as many browsers as possible (Chrome on iOS doesn't support pop-ups, for e.g.) I want to fallback to authenticating with a redirect ($authWithOAuthRedirect).
I have confirmed my setting in Facebook are correct (my app ID and secret, for e.g.) but when I am redirected back to my app after Facebook authenticating with a redirect, $onAuth fires but I don't have my Facebook authData.
Instead, I have anonymous authData. For a bit of background; all users are authenticated anonymously if they are not otherwise authenticated (with Facebook, in this e.g.).
I can't see to find why this would be - the user should now be authenticated with Facebook, and have the Facebook authData.
Excepts of my code are below for some context:
Triggered when a user clicks the login button
function logIn () {
firebaseAuth
.$authWithOAuthRedirect('facebook', function (error) {
if (error) {
console.log(error);
}
});
}
$onAuth (inside my Angular app's run)
function run ($rootScope, firebaseAuth, sessionStore) {
$rootScope
.$on('$routeChangeError', function (event, next, prev, error) {
if (error === 'AUTH_REQUIRED') {
console.log(error);
}
});
$rootScope
.$on('$routeChangeSuccess', function (event, current, prev) {
$rootScope.title = current.$$route.title;
});
firebaseAuth
.$onAuth(onAuth);
function onAuth (authData) {
console.log(authData);
}
}
Route resolver to otherwise anonymously authenticates users
function sessionState ($q, firebaseAuth) {
var deferred = $q.defer();
firebaseAuth
.$requireAuth()
.then(deferred.resolve, guest);
return deferred.promise;
function guest () {
firebaseAuth
.$authAnonymously()
.then(deferred.resolve, rejected);
}
function rejected () {
deferred.reject('AUTH_REQUIRED');
}
}
The route resolver (sessionState) checks to see if the user is authenticated already, and if not, tries to anonymously authenticate them.
After the Facebook authentication redirect, the user will already be authenticated, and therefore does not need to be anonymously authenticated.
But, it appears that they are? As $onAuth logs the authData to the console, and it is anonymous.
Any help with this would be much appreciated! I am sure it has something to do with my route resolver, as pop-up authentication works fine (the route is already resolved).
EDIT: I tried completely removing my route resolver in case it was that causing an issue, but it made no difference. The user was just 'unauthenticated' instead of being either authenticated with Facebook (after $authWithOAuthRedirect) or anonymously.
UPDATE: I tried authenticating with Twitter and the redirect transport and I have encountered the exact same problem. I have also tried using port 80, instead of port 3000 that my app was being served on locally, but no joy.
UPDATE: When I turn off html5Mode mode in my app - and routes now begin with #s - $authWithOAuthRedirect works perfectly. From this I can only assume that $authWithOAuthRedirect does not support AngularJS's html5Mode. Can anyone confirm this is an issue, or do I need to change my code to support html5Mode and authWithOAuthRedirect?
EXAMPLE REPO Here is an example repo demonstrating the problem: https://github.com/jonathonoates/myapp
Look in the dist directory - you should be able to download this and run the app to reproduce the problem. In scripts/main.js is the app's JS; I've added a couple of comments but it's pretty self explanatory.
To reproduce the problem: click on the 'Facebook Login' button, and you'll be redirected to Facebook to authenticate. FB will redirect you back to the app, but here lies the problem - you won't be authenticated, and the returned authData will be null - you'll see this in the console
UPDATE: When I add a hashPrefix in html5Mode e.g.
$locationProvider
.html5Mode(true)
.hashPrefix('!');
The app works as I would expect - authenticating with Facebook and the redirect transport works.
Couple of niggles though:
The URL has #%3F appended to it, and is available/visible in the browser's history.
This would rewrite URLs with #! in browsers that do not support History.pushState (html5Mode), and some less advanced search engines might look for a HTML fragment because of the 'hashbang'.
I'll look into highjacking the URL upon being redirected back from Facebook instead of using hashPrefix. In the URL there is a __firebase_request_key which may be significant e.g.
http://localhost:3000/#%3F&__firebase_request_key=
It looks like this is indeed an incompatibility between Firebase and AngularJS's html5mode as you suspected. At the end of the redirect flow, Firebase was leaving the URL as "http://.../#?", and Angular apparently doesn't like that so it did a redirect to "http://.../" This redirect interrupts Firebase (the page reloads while we're trying to auth against the backend) and so it is unable to complete the authentication process.
I've made an experimental fix that ensures we revert the URL to http://.../#" at the end of the redirect flow, which Angular is happy with, thus preventing the problematic redirect. You can grab it here if you like: https://mike-shared.firebaseapp.com/firebase.js
I'll make sure this fix gets into the next version of the JS client. You can keep an eye on our changelog to see when it is released.

Which is the right method to handle oauth2.0 done in server using Ionic framework?

I am creating an Ionic app which has multiple 3rd party integration. I already have a java server which does the oauth2 authentication for the 3rd parties and redirect to the callback url in the server itself.
Now my task is to open back the app page after the server callback url is done.
I have tried the following method:
monitoring the url changes in app using ionic and redirect after the successful callback.
Which is the best way to handle this sitn.
Thanks.
Frankly, I haven't done anything like this. But to my mind, you can check ngcordova oauth implementation for ideas.
var browserRef = window.open(your_url);
browserRef.addEventListener("loadstart", function(event) {
//your code
});
browserRef.addEventListener('exit', function(event) {
deferred.reject("The sign in flow was canceled");
});
Check oauth.js source for more details.
Moreover, you can find the sample of using this implementation on this page.
http://mcgivery.com/using-custom-url-schemes-ionic-framework-app/
Above link may help you. If I am thinking correctly what you want?

Ionic Framework Twitter integration

I am presently working on a Project in which I have to use Ionic Framework for twitter integration.
I was using a sample program from ionic forum: http://forum.ionicframework.com/t/twitter-integration-with-jsoauth/3936
available at bitbucket: https://bitbucket.org/aaronksaunders/ionic.twitter.sample
I have tested it in both way i.e. with ionic serve and on the emulator, but with the same result: whenever I click on the login a new browser window with adrress: https://api.twitter.com/oauth/authorize? appears that contains the below error message.
Whoa there!
There is no request token for this page. That's the special key we need
from applications asking to use your Twitter account. Please go back to
the site or application that sent you here and try again; it was probably
just a mistake.
I have placed my twitter API Key and API Secret at proper places.
I actually like using hello.js.
It's a great library that handles your social media tokens for you.
Example Initialization:
hello.init({
facebook : '12345678912345'
}, {
// Define the OAuth2 return URL
redirect_uri : 'http://adodson.com/hello.js/redirect.html'
});
Login:
hello( "facebook" ).login().then( function(){
alert("You are signed in to Facebook");
}, function( e ){
alert("Signin error: " + e.error.message );
});
After you've logged in, you can make any call to your social media account of your choice.
You should be using ngCordova where possible.
The Oauth plugin documentation explains that you need to use jsSHA to authenticate with Twitter.
To use Twitter in your project you must have the open source library, jsSHA, included in your project. This is because Twitter requires request signing using HMAC-SHA1, not natively found in JavaScript.
Further information is available in the ngCordova Oauth plugin documentation.
Try using Cordova oAuth plugin combined with the in-app-browser plugin, as suggested by #darryn.ten. Here is an example of how to trigger a Twitter login with the oAuth plugin:
Controller
angular.module('myApp')
.controller('MyAppCtrl', ['$scope', '$cordovaOauth', function($scope, $cordovaOauth) {
$scope.twitterLogin = function() {
$cordovaOauth.twitter(<consumer key>, <secret key>).then(function(r) {
//retrieve oAuth token from result
}, function(error) {
//show error
});
}
}])
View
<a class="button button-calm" href="#" ng-click="twitterLogin()">Twitter Login</a>
See docs here.

Resources