Saturday, July 27, 2013

Grails easy REST Security

REST services did not came with a standard way of authentication like WS-Security for SOAP services. You can always turn to OAuth authentication which is great if you are providing services for 3rd parties that will utilize your user base and their data (e.g. Facebook or Twitter) but it is not that easy to integrate and it may come as an overhead if you are sharing your services with control set of clients (e.g. other businesses that will consume your services from their servers). 

Since we are talking here about mostly "controlled" environment then all the complexity can be avoided by simply using SSL and just sending client identification to know who is consuming your data. This is the approach that many are taking and simple adding an "apiKey" parameter at the end, e.g.


https://awesomeapi.api/hotels/?apiKey=

This is fine and will provide enough security, but if you are using simple apiKeys (e.g. like client name or some username) it can be easy to guess the api key and use your service as someone else (especially if you have your service documentation publicly). Easy solution is to use hash based apiKeys which are not guessable. More secure way is to add additional argument something like "password". This way it would be very hard to guess both parameters and breach your service. E.g. this can be easily achieved by adding spring-security-plugin, adding a special role for the API consumers and generate accounts for the clients.

This is perfectly good approach and you get all the power of spring security. However if you find spring security filters as an overhead to your API or want to separate regular users and api users this might not be great option. Another benefit is to have a clean separation of your APIKeys and keep track who is owning them. And if they become compromised add ability to generate new APIKeys for the same user account.

Grails filters make it very easy to support this. Just create a file called something like APIFilters.groovy in your grails-app/conf folder and add code like this:



class ApiFilters {

    def filters = {
        all(uri: '/**') {

            def renderError = { status, message ->               
                boolean xml = request.getHeader("accept").contains("xml")
                boolean json = request.getHeader("accept").contains("json")
                if (json || !xml) {
                    render(status: status, contentType: 'application/json', text: '{"error":"' + message + '"}')
                } else {
                    render(status: status, contentType: 'application/xml', text: '' + message + '')
                }
                return false
            }
            before = {
                try {

                    String authorizationHeader = request.getHeader('authorization')?.trim()?.toLowerCase()

                    String key

                    if (authorizationHeader == null) {
                        // Try with api_key request parameter and render error if it's missing.
                        key = params.api_key
                        if (key == null) {
                            renderError(403, 'I need an authorization parameters to serve this request.')
                            return false
                        }
                    } else {
                        try {
                            byte[] token
                            if (authorizationHeader.startsWith("apikey ")) {
                                token = authorizationHeader.substring(7).getBytes("UTF-8");
                            } 
                            key = new String(token, "UTF-8");
                        } catch (ignore) {
                        }
                        // Return if key is empty.
                        if (key == null || key.trim() == "") {
                            renderError(401, "Check your authorization header syntax. It should look like \"Authorization: APIKey [your_api_key]\".")
                            return false
                        }
                    }
                    // Find API key and return if it does not exist.
                    APIKey apiKey = APIKey.findByApiKey(key)
                    if (apiKey == null) {
                        renderError(401, 'Unknown API key.')
                        return false
                    }
                } catch (Exception e) {
                    renderError(500, 'Darn it, please try later!')
                }

            }

        }
    }
}


And create APIKey domain object to hold your API Keys. API Keys should be some randomly generated hash so they are not guessable.

And voila, you have a perfectly secured grails REST service. Rest clients just need to pass their api keys as a parameter or in the header of the request like this:


Authorization: APIKey [your_api_key]

If for some reason you want to allow http access to your API there is now a common way to solve this by signing your message based on a shared secret between the client and the service. This is called HMAC (Hash-based Message Authentication Code). This is the approach many companies have taken like Amazon and Microsoft. This approach follows the 2-legged OAuth (keep in mind that OAuth is authorization specification and not authentication). As it adds additional complexity with calculating the hash I would always recommend going SSL only and have the API access as simple as possible (developers love simple!).

Saturday, February 23, 2013

Running Servlet 3.0 applications on Heroku

Heroku comes with Jetty 7.5.4 runner which does not support servlet 3.0. However it is very easy to overcome this as Heroku lets you push your own jetty runner version easily. All you have to do is to download it to a 'server' folder in the root of your project:

mkdir server
curl http://repo1.maven.org/maven2/org/mortbay/jetty/jetty-runner/8.1.9.v20130131/jetty-runner-8.1.9.v20130131.jar > server/jetty-runner.jar

And if you like tomcat better you can do this as well. Slick!

Thursday, November 15, 2012

Native Facebook SSO in Android

Android Facebook integration

Today mobile app without easy way to get inside is considered unfriendly. Users love to share the joy of using something nice with their friends and simply love to have to remember just one password. 

Facebook is a great SSO service and it is considered a "must have" feature. 

Fortunately it is easy to integrate it. There is Android Facebook SDK created by Facebook itself, but I want to draw your attention to Android Query library. It is a great asset for Android development. It contains all the little helpers that you might need during developing your super awesome apps. And of course you want to focus on getting it awesome, so AndroidQuery is a real thing to help you out. 

Apart from other things in the package there is a SSO capatibility and Facebook authentication is really easy (either through web, or native FB app). 

The process there is straight forward, and you have demos to help as well. What is not that clear is how to generate a key hash for Facebook native android app. Here is how it looks on Facebook developer page:
facebook key hash

This field will accept multiple hashes. So, for your developer certificate use following (use the password "android"): 

keytool -exportcert -alias androiddebugkey \
-keystore ~/.android/debug.keystore | openssl sha1 -binary \
| openssl enc -a -e


And for your production builds you can generate key hash by executing following over your p12 certificate


keytool -export -alias com.yourappname -storetype pkcs12 \
-keystore cert/certificate.p12 | openssl sha1 -binary \
| openssl enc -a -e


"com.yourappname" is your keyalias. You can find out this one by executing

keytool -list -storetype pkcs12 -keystore cert/certificate.p12 -v


Happy coding!

Sunday, July 29, 2012

Using low-power servers to host php sites (e.g. Amazon Micro instance)

First answer should be DON'T or better said understand your needs and then decide.

It really falls down to what are the expectations and if the site you are planning to run is not having 10s of thousands of visits daily you can probably utilize some of the low power servers available out there. Amazon is great for starting it up since it provide you with one year free tier option. You will have to leave the credit card info with them though since they might be some other charges in the future usage and Amazon would like to be able to charge for it.

So important things:

  • Do not expect to much
  • If you can separate web server and db server (maybe 2 micro instances)
  • If you can use nginx instead of apache web server. Nginx comes with much lower memory footprint.
  • Go with some lighter site frameworks (e.g. your own or wordpress). Drupal or Typo3 will take up a lot more resources.
Here are some recommended values for apache (httpd.conf)
Timeout 30 #Set this to some reasonable amount - who waits more then 30 secs for site to load?

    StartServers          3
    MinSpareServers       2
    MaxSpareServers       1

    MaxClients            6
    MaxRequestsPerChild   500

We are not allowing many concurrent requests here but it will limit the apache memory consumption so other processes may run. If you do not have intensive operations that require a lot of memory for php processes you should put some small amount for php memory_limit in php.ini

memory_limit = 64M #maximum amount of memory one php process can consume

And if you run MySQL or similar on this server monitor it for usage. If your MySQL process gets killed (Amazon has a watchdog that will do this automatically if there is no more free memory) you may adjust the apache configuration values to even lower values.

Conclusion: if you run some small blog or personal page this configuration will run smoothly for you and will provide you with snappy performance. If you have more then 1k unique visitors a day think of something different (or pay for small ec2 instance).

Saturday, March 3, 2012

OS X Finder open in path shortcuts for various Apps (ITerm2, Sublime Text 2, Vim)


While using Finder app a lot of times I need to open a terminal in the current path. Yes you can get info of the folder you are in, select path and then launch terminal and past the path... (sloooooow) :(

Luckily I found a neat useful app to open Terminal app in finders path. Since I am ITerm fan I tried to dig out more and found a script that can launch ITerm in path as well. You can find it here.

In order to make the use of this you will need to create application with the help of Automator. Just paste it to automator, click save and voila or download the apps I already bundled.

There are couple of more apps that I like using it this way so I created few more scripts and bundled apps for it:

  • ITerm 2
  • Sublime Text 2
  • MacVim
  • Vim
And here is how to install these sweeties:

  1. Download source code from bitbucket project (or clone it)
  2. Select apps you want and move application files to your Applications folder (e.g. /Applications)
  3.  Then pick up the application icon and drag it to finders toolbar
  4. There you go.. all set up.. enjoy!
Go ahead fork me up and add apps that you like using as well.

Update 2013/03/20:
Source code along with binaries available now on github as well  

Sunday, February 26, 2012

JDK 1.7 on Mac OS X and in various IDEs

Hey JDK 1.7 is out for a while and here is how to use it in your favorite IDE.

But first you need to download JDK 1.7 OS X Preview. Follow the installation instructions and your JDD 1.7 installation should finish up in

/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/


Eclipse

  • Edit your eclipse.ini
    vim /Applications/Eclipse.app/Contents/MacOS/eclipse.ini

  • Add before first line:
    - vm
    /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/bin/java

NetBeans

  • Edit your netbeans.conf
    • "vim /Applications/NetBeans/NetBeans\ 7.1.app/Contents/Resources/NetBeans/etc/netbeans.conf"
  • Change netbeans_jdkhome to
    netbeans_jdkhome="/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home"

6/15/2012 - Update:
This worked before official 11 release. Idea changed how they handle JDKs and they are depending on Apples JDK to run.
You can use Oracles JDK 1.7 for running any projects in IDEA however, but you cannot run IDEA itself. 

IntelliJ IDEA

  • Edit your Info.plist
    vim /Applications/IntelliJ\ IDEA\ 11.app/bin/idea.sh

  • Add to the top:
    IDEA_JDK=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home

  • Save and run IDEA by
    cd /Applications/IntelliJ\ IDEA\ 11.app/
    ./bin/idea.sh


Saturday, February 11, 2012

Distributed version control is natural way of thinking

Every day I get amazed with afraid looks in developer eyes when I mention working with distributed version control systems. These systems are now very mature and present for a long time and todays developers should feel confortable trying things out.

...BUT reality is very different. Since there are not many enthusiast out there experimenting every day, being passionate about software and focusing on their work in big enterprises I get the situation. I do not think this is good.

.. Yes yes I know it is expensive for an enterprise to upgrade some technology. There are banks out there still having their system on Java 1.2 with no upgrade plan (and of course there are many exams relaying on Cobol). And ok thats fine.

...BUT again we leave in a rapid changing world. We want to be productive and more efficient every day. We want to improve. We are engineers we move forward every day.. or at least some of us do.

I want to encourage positive thinking and educate people over the things I find useful and productive. DVCS are the thing to go.

WHY?

Because DVCS implemented natural human thinking behavior. Our thought BRANCH. They branch very often, and then we return and rethink what we have done and branch to other direction, and then rethink again and again branch and then we come to conclusion. Potentially not the best one but with a big chance to be the best one simple because we have been experimenting with different paths.

That is what distributed is all about. Experiment as much as you like. Branch whenever you need, be creative, productive and efficient.

What are the causes for not accepting this not so new movement? Developers learned to think as the machines worked and now when we managed to make machines work as we think not all of us have evolved to that level.

Do you remember working with MS SourceSafe? No? Good for you. I never personally used it (when I didn't had to) but have worked on educating many developers migrate from it.

LOCKS!

Developers love locking. You lock your file and work on it. So you are the only owner of the file and no one else is not interfering your work. Great in some world, but inefficient, slow and I am not thinking of indirect impact that this revision system caused to poor development teams that were not used to playing good in teams. They all worked in their own world. Their were thought and encouraged to work like that. Thats bad..

Somehow we all managed to overcome this and got used using SVN and merging files become normal.

BUT! SVN (and similars) are central systems. Whatever you want to do to you have to do it over server. Ok it is not the problem because internet is available everywhere. But why will you share all your mindmapping and your experiments with all other developers? Ok even if you want to share it, thats fine, but that is simple bloating the repository since it will be garbage for others but for you valuable process of thinking. And this process is slow! Branching in SVN is slow, comparing changes, listing history (arrrghhh I can scream at the thought of this again) ... all of this needs to go through the central repository.

So you try to overcome all of this and think linearly and keep working with constraints that are not natural to your mind and you transfer that limitations to your code. You do not let your mind play and explore. You do not search for great solutions, but instead just go with the flow, find the shortest path. Thats bad..

And then came DVCS. This is what we needed from the start, but machines were not ready, as machines evolved and our understanding of the ways how to interact with them evolved mankind came up with a way to allow developers work as their brains work, not imposing limitations but instead encouraged experiments. Then github came and made distributed a cool thing and others followed: bitbucket, gitorius, etc.. (I am more a Mercurial guy but do not mind git.. they are both great).

BUT! Enterprises didn't follow and this is bad thing! Enterprises do not realize how much are they loosing. Productivity is suffering. Employees are limited, they are not exploring, not finding better solutions. This should change. Everybody needs to move forward. Its in the nature of mankind. And trust me Mercurial is easy to setup in the enterprise and set up all permission models very similar to SVN so just go ahead an try it.

WHY should I bother?

DVC allows you to experiment. Start working on something, realize that you might do it differently, go back couple of steps start going to different direction, realize that you have a better way, and again go back and do it. Then merge something that you liked about your other work, cherry pick some part that you liked. And then you want to share with others. Its simple, pick what you want to share, share just some branches, rebase your changes and compact them to one change set. Remove the clutter for others. Its very very very easy.

And it gets even better!

You have multiple ways of sharing. E.g. you have a central push repository but during your work you want to share some pre alpha code with your coworker thats working on other part of the functionality. There is still no need to push this code to central and you SHOULDN'T. Share it by publishing it to your friend (multiple options here: shared folder, email, web server) and work together, exchange prepare the code and then push it to central. As you see easy and not limiting at all.

I strongly believe that DVCS make better software engineers, and those that are having trouble working this way are NOT welcome to my team. Unset your limits and let your minds free!