Product SiteDocumentation Site

12.3.5. Token Authentication

This authentication scheme allows you to authenticate your users based on a token. A token is usually a string representing a set of claims for an user. It allows you to enable your application as a Token Provider, responsible for issuing tokens.
Once the user is in possession of a token, it must be included on every single request in order to re-authenticate the user and create his security context before the request processing.

Note

Usually, when using tokens to authenticate your users, you would prefer to configure the Identity Bean as stateless. Take a look at Section 2.2.1, “Stateful or Stateless Authentication” for more details.
By default, tokens are issued based on a HTTP BASIC authentication. This is the primary authentication method used in order to check for user credentials before issuing a token. If the authentication is successful, PicketLink will ask a Token Provider to issue a new token and write it to the response using a JSON format.
To configure this authentication scheme for a path, just do:
httpBuilder
    .forPath("/authenticate")
        .authenticateWith()
            .token();
Before using this authentication scheme, you must provide a representation for your token and also a token provider, responsible for issuing tokens. Let's start by defining a simple token representation:
public class MyToken extends AbstractToken {

    private String token;

    public MyToken(String token) {
        super(token);
    }

    @Override
    public String getSubject() {
        return this.token;
    }
}
This is the most simple example about how to represent a token. It is just a string value where the token itself contains the user identifier. PicketLink allows you to support any token format, you can even use JSON Web Token and JOSE specifications to provide a better representation for your tokens. In real world use cases, you would prefer a format where the token has an unique identifier, expiration time and a set of claims representing the information for your users such as: username, identifier, roles and so forth.
Once you define your token format, you must provide a token provider.
@Stateless
public class MyTokenProvider implements Token.Provider<MyToken> {

    @Inject
    private PartitionManager partitionManager;

    @Override
    public MyToken issue(Account account) {
        MyToken token = new MyToken(account.getId());
        IdentityManager identityManager = getIdentityManager(account);

        identityManager.updateCredential(account, token);

        return token;
    }

    @Override
    public MyToken renew(Account account, MyToken renewToken) {
        IdentityManager identityManager = getIdentityManager(account);
        TokenCredentialStorage tokenStorage = getCurrentToken(account, identityManager);

        if (tokenStorage.getToken().equals(renewToken.getToken())) {
            invalidate(account);
            return issue(account);
        }

        return null;
    }

    @Override
    public void invalidate(Account account) {
        IdentityManager identityManager = getIdentityManager(account);

        identityManager.removeCredential(account, TokenCredentialStorage.class);
    }

    @Override
    public Class<MyToken> getTokenType() {
        return MyToken.class;
    }

    private TokenCredentialStorage getCurrentToken(Account account, IdentityManager identityManager) {
        return identityManager.retrieveCurrentCredential(account, TokenCredentialStorage.class);
    }

    private IdentityManager getIdentityManager(Account account) {
        return this.partitionManager.createIdentityManager(account.getPartition());
    }
}
This is a very simple example of a Token.Provider. Token providers are responsible for issuing, invalidating and renewing tokens. In this case, we're issuing a token where its value is the id of a specific Account. In real world use cases, you'll prefer a better format such as JWT.

Note

In this case we're marking the token provider as an EJB by using the @Stateless annotation. The reason for that is that if you are using the JPA Identity Store you must initiate or join a transaction before persisting data to the database. When using an EJB all transaction management is done by the container. Considering this is just an exmaple about how to use a specific functionality, we are trying to keep the code simple without managing transaction manually.
To the this configuration you can start by sending a request to the /authenticate path as follows:
POST /picketlink-forge-app/authenticate HTTP/1.1
Host: localhost:8080
Content-Type: application/json
X-Requested-With: XMLHttpRequest
Cache-Control: no-cache
The request above is trying to invoke the given path without provide any credentials. In this case, PicketLink will respond with a 401 HTTP Status Code, teeling that authentication is required. The response also contains a specific header to indicate which type of authentication is required.
Content-Length →1062
Content-Type →text/html;charset=utf-8
Date →Thu, 21 Aug 2014 12:58:51 GMT
Server →Apache-Coyote/1.1
WWW-Authenticate →Token
As you can see, the server is asking for a Token by setting the WWW-Authenticate header.
Now, let's get a token from the server. By default, PicketLink performs a HTTP Basic authentication in order to validate the identity of an user before issuing a token. That is what we call, the primary authentication scheme. You can always change this behavior and use whatever you want to validate the user identity prior to issue tokens.
POST /picketlink-forge-app/authenticate HTTP/1.1
Host: localhost:8080
Authorization: Basic cGlja2V0bGluazpwaWNrZXRsaW5r
Cache-Control: no-cache
The request above is sending a HTTP Basic credential to the server. If the server successfuly validates the given credential then it will finally respond with the token:
{"authctoken":"4761e6f7-847d-4a7a-afc1-1a899c3d5d61"}
By default, PicketLink will just write to the response body a JSON containing the token. Useful if you are in a HTML5 application using AJAX to authenticate your users. But you can also change this behavior if you want to.
This authentication scheme also provides a special behavior when handling AJAX requests. As you might know, some browsers display an authentication dialog when receiving a 401 status code even if you are using AJAX to send requests. PicketLink tries to avoid this issue by just checking the presence of the X-Requested-With header in the request. Most AJAX libraries such as JQuery and AngularJS do use this header when sending AJAX requests. In this case, PicketLink will not respond with a 401, but with a 403 status code.