The code to perform the login on the ChannelSet did look like this:
var token:AsyncToken = RemoteObject(service).channelSet.login(user,pwd);
token.addResponder(responder);
The above code will get the ChannelSet from the RemoteObject and calls the login() function on it to retrieve an AsyncToken. A responder is then added to the token and it is then sent off to the server.
Usually when making calls to the server, outside of login, we just make a call on the RemoteObject for a method defined by the server. If I was dealing with one of those calls I could add a new argument for the locale and be on my way, but for authentication the login function of ChannelSet is set in stone.
So after a little debugging and toying around I found that the AsyncToken contains an IMessage property, which has a headers property. On the server side I have a class which extends org.granite.spring.security.SpringSecurity3Service that handles the authentication. From inside that class I can get an instance of the HttpGraniteContext . I found the IMessage object from the AsyncToken was available inside the HttpGraniteContext . Since it is available on the server sign I simply needed to add a new property to the headers object.
So now the code looks like this:
var token:AsyncToken = RemoteObject(service).channelSet.login(user,pwd);
// Adding the locale to the CommandMessage's headers map.
token.message.headers["myLocaleKey"] = locale;
token.addResponder(responder);
On the server side the new header can be accessed like this:
HttpGraniteContext graniteContext = (HttpGraniteContext)GraniteContext.getCurrentInstance();
graniteContext.getAMFContext().getRequest().getHeader("myLocaleKey")
That's it!