So, this is what I've been up to. I want to be able to expose my grails api using REST, but want to do it in a secure manner. The basic idea is that I can develop desktop apps, web apps, mobile apps, etc, and they all use the api from a central server to persist and get data.
For the moment, I'm using grails 1.3.7 and the Nimble plugin for authentication. Nimble is based on shiro and I really like it. Once it is installed, I had to add the following to Config.groovy:
security{
shiro{
authc.required=false
filter.config="""\
[filters]
#HTTP Basic Authentication
authcBasic = org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
authcBasic.applicationName = Rest_Auth
[urls]
/author/**=authcBasic
"""
}
}
So here we are telling grails to use the specified filter to authenticate any request made to the given url. So if a user needs to access anything under author, they need to authenticate. Now, the javadoc for BasicHttpAuthenticationFilter says the following:
Requires the requesting user to be
authenticated for the request to continue, and if they're not, requires the user to login via the HTTP Basic protocol-specific challenge. Upon successful login, they're allowed to continue on to the requested resource/url.This implementation is a 'clean room' Java implementation of Basic HTTP Authentication specification per RFC 2617.
Basic authentication functions as follows:
- A request comes in for a resource that requires authentication.
- The server replies with a 401 response status, sets the
WWW-Authenticateheader, and the contents of a page informing the user that the incoming resource requires authentication. - Upon receiving this
WWW-Authenticatechallenge from the server, the client then takes a username and a password and puts them in the following format:username:password - This token is then base 64 encoded.
- The client then sends another request for the same resource with the following header:
Authorization: Basic Base64_encoded_username_and_password
So now our grails app requires that any requests to author be authenticated. Now, in our griffon app, we installed the rest plugin: griffon install-plugin rest.
The documentation for the plugin is not all that good, or maybe I'm too dumb. So I had to figure things out on my own. I found out that it actually makes extensive use of HttpBuilder : http://groovy.codehaus.org/modules/http-builder/doc
The rest plugin creates an instance of RESTClient, which in turn inherits from HttpBuilder, and guess what? HttpBuilder has a property auth.basic .Here we can specify the username and password and HttpBuilder will send that to the grails application whenever authentication is required. Here is a sample of how it would be done with griffon:
withRest(id:'sampleId', uri: 'http://localhost:8080/myapp'){
auth.basic 'username', 'password'
def response = get(path: 'author')
//Do something with the response
}
Caution, the password is send in clear, so just make sure you use https.