title: JAAS Kerberos authentication fails for user with international characters
body: <p>Below is a sample Kerberos JAAS client I used for trying out Active Directory authentication (based on this Spring Source code <a href="http://goo.gl/qRFNKY" rel="nofollow">http://goo.gl/qRFNKY</a>).</p>
  
  <p>I am able to authenticate the user when the name and password contain only English characters.  </p>
  
  <pre><code>//works
  client.login("joe@MYDOMAIN.COM", "Password1");
  </code></pre>
  
  <p>It fails when either field contains international characters.</p>
  
  <pre><code>//fails
  client.login("áá@MYDOMAIN.COM", "çã123");
  </code></pre>
  
  <p>How to internationalize this code?</p>
  
  <pre><code>package aa;
  
  import java.io.IOException;
  import java.util.HashMap;
  
  import javax.security.auth.callback.Callback;
  import javax.security.auth.callback.CallbackHandler;
  import javax.security.auth.callback.NameCallback;
  import javax.security.auth.callback.PasswordCallback;
  import javax.security.auth.callback.UnsupportedCallbackException;
  import javax.security.auth.login.AppConfigurationEntry;
  import javax.security.auth.login.Configuration;
  import javax.security.auth.login.LoginContext;
  import javax.security.auth.login.LoginException;
  
  
  public class SampleKerberosClient {
  
      public static void main(String[] args) throws LoginException {
          SampleKerberosClient client = new SampleKerberosClient();
  
          //works
              client.login("joe@MYDOMAIN.COM", "Password1");
  
          //fails
              client.login("áá@MYDOMAIN.COM", "çã123");
  
      }
  
      private boolean debug = true;
      private String krbConfLocation = "/Users/aa/java/jaas/src/aa/krb5.conf";
  
      public SampleKerberosClient() {
          System.setProperty("java.security.krb5.conf", krbConfLocation);
          System.setProperty("sun.security.krb5.debug", "true");
      }
  
      public String login(String username, String password) throws LoginException {
          System.out.println("Trying to authenticate " + username + " with Kerberos");
          String validatedUsername;
  
          LoginContext loginContext = new LoginContext("", null, new KerberosClientCallbackHandler(username, password),
                  new LoginConfig(this.debug));
          loginContext.login();
          System.out.println("Kerberos authenticated user: " + loginContext.getSubject());
          validatedUsername = loginContext.getSubject().getPrincipals().iterator().next().toString();
          loginContext.logout();
  
          System.out.println("validated user name: " + validatedUsername);
          return validatedUsername;
  
      }
  
  
      private static class LoginConfig extends Configuration {
          private boolean debug;
  
          public LoginConfig(boolean debug) {
              super();
              this.debug = debug;
          }
  
          @Override
          public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
              HashMap&lt;String, String&gt; options = new HashMap&lt;String, String&gt;();
              options.put("storeKey", "true");
              if (debug) {
                  options.put("debug", "true");
              }
  
              return new AppConfigurationEntry[]{new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
                      AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options),};
          }
      }
  
      private static class KerberosClientCallbackHandler implements CallbackHandler {
          private String username;
          private String password;
  
          public KerberosClientCallbackHandler(String username, String password) {
              this.username = username;
              this.password = password;
          }
  
          @Override
          public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
              for (Callback callback : callbacks) {
                  if (callback instanceof NameCallback) {
                      NameCallback ncb = (NameCallback) callback;
                      ncb.setName(username);
                  } else if (callback instanceof PasswordCallback) {
                      PasswordCallback pwcb = (PasswordCallback) callback;
                      pwcb.setPassword(password.toCharArray());
                  } else {
                      throw new UnsupportedCallbackException(callback, "We got a " + callback.getClass().getCanonicalName()
                              + ", but only NameCallback and PasswordCallback is supported");
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>Below is the console output (when it fails)</p>
  
  <pre><code>Trying to authenticate áá@MYDOMAIN.COM with Kerberos
  Debug is  true storeKey true useTicketCache false useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is null tryFirstPass is false useFirstPass is false storePass is false clearPass is false
          [Krb5LoginModule] user entered username: áá@MYDOMAIN.COM
  
  Using builtin default etypes for default_tkt_enctypes
  default etypes for default_tkt_enctypes: 3 1 23 16 17 18.
  Acquire TGT using AS Exchange
  &gt;&gt;&gt; KdcAccessibility: reset
  Using builtin default etypes for default_tkt_enctypes
  default etypes for default_tkt_enctypes: 3 1 23 16 17 18.
  &gt;&gt;&gt; KrbAsReq calling createMessage
  &gt;&gt;&gt; KrbAsReq in createMessage
  &gt;&gt;&gt; KrbKdcReq send: kdc=ADSERVER.MYDOMAIN.COM.com UDP:88, timeout=30000, number of retries =3, #bytes=179
  &gt;&gt;&gt; KDCCommunication: kdc=ADSERVER.MYDOMAIN.COM UDP:88, timeout=30000,Attempt =1, #bytes=179
  &gt;&gt;&gt; KrbKdcReq send: #bytes read=116
  &gt;&gt;&gt; KrbKdcReq send: #bytes read=116
  &gt;&gt;&gt; KdcAccessibility: remove ADSERVER.MYDOMAIN.COM.
  &gt;&gt;&gt; KDCRep: init() encoding tag is 126 req type is 11
  &gt;&gt;&gt;KRBError:
       sTime is Mon Mar 31 17:10:03 PDT 2014 1396311003000
       suSec is 268438
       error code is 6
       error Message is Client not found in Kerberos database
       realm is MYDOMAIN.COM
       sname is krbtgt/MYDOMAIN.COM
       msgType is 30
          [Krb5LoginModule] authentication failed 
  Client not found in Kerberos database (6)
  Exception in thread "main" javax.security.auth.login.LoginException: Client not found in Kerberos database (6)
      at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:696)
      at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:542)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
      at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
      at javax.security.auth.login.LoginContext$5.run(LoginContext.java:706)
      at java.security.AccessController.doPrivileged(Native Method)
      at javax.security.auth.login.LoginContext.invokeCreatorPriv(LoginContext.java:703)
      at javax.security.auth.login.LoginContext.login(LoginContext.java:575)
      at aa.SampleKerberosClient.login(SampleKerberosClient.java:45)
      at aa.SampleKerberosClient.main(SampleKerberosClient.java:27)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
  Caused by: KrbException: Client not found in Kerberos database (6)
      at sun.security.krb5.KrbAsRep.&lt;init&gt;(KrbAsRep.java:66)
      at sun.security.krb5.KrbAsReq.getReply(KrbAsReq.java:446)
      at sun.security.krb5.Credentials.sendASRequest(Credentials.java:419)
      at sun.security.krb5.Credentials.acquireTGT(Credentials.java:368)
      at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:662)
      ... 18 more
  Caused by: KrbException: Identifier doesn't match expected value (906)
      at sun.security.krb5.internal.KDCRep.init(KDCRep.java:133)
      at sun.security.krb5.internal.ASRep.init(ASRep.java:58)
      at sun.security.krb5.internal.ASRep.&lt;init&gt;(ASRep.java:53)
      at sun.security.krb5.KrbAsRep.&lt;init&gt;(KrbAsRep.java:50)
      ... 22 more
  </code></pre>