////
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
////

The tokens are stored on the server using a `tokenStorageService` bean. The plugin comes with out-of-the-box support
for JWT, Memcached, GORM and http://grails.org/plugin/cache[Grails Cache], but you can use your own strategy implementing the
include::{baseGroovyApiUrl}grails/plugin/springsecurity/rest/token/storage/TokenStorageService.html[TokenStorageService]
interface.

[NOTE]
====
The default implementation, JWT, is stateless. Nothing is really stored. However, the plugin still gives a
chance to the other implementations to store the principal if they need to.
====

=== JSON Web Token

JSON Web Token (JWT) is an https://tools.ietf.org/html/rfc7519[IETF standard] which defines a secure way to encapsulate arbitrary data that can be sent over unsecure URL's.

Generally speaking, JWT's can be useful in the following use cases:

* When generating "one click" action emails, like "delete this comment" or "add this to favorites". Instead of giving 
  the users URL's like `/comment/delete/123`, you can give them something like `/comment/delete/<JWT_TOKEN>`, where the 
  `JWT_TOKEN` contains encapsulated information about the user and the comment, in a safe way, so authentication is not required.
  
* To achieve single sign-on, by sharing a JWT across applications.

In the context of authentication and authorization, JWT will help you implement a stateless implementation, as the
principal information is stored directly in the JWT.

==== How does a JWT looks like?

.JWT example
image::images/jwt.png[]

===== Header

A base64-encoded JSON like:

[source,javascript]
.Listing {counter:listing}. JWT header
----
{
    "alg": "HS256",
    "typ": "JWT"
}
----

===== Claims

A base64-encoded JSON like:

[source,javascript]
.Listing {counter:listing}. JWT claims
----
{
    "exp": 1422990129,
    "sub": "jimi",
    "roles": [
        "ROLE_ADMIN",
        "ROLE_USER"
    ],
    "iat": 1422986529
}
----

===== Signature

Depends on the algorithm specified on the header, it can be a digital signature of the base64-encoded header and claims,
or an encryption of them using RSA.

==== Signed JWT's

By default, this plugin uses signed JWT's as specified by the
https://tools.ietf.org/html/draft-ietf-jose-json-web-signature[JSON Web Signature] specification. More specifically,
the algorithm used is HMAC SHA-256 with a specified shared secret. The relevant configuration properties are:

.JWT configuration options for signing
[cols="80,20"]
|===
|*Config key*   |*Default value*

|`grails.plugin.springsecurity.rest.token.storage.jwt.useSignedJwt`
|`true`

|`grails.plugin.springsecurity.rest.token.storage.jwt.secret`
|`null` //Needs to be set or the app won't boot

|`grails.plugin.springsecurity.rest.token.storage.jwt.expiration`
|`3600`

|`grails.plugin.springsecurity.rest.token.storage.jwt.refreshExpiration`
|`(No Expiration)`
|===

==== Encrypted JWT's

[NOTE]
====
Grails's `grails-docs` artifact includes a version of `com.lowagie:itext` which in turns bring old BouncyCastle's libraries
into the classpath. To avoid the problem, you have to override explicitly that dependency:

[source,groovy]
.Listing {counter:listing}. Excluding BouncyCastle's libraries
----
build("com.lowagie:itext:2.0.8") { excludes "bouncycastle:bcprov-jdk14:138", "org.bouncycastle:bcprov-jdk14:1.38" }
{code}
----
====

In the previous strategy, the claims are just signed, so it prevents an attacker to tamper its contents to introduce
malicious data or try a privilege escalation by adding more roles. However, the claims can be decoded just by using
Base 64.

If the claims contains sensitive information, you can use a
https://tools.ietf.org/html/draft-ietf-jose-json-web-encryption[JSON Web Encryption] algorithm to prevent them to be decoded.
Particularly, this plugin uses RSAES OAEP for key encryption and AES GCM (Galois/Counter Mode) algorithm with a 256 bit key
for content encryption.

By default, RSA public/private keys are generated every time the application runs. This means that  generated tokens
won't be decrypted across executions of the application. So better create your own key pair using OpenSSL:

[source,bash]
.Listing {counter:listing}. Certificate generation for JWT
----
openssl genrsa -out private_key.pem 2048
openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
----

Then, configure the keys properly, along with the rest of the configuration:

.JWT configuration options for signing
[cols="80,20"]
|===
|*Config key*   |*Default value*

|`grails.plugin.springsecurity.rest.token.storage.jwt.useEncryptedJwt`
|`false`


|`grails.plugin.springsecurity.rest.token.storage.jwt.privateKeyPath`
|`null`


|`grails.plugin.springsecurity.rest.token.storage.jwt.publicKeyPath`
|`null`
|===


Example configuration:

[source,groovy]
.Listing {counter:listing}. JWT encryption example configuration
----
grails.plugin.springsecurity.rest.token.storage.jwt.useEncryptedJwt = true
grails.plugin.springsecurity.rest.token.storage.jwt.privateKeyPath = '/path/to/private_key.der'
grails.plugin.springsecurity.rest.token.storage.jwt.publicKeyPath = '/path/to/public_key.der'
----

[WARNING]
====
The performance of encryption algorithms is much slower compared with signing ones. If you are considering encrypting
you JWT's, think if you really need it.
====

==== Token expiration and refresh tokens

When using JWT, issued access tokens expire after a period of time, and they are paired with refresh tokens, eg:

[source,javascript]
.Listing {counter:listing}. Sample access token response, including refresh token
----
{
   "username": "jimi",
   "roles": [
      "ROLE_ADMIN",
      "ROLE_USER"
   ],
   "expires_in": 3600,
   "token_type": "Bearer",
   "refresh_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.fUaSWIdZakFX7CyimRIPhuw0sfevgmwL2xzm5H0TuaqwKx24EafCO0TruGKG-lN-wGCITssnF2LQTqRzQGp0PoLXHfUJ0kkz5rBl6LtnRu7cdD1ZUNYXLJtFjQ3IATzoo15tPafRPyStG1Qm7-1L0VxquhrLxkkpti0F1_VTytZAq8ltFrnxM4ahJUwS7eriivvdLqmHtnwuXw0kBXEseIyCkiyKklWDJAcD_P_gHoQJvSCoXedlr7Pp0n6LEUrRWJ2Hb-Zyt9dWqWDxm9nyDeEVtEZGcQtpgCGgbXxaUpULIy5nvrbRzXSNyT6iXhK1CLqiFVkfh-Y-DHXdB6Q4sg.uYdpxl835KnlkqC5.gBgSnPWZOo6FINovJNG7Xx2RuS09QJbU4-_J4EgZQkygt8xE-HfdYaOmtmJLjGJR1XKoaRsuX1gNjFoCZgqWAon6.Zsrk52dkjskSVQLXZBQooQ",
   "access_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.n-gGe65x0SlSXS3fTG8ZLdXvv6b5_1pDvkcGyCjFy-vm1VhaBEQL5p3hc6iUcCAcuyrqzGk95lV9dHCv46cNfCiUFHWfbEcd4nqScIxBbc28xO9L1mNLnZ0G1rx1Mx1L0Y_ZPoSxDXpJaHCT28cdZffHLxx2B9ioIClgdlYBAJ5Oz8VT39-D0QSomS6QhFqmcpbDsXrsKxs545Pn-TIlu-fSQ4wpIvAxusOKB6CV2EYKqBplMBrh-3btE8WksVcX2N3LsrcMhrKxSKi93c06MZh6JzSLWe5bl9hvUvBdEuwDrk-fQgD3ZlmjjoevRWYhv_kslW1PlqUHYmKOQ7csUw.3mvvsFWikEjZzExA.YixjnnzzcPRy_uUpgPv5zqOfshv3pUwfrME0AijpsB7u9CmJe94g6f2y_3vqUps-5weKKGZyk3ZtnwEbPVAk9-HZt-Y27SbZl4JNCFEOLVsMsK8.h4j9BdFXuWKKez6xxRAwJA"
}
----

Refresh tokens never expire, by default, and can be used to obtain a new access token by sending a POST request to the
`/oauth/access_token` endpoint.

If you prefer to configure your refresh tokens to expire automatically, you can set
`grails.plugin.springsecurity.rest.token.storage.jwt.refreshExpiration` to the number of seconds before the token
is invalid. After this period, a client would be forced to present login credentials in order to obtain a new access token.

[source,javascript]
.Listing {counter:listing}. Sample HTTP request to obtain an access token
----
POST /myApp/oauth/access_token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ....
----

As you can see, is a form request with 2 parameters:

* `grant_type`: must be `refresh_token` always.
* `refresh_token`: the refresh token provided earlier.

[NOTE]
====
By default, refresh tokens never expire and must be securely stored in your client application. See
https://tools.ietf.org/html/rfc6749#section-10.4[section 10.4 of the OAuth 2.0 spec] for more information.
====

=== Memcached

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

.Memcached configuration options
[cols="80,20"]
|===
|*Config key*   |*Default value*

|`grails.plugin.springsecurity.rest.token.storage.memcached.hosts`
|`localhost:11211`

|`grails.plugin.springsecurity.rest.token.storage.memcached.username`
|`''`

|`grails.plugin.springsecurity.rest.token.storage.memcached.password`
|`''`

|`grails.plugin.springsecurity.rest.token.storage.memcached.expiration`
|`3600`
|===

For development, if you have Memcached installed locally with the default settings, it should  just work with the defaults.

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

=== GORM

To use GORM, these are the relevant configuration properties:

.GORM configuration options
[cols="80,20"]
|===
|*Config key*   |*Default value*

|`grails.plugin.springsecurity.rest.token.storage.gorm.tokenDomainClassName`
|`null`

|`grails.plugin.springsecurity.rest.token.storage.gorm.tokenValuePropertyName`
|`tokenValue`

|`grails.plugin.springsecurity.rest.token.storage.gorm.usernamePropertyName`
|`username`
|===

The relevant domain class should look something like this:

[source,groovy]
.Listing {counter:listing}. Authentication token domain class example
----
package org.example.product

class AuthenticationToken {

    String tokenValue
    String username

    static mapping = {
        version false
    }
}
----

[NOTE]
====
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.example.product.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 unnecessary 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.

[source,groovy]
----
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.

[source,groovy]
----
Date lastUpdated
Integer accessCount = 0

def afterLoad() {
  accessCount++
}
----

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

[source,groovy]
----
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:

[source,groovy]
----
class RemoveStaleTokensJob {
    static triggers = {
        cron name: 'every4hours', cronExpression: '0 0 */4 * * *'
    }

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

=== Redis

To use Redis as a token store simply you just have to enable it in you configuration by setting `useRedis` to `true`
(see table below).

You have to have the `redis` plugin installed in order to be able to use Redis as your token store. Refer to the
https://github.com/apache/grails-redis[Redis plugin documentation] for more details about how to configure it.

Configuration options for Redis:

.Redis configuration options
[cols="80,20"]
|===
|*Config key*   |*Default value*

|`grails.plugin.springsecurity.rest.token.storage.redis.expiration`
|`3600`
|===

=== Grails Cache

To use http://grails.org/plugin/cache[Grails Cache], simply define a cache name:

.Redis configuration options
[cols="80,20"]
|===
|*Config key*   |*Default value*

|`grails.plugin.springsecurity.rest.token.storage.grailsCacheName`
| `defaultTokenCache`
|===

The cache name should correspond to a name specified in the [cache DSL|http://grails-plugins.github.io/grails-cache/docs/manual/guide/usage.html#dsl].

[NOTE]
.Token expiration / eviction / TTL
====
By default, Spring Cache abstraction
http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/cache.html#cache-specific-config[does not support expiration].
It depends on the specific support of the actual providers. Grails has several plugins for this:

* http://grails-plugins.github.io/grails-cache/guide/usage.html#dsl[Core]: unsupported.
* http://grails-plugins.github.io/grails-cache-ehcache/guide/usage.html#dsl[Ehcache]: supported.
* http://grails-plugins.github.io/grails-cache-redis/guide/usage.html#dsl[Redis]: unsupported.
* http://grails.org/plugin/cache-gemfire[Gemfire]: unsupported.
====

[WARNING]
====
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 https://github.com/grails/grails-spring-security-rest/issues/89[#89] for more information.
====
