(Quick Reference)

6 Token Storage - Reference Documentation

Authors: Alvaro Sanchez-Mariscal

Version: 1.4.1

6 Token Storage

The tokens are stored on the server using a tokenStorageService bean. The plugin comes with out-of-the-box support for Memcached, GORM and Grails Cache, but you can use your own strategy implementing the TokenStorageService interface.

6.1 Memcached

To use Memcached, simply define the following configuration properties to match your environments accordingly:

Config keyDefault value
grails.plugin.springsecurity.rest.token.storage.useMemcachedfalse
grails.plugin.springsecurity.rest.token.storage.memcached.hostslocalhost:11211
grails.plugin.springsecurity.rest.token.storage.memcached.username''
grails.plugin.springsecurity.rest.token.storage.memcached.password''
grails.plugin.springsecurity.rest.token.storage.memcached.expiration3600

For development, if you have Memcached installed locally with the default settings, just define grails.plugin.springsecurity.rest.token.storage.useMemcached = true. It should work.

In Memcached tokens will expire automatically after the configured timeout (1h by default). They get refreshed on every access

6.2 GORM

To use GORM, these are the relevant configuration properties:

Config keyDefault value
grails.plugin.springsecurity.rest.token.storage.useGormfalse
grails.plugin.springsecurity.rest.token.storage.gorm.tokenDomainClassNamenull
grails.plugin.springsecurity.rest.token.storage.gorm.tokenValuePropertyNametokenValue
grails.plugin.springsecurity.rest.token.storage.gorm.usernamePropertyNameusername

The relevant domain class should look something like this:

package org.my.path

class AuthenticationToken {

String tokenValue String username

static mapping = { version false } }

For the tokenDomainClassName configuration you must enter a fully qualified class name. In the case of the example above: grails.plugin.springsecurity.rest.token.storage.gorm.tokenDomainClassName = 'org.my.path.AuthenticationToken'

A few things to take into consideration when using GORM for token storage:

  • Instead of storing the whole UserDetails object, probably only the username is needed. This is because applications

using this strategy will probably have the standard User and Role domain classes. When the token is verified the username is passed to the default userDetailsService bean, which in the case of the default Spring Security Core GORM implementation will fetch the information from the mentioned domain classes.

  • GORM's optimistic locking feature is likely unecessary and may cause performance issues.
  • You'll have to handle token expiration by yourself via Quartz jobs or a similar mechanism. There are various ways you might

go about this.

Gorm Token Expiration Examples:

Adding a GORM autoTimestamp property like lastUpdated or dateCreated and sorting out stale or old tokens with Quartz jobs are the most obvious routes. Each has its drawbacks though.

dateCreated is useful if you want tokens to expire a set time after they are issued. However, API users who didn't pay attention to when their token was issued may find themselves needing a new token unexpectedly.

Date dateCreated

lastUpdated requires a change to the token domain instance in order to be triggered. Something as simple as an access counter may work as a strategy to keepTokens fresh, but doing a write to a disk based database on each token access may be something you would prefer to avoid for the sake of performance.

Date lastUpdated
    Integer accessCount = 0

def afterLoad() { accessCount++ }

Simply using your own date or timestamp is also a valid option.

Date refreshed = new Date()

def afterLoad() { // if being accessed and it is more than a day since last marked as refreshed // and it hasn't been wiped out by Quartz job (it exists, duh) // then refresh it if (refreshed < new Date() -1) { refreshed = new Date() it.save() } }

Here is an example quartz job to go with the custom refresh timestamp above:

class RemoveStaleTokensJob {
    static triggers = {
        cron name: 'every4hours', cronExpression: '0 0 */4 * * *'
    }

void execute() { AuthenticationToken.executeUpdate('delete AuthenticationToken a where a.refreshed < ?' [new Date()-1]) } }

6.3 Grails Cache

To use Grails Cache, simply define a cache name:

Config keyDefault value
grails.plugin.springsecurity.rest.token.storage.useGrailsCachefalse
grails.plugin.springsecurity.rest.token.storage.grailsCacheNamenull

The cache name should correspond to a name specified in the cache DSL.

Token expiration / eviction / TTL

By default, Spring Cache abstraction does not support expiration. It depends on the specific support of the actual providers. Grails has several plugins for this:

There is a bug in :cache-ehcache:1.0.0 plugin that will cause issues. It's recommended that you use the latest version. See #89 for more information.