Product SiteDocumentation Site

4.4.5. Token-based Credential Handler

This credential handler enables authentication using a security token. You can use any token format you want. Tokens are represented as a string value containing sensitive information about an account. Different tokens can be represented such as SAML Assertions, OpenID ID Tokens, JWT and so forth.
Credentials can be updated as follows:
User user = BasicModel.getUser(identityManager, "jsmith");

StringBuilder tokenBuilder = new StringBuilder();

tokenBuilder
    .append("id=").append(UUID.randomUUID().toString())
    .append(";")
    .append("subject=").append(user.getId())
    .append(";")
    .append("partition=").append(user.getPartition().getName())
    .append(";")
    .append("userName=").append(user.getLoginName())
    .append(";")
    .append("expiration=").append(1000)
    .append(";");

MyToken token = new MyToken(tokenBuilder.toString());

identityManager.updateCredential(user, token);
In order to validate a credential you need the following code:
User user = BasicModel.getUser(identityManager, "jsmith");

MyToken token = new MyToken(tokenBuilder.toString());

TokenCredential credential = new TokenCredential(token);

identityManager.validateCredentials(credential);

if (Status.VALID.equals(credential.getStatus()) {
  // successful validation
} else {
  // invalid credential
}
In PicketLink you represent your tokens by implementing the org.picketlink.idm.credential.Token. You can also extend org.picketlink.idm.credential.AbstractToken, which is basically an adapter for the Token interface.
public class MyToken extends AbstractToken {

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

    @Override
    public String getSubject() {
        return extractSubjectFromToken();
    }

    private String extractSubjectFromToken() {
        // the code that knows how to extract the subject from the token string
    }
}
Your token type (eg.: the MyToken type above) is responsible to extract all the necessary information from the string value representing a token instance. Being the subject the most important piece of information. The subject helps PicketLink to properly validate tokens by linking it with the corresponding account. By default, PicketLink will try to resolve the account associated with a token using the subject as both an identifier or user name.
When validating tokens, PicketLink will just check if the string representing the token is the same as the value that was previously stored. While this should be enough for simple use cases, you may want to perform more validations when checking if a token is valid or not. In this case, you can provide a org.picketlink.idm.credential.Token.Consumer type and implement the validate method.
public class MyTokenConsumer implements Token.Consumer<MyToken> {

    @Override
    public boolean validate(MyToken token) {
        // eg.: check signatures, expiration, issuer and so forth
        return false;
    }
    
    @Override
    public <I extends IdentityType> I extractIdentity(MyToken token, Class<I> identityType, StereotypeProperty.Property stereotypeProperty, Object identifier) {
        return null;
    }

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

}
The token consumer also plays an important role when your application is just a service provider or relaying party that consumes token to perform local authentication and authorization. This is a very common scenario when your application is SSO-enabled and consuming tokens from an Identity Provider. In this case, the consumer also provides a extractIdentity method that will be used by PicketLink to ask for some very common identity information such as the account associated with a token, roles, groups and so forth.
When consuming tokens from an external IdP, you will probably want to provide a IDM configuration as follows.
IdentityConfigurationBuilder serviceProviderConfigBuilder = new IdentityConfigurationBuilder();

serviceProviderConfigBuilder
    .named("sp.config")
        .stores()
            .token()
                .tokenConsumer(new MyTokenConsumer())
                .supportAllFeatures();
The configuration above tells PicketLink to use a token-based identity store. That identity store is responsible to use the token associated with the current thread as a repository for identity information. It will invoke Token.Consumer#extractIdentity method all the time your code tries to lookup user, role or group information. The token identity store is very useful to support all authentication and authorization features provided by PicketLink even if you don't manage the identities consumed by your application. In this case, the only source of identity data you have is a token.
For last, tokens can also be managed by a org.picketlink.idm.credential.Token.Provider. Token providers are responsible to issue, renew and invalidate tokens for a given account.
public class MyTokenProvider implements Token.Provider<MyToken> {

    @Override
    public MyToken issue(Account account) {
        User user = (User) account;
        StringBuilder tokenBuilder = new StringBuilder();

        tokenBuilder
            .append("id=").append(UUID.randomUUID().toString())
            .append(";")
            .append("subject=").append(user.getId())
            .append(";")
            .append("partition=").append(user.getPartition().getName())
            .append(";")
            .append("userName=").append(user.getLoginName())
            .append(";")
            .append("expiration=").append(1000)
            .append(";");

        return new MyToken(tokenBuilder.toString());
    }

    @Override
    public MyToken renew(Account account, MyToken renewToken) {
        // you may also check if the renew token is valid
        return issue(account);
    }

    @Override
    public void invalidate(Account account) {
        // invalidate the token
    }

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

4.4.5.1. Configuration Parameters

The following table describes all configuration parameters supported by this credential handler:

Table 4.4. Configuration Parameters

Parameter Description
TokenCredentialHandler.TOKEN_CONSUMER Stores stateless and thread-safe instances of {@link org.picketlink.idm.credential.Token.Consumer}. The value can be a single instance, a list or an array.