class OpenIdConnectTokenGenerationImpl implements OpenIdConnectTokenGeneration {

    @Override
    public String generate(SSOToken subjectToken, STSInstanceState stsInstanceState,
                           TokenGenerationServiceInvocationState invocationState) throws TokenCreationException {

        final OpenIdConnectTokenConfig tokenConfig = stsInstanceState.getConfig().getOpenIdConnectTokenConfig();
        final long issueInstant = currentTimeMillis();
        final String subject = ssoTokenIdentity.validateAndGetTokenPrincipal(subjectToken);

        STSOpenIdConnectToken openIdConnectToken = buildToken(subjectToken, tokenConfig,
                invocationState.getOpenIdConnectTokenGenerationState(), issueInstant / 1000, subject);

        final JwsAlgorithm jwsAlgorithm = tokenConfig.getSignatureAlgorithm();
        final JwsAlgorithmType jwsAlgorithmType = jwsAlgorithm.getAlgorithmType();

        String tokenString;
        if (JwsAlgorithmType.HMAC.equals(jwsAlgorithmType)) {
            final SignedJwt signedJwt = symmetricSign(openIdConnectToken, jwsAlgorithm, tokenConfig.getClientSecret());
            tokenString = signedJwt.build();
        } else if (JwsAlgorithmType.RSA.equals(jwsAlgorithmType)) {
            final SignedJwt signedJwt = asymmetricSign(openIdConnectToken, jwsAlgorithm, getKeyPair(stsInstanceState.getOpenIdConnectTokenPKIProvider(),
                    tokenConfig.getSignatureKeyAlias(), tokenConfig.getSignatureKeyPassword()), determinePublicKeyReferenceType(tokenConfig));
            tokenString = signedJwt.build();
        } else {
            throw new TokenCreationException(ResourceException.BAD_REQUEST, "Unknown JwsAlgorithmType: " + jwsAlgorithmType);
        }
        if (stsInstanceState.getConfig().persistIssuedTokensInCTS()) {
            try {
                ctsTokenPersistence.persistToken(invocationState.getStsInstanceId(), TokenType.OPENIDCONNECT,
                        tokenString, subject, issueInstant, tokenConfig.getTokenLifetimeInSeconds());
            } catch (CTSTokenPersistenceException e) {
                throw new TokenCreationException(e.getCode(), e.getMessage(), e);
            }
        }
        return tokenString;
    }

    @Inject  OpenIdConnectTokenGenerationImpl(SSOTokenIdentity ssoTokenIdentity, JwtBuilderFactory jwtBuilderFactory,
                                     OpenIdConnectTokenClaimMapperProvider openIdConnectTokenClaimMapperProvider,
                                     CTSTokenPersistence ctsTokenPersistence,
                                     Logger logger);

}