Friday, July 12, 2013

Default Value for Properties in Grails Domain Classes

Grails 2.2 has a new feature that allows you to set a default value for a domain class property, as you normally would do in the database. I can't find much (any) documentation about this feature at this point other than a couple stackoverflow posts and this JIRA.

This is a really useful feature because, even though I am working with a legacy Oracle schema and have the default values specified on those tables, my integration tests use the internal h2 database with the tables generated by Hibernate from my domain classes. Without being able to specify default values in my domain classes, I am stuck always having to insert all values into my tables even if they aren't important for my integration tests.

The syntax for specifying default value is very simple and goes in the mapping block:

static mapping = {
    myField defaultValue: "'foo'"
}

Note that you need the double quotes *and* single quotes or the DDL to generate the column will not have the correct syntax. If you only specified defaultValue: 'foo' for instance, the resulting DDL would be the following:
my_field varchar(100) default foo not null

You would therefore receive this error:
hbm2ddl.SchemaUpdate  - Column "FOO" not found

By putting both double and single quotes, like defaultValue: "'foo'", you get the correct DDL:
my_field varchar(100) default 'foo' not null

For numeric values, you also need quotes around the default value or the DDL for the default value does not even get generated. For example:

static mapping = {
    myIntegerField defaultValue: "1"
}

I have several fields that are mapped to enums, and unfortunately Grails does not seem to respect the defaultValue at all for those fields, at least in the version I am using (2.2.3). But since most of my fields with default values are either Strings or numbers this feature helps quite a bit!

Thursday, June 6, 2013

Using Shibboleth Security with Grails

This post discusses setting up Grails to be able to access a user ID provided by Shibboleth via request headers. It does not cover base setup of the Spring Security plugin for Grails or of Shibboleth and Apache. I assume you have all that set up. If your Shib installation is providing data via request attributes rather than headers, you may be able to use the Shib plugin for Grails instead. (If I have some free time someday I may look into trying to modify that plugin with an option to read Shib data from headers).

Basically, you will use Spring's RequestHeaderAuthenticationFilter to get the user ID from the request headers and PreAuthenticatedAuthenticationProvider which is for use with any system where the user has already been authenticated (in this case by Shibboleth). This example also makes use of a custom MockRequestHeaderAuthenticationFilter which allows you to pass in a user ID when you're in the development environment to make testing easier.

Of course, first thing is you need to install Spring Security plugin and set its properties so it knows about your domain classes. Then, in conf/spring/resources.groovy you will need to set up a few beans:

In conf/Config.groovy, you need to let Spring Security know to use your preauthAuthenticationProvider:
grails.plugins.springsecurity.providerNames = ['preauthAuthenticationProvider']

This block in conf/BootStrap.groovy actually registers the filter for each environment. For development and test we want the mock filter and for QA and production, we use the real filter:

This is the entirety of the MockRequestHeaderAuthenticationFilter.groovy class. It just returns whatever user name you told it to in the spring bean setup above:

Wednesday, June 5, 2013

WS security with UsernameToken

I recently needed to troubleshoot a client connection to a Web service that required WS security using the UsernameToken profile with a digest password (not plain text). The easiest way to do this (I thought) would be to just write the UsernameToken headers myself. That way, I would be minimizing the number of frameworks involved and so could get to the heart of the problem easier.

After a decent amount of searching, I couldn't find a complete Java example, but was able to piece together a workable solution. I'm no security expert, just an application developer trying to troubleshoot a problem. So this definitely isn't production-ready code, but if you're in the same boat trying to troubleshoot a connection, hopefully this will be of some use to you and save you some time.

The code here is a SOAPHandler that will add the appropriate headers to your Web service call. I won't go into how to configure a handler here as that is specific to whatever development tool you are using. But once you get this handler configured correctly, it should add the headers so your SOAP message looks something like this:

The main difficulty with the implementation is the password digest. From the spec:

Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )

In other words, you must concatenate the bytes or a nonce, a created date, and the password; then SHA-1 digest the result; then Base64 encode the digest. Here is the code: