DIRKRB-652 Support dynamic load token provider.
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/TokenKdcTestBase.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/TokenKdcTestBase.java
index b53495a..d330abf 100644
--- a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/TokenKdcTestBase.java
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/TokenKdcTestBase.java
@@ -33,8 +33,6 @@
 import org.apache.kerby.kerberos.kerb.type.ticket.KrbTicket;
 import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
 import org.apache.kerby.kerberos.provider.token.JwtTokenEncoder;
-import org.apache.kerby.kerberos.provider.token.JwtTokenProvider;
-import org.junit.Before;
 
 import java.io.File;
 import java.io.IOException;
@@ -56,12 +54,6 @@
     private File cCacheFile;
     private KrbToken krbToken;
 
-    @Before
-    public void setUp() throws Exception {
-        KrbRuntime.setTokenProvider(new JwtTokenProvider());
-        super.setUp();
-    }
-
     @Override
     protected void configKdcSeverAndClient() {
         super.configKdcSeverAndClient();
@@ -90,7 +82,7 @@
 
     protected AuthToken prepareToken(String audience, String issuer,
                                      PrivateKey signingKey, PublicKey encryptionKey) {
-        AuthToken authToken = KrbRuntime.getTokenProvider().createTokenFactory().createToken();
+        AuthToken authToken = KrbRuntime.getTokenProvider("JWT").createTokenFactory().createToken();
         authToken.setIssuer(issuer);
         authToken.setSubject(SUBJECT);
 
@@ -112,7 +104,7 @@
         Date iat = now;
         authToken.setIssueTime(iat);
 
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
 
         if (tokenEncoder instanceof JwtTokenEncoder && signingKey != null) {
             tokenEncoder.setSignKey(signingKey);
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
index 792e23a..116185a 100644
--- a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
@@ -512,7 +512,7 @@
     }
 
     private byte[] signToken(AuthToken authToken, PrivateKey signKey) throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
         assertTrue(tokenEncoder instanceof JwtTokenEncoder);
 
         ((JwtTokenEncoder) tokenEncoder).setSignKey((RSAPrivateKey) signKey);
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/KerbyTokenAppTest.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/KerbyTokenAppTest.java
index b0033f4..897e084 100644
--- a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/KerbyTokenAppTest.java
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/KerbyTokenAppTest.java
@@ -100,7 +100,7 @@
     }
 
     private byte[] signToken(AuthToken authToken, PrivateKey signKey) throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
         assertTrue(tokenEncoder instanceof JwtTokenEncoder);
 
         ((JwtTokenEncoder) tokenEncoder).setSignKey((RSAPrivateKey) signKey);
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
index 044870b..e064b20 100644
--- a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
@@ -20,20 +20,19 @@
 package org.apache.kerby.kerberos.kerb.integration.test;
 
 import org.apache.kerby.kerberos.kerb.KrbRuntime;
-import org.apache.kerby.kerberos.kerb.common.KrbUtil;
 import org.apache.kerby.kerberos.kerb.client.jaas.TokenCache;
 import org.apache.kerby.kerberos.kerb.client.jaas.TokenJaasKrbUtil;
+import org.apache.kerby.kerberos.kerb.common.KrbUtil;
 import org.apache.kerby.kerberos.kerb.provider.TokenEncoder;
 import org.apache.kerby.kerberos.kerb.server.KdcConfigKey;
 import org.apache.kerby.kerberos.kerb.server.LoginTestBase;
 import org.apache.kerby.kerberos.kerb.server.TestKdcServer;
 import org.apache.kerby.kerberos.kerb.type.base.AuthToken;
 import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
-import org.apache.kerby.kerberos.provider.token.JwtTokenProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.junit.After;
 import org.junit.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.security.auth.Subject;
 import java.io.File;
@@ -52,10 +51,6 @@
     static final String GROUP = "sales-group";
     static final String ROLE = "ADMIN";
 
-    static {
-        KrbRuntime.setTokenProvider(new JwtTokenProvider());
-    }
-
     @Before
     @Override
     public void setUp() throws Exception {
@@ -89,7 +84,7 @@
 
         TokenEncoder tokenEncoder = null;
         try {
-            tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+            tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
         } catch (Exception e) {
             LOG.error("Failed to create token. " + e.toString());
         }
@@ -107,7 +102,7 @@
     }
 
     protected AuthToken issueToken(String principal) {
-        AuthToken authToken = KrbRuntime.getTokenProvider().createTokenFactory().createToken();
+        AuthToken authToken = KrbRuntime.getTokenProvider("JWT").createTokenFactory().createToken();
 
         String iss = "token-service";
         authToken.setIssuer(iss);
diff --git a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/jaas/TokenAuthLoginModule.java b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/jaas/TokenAuthLoginModule.java
index bb98a46..472fecd 100644
--- a/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/jaas/TokenAuthLoginModule.java
+++ b/kerby-kerb/kerb-client/src/main/java/org/apache/kerby/kerberos/kerb/client/jaas/TokenAuthLoginModule.java
@@ -263,13 +263,13 @@
         // Sign the token.
         if (signKeyFile != null) {
             try {
-                TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+                TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
                 try {
                     authToken = tokenDecoder.decodeFromString(tokenStr);
                 } catch (IOException e) {
                     LOG.error("Token decode failed. " + e.toString());
                 }
-                TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+                TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
 
                 if (tokenEncoder instanceof JwtTokenEncoder) {
                     PrivateKey signKey = null;
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbRuntime.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbRuntime.java
index ff36235..c1a668d 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbRuntime.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/KrbRuntime.java
@@ -35,7 +35,10 @@
      * Set up token provider, should be done at very initial time
      * @return token provider
      */
-    public static synchronized TokenProvider getTokenProvider() {
+    public static synchronized TokenProvider getTokenProvider(String tokenType) {
+        if (tokenProvider == null || !tokenType.equals(tokenProvider.getTokenType())) {
+            tokenProvider = TokenProviderRegistry.createProvider(tokenType);
+        }
         if (tokenProvider == null) {
             throw new RuntimeException("No token provider is available");
         }
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/TokenProviderRegistry.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/TokenProviderRegistry.java
new file mode 100644
index 0000000..55bc076
--- /dev/null
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/TokenProviderRegistry.java
@@ -0,0 +1,63 @@
+/**
+ * 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
+ *
+ *     http://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.
+ */
+package org.apache.kerby.kerberos.kerb;
+
+import org.apache.kerby.kerberos.kerb.provider.TokenProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class TokenProviderRegistry {
+    static final Logger LOG = LoggerFactory.getLogger(TokenProviderRegistry.class);
+
+    private static Map<String, Class> allProvider = new ConcurrentHashMap<>();
+
+    static {
+        ServiceLoader<TokenProvider> providers = ServiceLoader.load(TokenProvider.class);
+
+        for (TokenProvider provider : providers) {
+            allProvider.put(provider.getTokenType(), provider.getClass());
+        }
+    }
+
+    public static Set<String> registeredProviders() {
+        return Collections.unmodifiableSet(allProvider.keySet());
+    }
+
+    public static boolean registeredProvider(String name) {
+        return allProvider.containsKey(name);
+    }
+
+    public static TokenProvider createProvider(String name) {
+        if (!registeredProvider(name)) {
+            LOG.error("Unregistered token provider " + name);
+            throw new RuntimeException("Unregistered token provider " + name);
+        }
+        try {
+            return (TokenProvider) allProvider.get(name).newInstance();
+        } catch (Exception e) {
+            LOG.error("Create {} token provider failed", name, e);
+            throw new RuntimeException("Create " + name + "token provider failed" + e);
+        }
+    }
+}
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/provider/TokenProvider.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/provider/TokenProvider.java
index 0ff548f..6a64c37 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/provider/TokenProvider.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/provider/TokenProvider.java
@@ -27,6 +27,13 @@
 public interface TokenProvider extends KrbProvider {
 
     /**
+     * Get the token type
+     *
+     * @return login type
+     */
+    String getTokenType();
+
+    /**
      * Create a token encoder.
      * @return token encoder
      */
diff --git a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbToken.java b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbToken.java
index d1637b5..dbc99d7 100644
--- a/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbToken.java
+++ b/kerby-kerb/kerb-core/src/main/java/org/apache/kerby/kerberos/kerb/type/base/KrbToken.java
@@ -63,7 +63,7 @@
         setTokenType();
         setTokenFormat(format);
         try {
-            setTokenValue(getTokenEncoder().encodeAsBytes(innerToken));
+            setTokenValue(getTokenEncoder(format).encodeAsBytes(innerToken));
         } catch (KrbException e) {
             throw new RuntimeException("Failed to encode AuthToken", e);
         }
@@ -93,7 +93,7 @@
     public void decode(Asn1ParseResult parseResult) throws IOException {
         super.decode(parseResult);
         if (getTokenValue() != null) {
-            this.innerToken = getTokenDecoder().decodeFromBytes(getTokenValue());
+            this.innerToken = getTokenDecoder(getTokenFormat()).decodeFromBytes(getTokenValue());
             setTokenType();
         }
     }
@@ -114,9 +114,9 @@
      * Get token encoder.
      * @return The token encoder
      */
-    protected static TokenEncoder getTokenEncoder() {
+    protected static TokenEncoder getTokenEncoder(TokenFormat format) {
         if (tokenEncoder == null) {
-            tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+            tokenEncoder = KrbRuntime.getTokenProvider(format.getName()).createTokenEncoder();
         }
         return tokenEncoder;
     }
@@ -125,9 +125,9 @@
      * Get token decoder.
      * @return The token decoder
      */
-    protected static TokenDecoder getTokenDecoder() {
+    protected static TokenDecoder getTokenDecoder(TokenFormat format) {
         if (tokenDecoder == null) {
-            tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+            tokenDecoder = KrbRuntime.getTokenProvider(format.getName()).createTokenDecoder();
         }
         return tokenDecoder;
     }
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java
index e508023..2b703bb 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/preauth/token/TokenPreauth.java
@@ -91,7 +91,7 @@
             }
 
             // Configure keys
-            TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+            TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
             configureKeys(tokenDecoder, kdcRequest, issuer);
 
             AuthToken authToken = null;
diff --git a/kerby-provider/token-provider/src/main/java/org/apache/kerby/kerberos/provider/token/JwtTokenProvider.java b/kerby-provider/token-provider/src/main/java/org/apache/kerby/kerberos/provider/token/JwtTokenProvider.java
index 036443e..91f795b 100644
--- a/kerby-provider/token-provider/src/main/java/org/apache/kerby/kerberos/provider/token/JwtTokenProvider.java
+++ b/kerby-provider/token-provider/src/main/java/org/apache/kerby/kerberos/provider/token/JwtTokenProvider.java
@@ -34,6 +34,14 @@
      * {@inheritDoc}
      */
     @Override
+    public String getTokenType() {
+        return "JWT";
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public TokenEncoder createTokenEncoder() {
         return new JwtTokenEncoder();
     }
diff --git a/kerby-provider/token-provider/src/main/resources/META-INF/services/org.apache.kerby.kerberos.kerb.provider.TokenProvider b/kerby-provider/token-provider/src/main/resources/META-INF/services/org.apache.kerby.kerberos.kerb.provider.TokenProvider
new file mode 100644
index 0000000..18dbdd5
--- /dev/null
+++ b/kerby-provider/token-provider/src/main/resources/META-INF/services/org.apache.kerby.kerberos.kerb.provider.TokenProvider
@@ -0,0 +1,16 @@
+# 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
+#
+#     http://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.
+
+org.apache.kerby.kerberos.provider.token.JwtTokenProvider
diff --git a/kerby-provider/token-provider/src/test/java/org/apache/kerby/kerberos/provider/token/TokenTest.java b/kerby-provider/token-provider/src/test/java/org/apache/kerby/kerberos/provider/token/TokenTest.java
index d6b07bf..ba544f7 100644
--- a/kerby-provider/token-provider/src/test/java/org/apache/kerby/kerberos/provider/token/TokenTest.java
+++ b/kerby-provider/token-provider/src/test/java/org/apache/kerby/kerberos/provider/token/TokenTest.java
@@ -19,6 +19,8 @@
  */
 package org.apache.kerby.kerberos.provider.token;
 
+import com.nimbusds.jose.JWEAlgorithm;
+import com.nimbusds.jose.JWSAlgorithm;
 import org.apache.kerby.kerberos.kerb.KrbRuntime;
 import org.apache.kerby.kerberos.kerb.provider.TokenDecoder;
 import org.apache.kerby.kerberos.kerb.provider.TokenEncoder;
@@ -27,9 +29,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import com.nimbusds.jose.JWEAlgorithm;
-import com.nimbusds.jose.JWSAlgorithm;
-
+import javax.crypto.KeyGenerator;
 import java.io.IOException;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
@@ -40,14 +40,8 @@
 import java.util.Date;
 import java.util.List;
 
-import javax.crypto.KeyGenerator;
-
 public class TokenTest {
 
-    static {
-        KrbRuntime.setTokenProvider(new JwtTokenProvider());
-    }
-
     static final String SUBJECT = "test-sub";
     static final String AUDIENCE = "krbtgt@EXAMPLE.COM";
     static final String ISSUER = "oauth2.com";
@@ -59,7 +53,7 @@
 
     @Before
     public void setUp() {
-        authToken = KrbRuntime.getTokenProvider().createTokenFactory().createToken();
+        authToken = KrbRuntime.getTokenProvider("JWT").createTokenFactory().createToken();
 
         authToken.setIssuer(ISSUER);
         authToken.setSubject(SUBJECT);
@@ -84,11 +78,11 @@
 
     @Test
     public void testToken() throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
         String tokenStr = tokenEncoder.encodeAsString(authToken);
         Assertions.assertThat(tokenStr).isNotNull();
 
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         setAudience((JwtTokenDecoder) tokenDecoder, auds);
 
@@ -99,11 +93,11 @@
 
     @Test
     public void testDecodeFromBytes() throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
         byte[] tokenStr = tokenEncoder.encodeAsBytes(authToken);
         Assertions.assertThat(tokenStr).isNotNull();
 
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         setAudience((JwtTokenDecoder) tokenDecoder, auds);
 
@@ -114,8 +108,8 @@
 
     @Test
     public void testTokenWithEncryptedJWT() throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         setEncryptKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
         setAudience((JwtTokenDecoder) tokenDecoder, auds);
@@ -130,8 +124,8 @@
     
     @Test
     public void testTokenWithDirectEncryptedJWT() throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
         keyGenerator.init(128);
@@ -165,8 +159,8 @@
 
     @Test
     public void testTokenWithSignedJWT() throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         setSignKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
         setAudience((JwtTokenDecoder) tokenDecoder, auds);
@@ -181,8 +175,8 @@
     
     @Test
     public void testTokenWithHMACSignedJWT() throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
         keyGenerator.init(256);
@@ -212,8 +206,8 @@
     @org.junit.Ignore
     // TODO: building error with openjdk8: NoSuchAlgorithm EC KeyPairGenerato..
     public void testTokenWithECDSASignedJWT() throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
         KeyPair keyPair = kpg.generateKeyPair();
@@ -233,8 +227,8 @@
     
     @Test
     public void testTokenWithSignedAndEncryptedJWT() throws Exception {
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         setSignKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
         setEncryptKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
@@ -253,8 +247,8 @@
         List<String> audiences = new ArrayList<String>();
         audiences.add("invalid@EXAMPLE.COM");
 
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         setSignKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
         setEncryptKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
@@ -271,8 +265,8 @@
     public void testExpiredJWT() throws Exception {
         authToken.setExpirationTime(new Date(new Date().getTime() - 100));
 
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         setSignKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
         setEncryptKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
@@ -289,8 +283,8 @@
     public void testNotBeforeTime() throws Exception {
         authToken.setNotBeforeTime(new Date(new Date().getTime() + 1000 * 60));
 
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
 
         setSignKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
         setEncryptKey((JwtTokenEncoder) tokenEncoder, (JwtTokenDecoder) tokenDecoder);
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenInit.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenInit.java
index d5ff8e1..a1cd5da 100644
--- a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenInit.java
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/token/TokenInit.java
@@ -23,7 +23,6 @@
 import org.apache.kerby.kerberos.kerb.provider.TokenDecoder;
 import org.apache.kerby.kerberos.kerb.provider.TokenEncoder;
 import org.apache.kerby.kerberos.kerb.type.base.AuthToken;
-import org.apache.kerby.kerberos.provider.token.JwtTokenProvider;
 
 import java.util.ArrayList;
 import java.util.Date;
@@ -35,12 +34,8 @@
  */
 public class TokenInit {
 
-    static {
-        KrbRuntime.setTokenProvider(new JwtTokenProvider());
-    }
-
     public static AuthToken issueToken(String principal, String group, String role) {
-        AuthToken authToken = KrbRuntime.getTokenProvider().createTokenFactory().createToken();
+        AuthToken authToken = KrbRuntime.getTokenProvider("JWT").createTokenFactory().createToken();
 
         String iss = "token-service";
         authToken.setIssuer(iss);
@@ -86,13 +81,13 @@
             role = args[2];
         }
 
-        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+        TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider("JWT").createTokenEncoder();
         AuthToken token = issueToken(principal, group, role);
         String tokenStr = tokenEncoder.encodeAsString(token);
         TokenCache.writeToken(tokenStr);
         System.out.println("Issued token: " + tokenStr);
 
-        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider().createTokenDecoder();
+        TokenDecoder tokenDecoder = KrbRuntime.getTokenProvider("JWT").createTokenDecoder();
         AuthToken token2 = tokenDecoder.decodeFromString(tokenStr);
         System.out.println("Decoded token's subject: " + token2.getSubject());
     }