class StatefulTokenStore implements OpenIdConnectTokenStore {

    public AccessToken createAccessToken(String grantType, String accessTokenType, String authorizationCode,
            String resourceOwnerId, String clientId, String redirectUri, Set<String> scope,
            RefreshToken refreshToken, String nonce, String claims, OAuth2Request request)
            throws ServerException, NotFoundException {

        OpenIdConnectClientRegistration clientRegistration = getClientRegistration(clientId, request);
        
        final OAuth2ProviderSettings providerSettings = providerSettingsFactory.get(request);
        final String id = UUID.randomUUID().toString();
        final String auditId = IdGenerator.DEFAULT.generate();

        String realm = null;
        try {
            realm = realmNormaliser.normalise(request.<String>getParameter(REALM));
        } catch (org.forgerock.json.resource.NotFoundException e) {
            throw new NotFoundException(e.getMessage());
        }

        long expiryTime = 0;
        if (clientRegistration == null) {
            expiryTime = providerSettings.getAccessTokenLifetime() + currentTimeMillis();
        } else {
            expiryTime = clientRegistration.getAccessTokenLifeTime(providerSettings) + currentTimeMillis();
        }
        
        final AccessToken accessToken = new StatefulAccessToken(id, authorizationCode, resourceOwnerId,
                clientId, redirectUri, scope, expiryTime, refreshToken, OAuth2Constants.Token.OAUTH_ACCESS_TOKEN,
                grantType, nonce, realm, claims, auditId);
        try {
            tokenStore.create(accessToken.toJsonValue());
            if (auditLogger.isAuditLogEnabled()) {
                String[] obs = {"CREATED_TOKEN", accessToken.toString()};
                auditLogger.logAccessMessage("CREATED_TOKEN", obs, null);
            }
        } catch (CoreTokenException e) {
            logger.error("Could not create token in CTS: " + e.getMessage());
            if (auditLogger.isAuditLogEnabled()) {
                String[] obs = {"FAILED_CREATE_TOKEN", accessToken.toString()};
                auditLogger.logErrorMessage("FAILED_CREATE_TOKEN", obs, null);
            }
            throw new ServerException("Could not create token in CTS: " + e.getMessage());
        }
        request.setToken(AccessToken.class, accessToken);
        return accessToken;
    }

    @Inject public  StatefulTokenStore(OAuthTokenStore tokenStore, OAuth2ProviderSettingsFactory providerSettingsFactory,
            OAuth2UrisFactory<RealmInfo> oauth2UrisFactory,
            OpenIdConnectClientRegistrationStore clientRegistrationStore, RealmNormaliser realmNormaliser,
            SSOTokenManager ssoTokenManager, CookieExtractor cookieExtractor, OAuth2AuditLogger auditLogger,
            @Named(OAuth2Constants.DEBUG_LOG_NAME) Debug logger, SecureRandom secureRandom,
            ClientAuthenticationFailureFactory failureFactory, RecoveryCodeGenerator recoveryCodeGenerator);

}