Node JS - Listen to External IP Address
Good to know !
The SOOMLA Blog: Amazon's Global Coin - Smart Move or Doomed to Fail
Amazon recently announced the launch of a global coin allowing game developers for the kindle fire to recognize it as a form of payment for in app purchases. This is not a new idea, far from it. One might remember that Facebook discontinued a similar service by the name of Facebook credits or…
android tip #2: @JavascriptInterface
If your targetSdkVersion (in AndroidManifest.xml) is 17 and you’re adding a Javascript interface to a Webview than you’ll have to add the annotation @JavascriptInterface above every JS interface function (all functions must also be public).
@JavascriptInterface
public void getDeviceId() {
return "blabla";
}
(taken from http://developer.android.com/guide/webapps/webview.html)
android tip: allow cross-origin for local files
If you’re on JellyBean and you get this error: ‘Origin null is not allowed by Access-Control-Allow-Origin’ when trying to navigate to a local file when inside a Webview, just add the following:
if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
}
Great project for publish-subscribe in Android
I found Square’s otto while looking for a way to implement the publish-subscribe pattern in an Android application.
This great project has exactly what you need to have a notification center (like ios’s NSNotificationCenter) in Android.
ios tip: Screen Rotation ios5 vs ios6
Just a small tip for ios devs:
Rotating a UIViewController is done differently in ios5 and ios6. Just copy the relevant code below into your UIViewController. You can copy both code blocks if you want to support both io5 and ios6.
ios5:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
if ([[StorefrontInfo getInstance] orientationLandscape]){
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
ios6:
- (BOOL)shouldAutorotate
{
//returns true if want to allow orientation change
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
if ([[StorefrontInfo getInstance] orientationLandscape]){
return UIInterfaceOrientationMaskLandscape;
}
return UIInterfaceOrientationMaskPortrait;
}
Rails with AJAX Facebook Connect
Just implemented an option to connect to our Designer using Facebook and i wanted to share. It’s actually quite easy when you get the hang of it.
My requirements:
- Let users connect with their Facebook account (duh!).
- The login process must be done with AJAX and not like the regular process where you get redirected to facebook and back to the home page when the login process finishes.
Lets get right to work:
Integrating Facebook into your Rails application
Everyone knows about the AMAZING authentication plugin devise. This entire tutorial is based on The ‘devise’ team’s GREAT tutorial that explains how to integrate Facebook into your Rails application. Go over the tutorial and make sure it works. Things i did different:
- I’m using MongoDB (with Mongoid) so instead of creating a migration to the User table i just added ‘provider’ and ‘uid’ straight to the User model.
- In the function ‘find_for_facebook_oauth’ (in the User model) i added code that checks if the user that just connected with his Facebook account already registered with us (by the user’s email). This is my code:
def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
user = User.where(provider: auth.provider, uid: auth.uid).first
unless user
# checking if the email from facebook already exists for one of the users
user = User.where(email: auth.info.email).first
if user
user.provider = auth.provider
user.uid = auth.uid
user.save!
else
user = User.create(name:auth.extra.raw_info.name,
provider:auth.provider,
uid:auth.uid,
email:auth.info.email,
password:Devise.friendly_token[0,20]
)
end
end
user
end
Supporting AJAX
We want to respond to the Facebook-Connect login process with a JSON format response. You’ll see in the next step below that you’ll handle this response and use it to change stuff on the screen.
(look in the code below for [PUT YOUR POST-LOGIN CODE HERE]).
To change the response to a JSON response, go to ‘OmniauthCallbacksController’ and make it look like this:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
@user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
if @user.persisted?
sign_in(@user)
render :status => 200, :json => { :user => { :email => @user.email, :name => @user.name } }
else
render :status => 401, :json => { :errors => alert }
end
end
end
Adding Facebook javascript SDK
If we don’t want to navigate out of the page in order to connect with Facebook and we want to get the Facebook-Connect callback into our Rails application, we have to take the default code from Facebook javascript SDK and change it a bit. This is what you need to add to your application.html.erb:
<!-- Facebook connect script -->
<div id="fb-root"></div>
<script type="text/javascript">
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : '[YOUR APP ID HERE]', // App ID from the App Dashboard
channelUrl : '//[YOUR DOMAIN HERE]/channel.html', // Channel File for x-domain communication
status : true, // check the login status upon init?
cookie : true, // set sessions cookies to allow your server to access the session?
xfbml : true // parse XFBML tags on this page?
});
// Additional initialization code such as adding Event Listeners goes here
};
(function(d, debug){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all" + (debug ? "/debug" : "") + ".js";
ref.parentNode.insertBefore(js, ref);
}(document, /*debug*/ false));
$(function() {
$('#facebook-connect').click(function(e) {
e.preventDefault();
FB.login(function(response) {
if (response.authResponse) {
// since we have cookies enabled, this request will allow omniauth to parse
// out the auth code from the signed request in the fbsr_XXX cookie
$.getJSON('<%=user_omniauth_callback_path(:facebook)%>', function(data) {
// 'data' contains a 'user' object with 'email' and 'name' in it.
[PUT YOUR POST-LOGIN CODE HERE]
});
}
}, { scope: '[ADD THE SCOPE YOU WANT HERE]' });
});
});
</script>
<!-- end Facebook connect script -->
- channelUrl is just for cross domain issues on some browsers. Add a file called ‘channel.html’ to your public folder and in it put this one line:
<script src="//connect.facebook.net/en_US/all.js"></script> - You can see that i put the Facebook-Connect login process to a button with id ‘facebook-connect’. Make sure you have it in your code.
That’s it! You got Facebook Connect working with AJAX in your Rails application
IMPORTANT: omniauth-facebook has an issue with CSRF in version 1.4.1 so use 1.4 until they’ll fix it. (thanks Alex Dolgov)
Multiple token authentication with Devise & redis


I’ve been developing on Rails for quite some time now and i continue to realize the power and benefits this framework gives you. In Rails, when you want to get a new capability into your application, you first try to find something OOTB. The best gem for the job is usually the one that gives you everything you want in one place. The variety and maturity of community plugins provide Rails developers with the ability to easily create rich web applications. But what happens when you find a plugin that gives you 95% of what you want and you need to add the 5% yourself ?
I found Devise to be that plugin. This great plugin gave me everything i needed in order to authenticate users in my application except one feature.
Using Rails, i have developed an api and i was looking for a way to authenticate users in different clients simultaneously and let every client work dependently of the others. Devise only gives you 2 forms of authentication: database (using cookies) and token based authentication. I wanted to use the database authentication for users who login with email and password and the token authentication for those who wanna use the api from mobile devices and other applications and want to just login with a token.
Database authentication using Devise was pretty easy. With the tokens i had 2 requirements:
- The token had to be regenerated on every login (for security reasons).
- Logging out of the api had to revoke the token.
The problem i had was that logging in from 2 devices simultaneously was impossible because (the numbers correlate to the requirements numbers above):
- One client login always revokes the token for the other.
- Logging out from one client revokes the token for the other.
I figured i had to generate a token for each user+client. That token will “live” for as long as the user is logged in on a specific client. In order to accomplish that and still use Devise i had to expand its capabilities to support my multiple tokens philosophy. I also selected redis as my storage for the tokens (I won’t get down to details on “why redis” in this post)
So lets go down to the code:
First, i had to create a class that handles the interaction with redis. I created a file under “lib” and called it authentication_tokens.rb. In my implementation, every token is added to redis with the prefix “auth_token:”. You can also notice that i’ve put a 24.hours expiration time for a token (24 hours of no activity with the token).
class AuthenticationTokens
include Singleton
def initialize
@redis ||= Redis.new(:host => "localhost")
end
def AuthenticationTokens.finalize(id)
@redis.quit
end
# generate authentication token using the given email and save it in redis
# the generated token will have a field "user_id" in order to identify the associated user later
def generate(email, user_id)
token = Utils::gen_token(email)
key_s = token_key token
@redis[key_s] = user_id
@redis.expire key_s, 24.hours
token
end
# renewing expiration timeout
def touch(token)
@redis.expire token_key(token), 24.hours
end
# deletes the token
def revoke(token)
@redis.del token_key(token)
end
def token_val(token)
@redis.expire token_key(token), 24.hours
@redis[token_key(token)]
end
private
def token_key(token)
"auth_token:#{token}"
end
end
I also created a Devise strategy to handle my multiple tokens authentication logic inside devise. The strategy is kept in multiple_tokens_strategy.rb under “config/initializers”. The strategy uses the previously created class in order to check with redis if the token exists.
module Devise
module Strategies
class MultipleTokensStrategy < Devise::Strategies::Base
def valid?
params[:auth_token]
end
def authenticate!
user_id_str = AuthenticationTokens.instance.token_val(params[:auth_token])
if user_id_str
user = User.find(user_id_str.to_i)
if user
user.after_database_authentication
success!(user)
end
end
if (!(params[:user]) && !halted?)
fail!("Invalid authentication token.")
end
end
end
end
end
The newly created strategy needs to be added to the initializer “devise.rb”
Devise.setup do |config|
...
config.warden do |manager|
manager.strategies.add(:multiple_tokens_strategy, Devise::Strategies::MultipleTokensStrategy)
manager.default_strategies(:scope => :user).unshift :multiple_tokens_strategy
end
end
After creating the strategy and registering it with Devise we just need to generate the token when the user logs into the system (through the api or regular signin). In order to do that we’ll have to override Devise’s SessionsController as explained in many places on the web (for example: http://stackoverflow.com/questions/8070320/rails-3-override-devise-sessions-controller). After overriding Devise’s SessionsController, i overridden 3 actions: “create” & “require_no_authentication” & “destroy”. I copied Devise’s original code and added my functionality inside. Inside the code you’ll see comments with what i did exactly:
class SessionsController resource_name,
:recall => ("#{controller_path}#new" : "sessions#authentication_failure_json"))
# This code is copied from Devise
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource)
# if the winning strategy is MultipleTokensStrategy than don't replace
# auth_token, otherwise generate a token for the user.
if warden.winning_strategy.class != Devise::Strategies::MultipleTokensStrategy
auth_token = AuthenticationTokens.instance.generate resource.email, resource.id
else
# we assume that params[:auth_token] exists b/c winning strategy is MultipleTokensStrategy
auth_token = params[:auth_token]
end
# keep the token in the session for future reference
session[:auth_token] = auth_token
# Here i respond to different formats.
respond_to do |format|
format.html { redirect_to root_path }
format.json { render :json => resource }
end
end
# This action is called to check if an authentication is actually needed.
def require_no_authentication
# This code is copied from Devise
no_input = devise_mapping.no_input_strategies
args = no_input.dup.push :scope => resource_name
if no_input.present? && warden.authenticate?(*args)
resource = warden.user(resource_name)
flash[:alert] = I18n.t("devise.failure.already_authenticated")
# My code here
# We generate a new token even if no authentication is required b/c we don't
# know what token to return if the user is logged in already and asks to
# login again ONLY with user and password than (in my implementation) he
# actually "asks" for a new token.
# If the user is logged in already and asks to login again with
# a valid auth_token than that token is returned.
auth_token = params[:auth_token] || session[:auth_token] || AuthenticationTokens.instance.generate(resource.email, resource.id)
session[:auth_token] = auth_token
# Here i respond to different formats.
respond_to do |format|
format.html { redirect_to after_sign_in_path_for(resource) }
format.json { render :json => resource }
end
end
end
# This action is called on logout.
def destroy
# My code here.
# I look for the user with the given token. If he exists than he gets logged
# out, if not than the current_user is logged out.
auth_token = params[:auth_token]
if auth_token
user_id_str = AuthenticationTokens.instance.token_val(auth_token)
if user_id_str.blank?
if current_user
@user = current_user
else
respond_to do |format|
format.html { redirect_to root_path }
format.json { render :json => {:errors => "Already logged out!"} }
end
return
end
else
@user = User.find(user_id_str.to_i)
AuthenticationTokens.instance.revoke auth_token
session[:auth_token] = nil
end
else
@user = current_user
end
# This code is copied from Devise
sign_out(@user)
# Here i respond to different formats.
respond_to do |format|
format.html { redirect_to root_path }
format.json {
render :status => 200, :json => { :email => @user.email } }
end
end
# This function supports returning error message on failure to authenticate.
def authentication_failure_json
return render :json => { :errors => alert }
end
end
That’s it! Quite an effort to get it done but with that you’ll have the ability to connect with multiple clients to your rails application without then interfering each other.
