• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Getting 500 Internal server error on hitting the API with SSO using JAAS/GSS/Kerberos

 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Currently, I am working on REST APIs and want to make them sso enabled. For this I'm using OpenAM as well as trying to write a Java Client using Kerberos, JAAS and GSS API.
I came to know that with Open AM i can only test PCA apps and therefore i can only execute GET APIs using the browser. Therefore, to test the rest of the PUT, POST and DELETE APIs i have written a java client using JAAS/GSS and Kerberos.
I have attached my code with the post.
My concern is that :

As the subject of Login Context I get this:

Principal: akaagarwsso@DC2K3.COM

Private Credential: Ticket (hex) =

0000: 61 82 03 8A 30 82 03 86 A0 03 02 01 05 A1 0B 1B a...0...........

0010: 09 44 43 32 4B 33 2E 43 4F 4D A2 1E 30 1C A0 03 .DC2K3.COM..0...

0020: 02 01 02 A1 15 30 13 1B 06 6B 72 62 74 67 74 1B .....0...krbtgt.

0030: 09 44 43 32 4B 33 2E 43 4F 4D A3 82 03 50 30 82 .DC2K3.COM...P0.

0040: 03 4C A0 03 02 01 17 A1 03 02 01 02 A2 82 03 3E .L.............>

0050: 04 82 03 3A CC FA 72 CC 99 D6 04 CD 28 8B DE 53 ...:..r.....(..S

................................................................

Client Principal = akaagarwsso@DC2K3.COM

Server Principal = krbtgt/DC2K3.COM@DC2K3.COM

Session Key = EncryptionKey: keyType=3 keyBytes (hex dump)=

0000: F2 EF F1 E6 6D DA 58 10

Forwardable Ticket false

Forwarded Ticket false

Proxiable Ticket false

Proxy Ticket false

Postdated Ticket false

Renewable Ticket false

Initial Ticket false

Auth Time = Fri Aug 24 04:01:36 PDT 2012

Start Time = Fri Aug 24 04:01:36 PDT 2012

End Time = Fri Aug 24 14:01:36 PDT 2012

Renew Till = null

Client Addresses Null


I am getting the principal key in return. But when I execute the API, I get 500 Internal Server Error. This generally comes when the session has expired for SSO and I try to hit the API on the browser. So this means that the reason for this Internal Server Error is that as soon as I send the key to login to the server, the session expires or may be the credentials are incorrect.
FYI:

AD Info:
ucbu-vm87.dc2k3.com
Domain: dc2k3.com

User: akaagarwsso

Jaas.conf:

GSSClient{
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=false;
};

and the CallBackHandler:
import java.io.*;
import java.security.*;
import javax.security.auth.*;
import javax.security.auth.callback.*;

public class BeanCallbackHandler implements CallbackHandler {

// Store username and password.
String name = null;
String password = null;

public BeanCallbackHandler(String name, String password) {
System.out.println("The servername and password are::::" + name + " and " + password);
this.name = name;
this.password = password;
}// BeanCallbackHandler

public void handle(Callback[] callbacks)
throws UnsupportedCallbackException, IOException {
for (int i = 0; i < callbacks.length; i++) {
Callback callBack = callbacks[i];

// Handles user-name call-back.
if (callBack instanceof NameCallback) {
NameCallback nameCallback = (NameCallback) callBack;
nameCallback.setName(name);
// Handles password callback.
} else if (callBack instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback) callBack;
passwordCallback.setPassword(password.toCharArray());

} else {
throw new UnsupportedCallbackException(callBack,
"Call back not supported");
}// else
}// for

}// handle

}// BeanCallbackHandler


I also tried to create a simple html using Ajax call and when i opened that html in browser and hit a GET API, it also gave me 500 internal server error. For this thing what i could see in the firebug is that the cookie was not getting passed and probably that was the reason it was not able to authenticate.

However, I couldn't figure out the reason of failure for the JAAS based java app.

I don't understand what am i missing in both the approaches. Any help and guidance would be really appreciable.


Following i sthe code for Test.java:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.ietf.jgss.GSSException;

public class test {

private static GSSClient gssClient;

/**
* @param args
* @throws IOException
* @throws HttpException
* @throws InterruptedException
*/
public static void main(String[] args) throws HttpException, IOException, InterruptedException {

String theClientCred = authenticateAndGetKerberosToken();

String serviceAddress = "https://ucbu-aricent-vm199.dc2k3.com:8443/vmrest/user";
// String serviceAddress1 = "https://ucbu-aricent-vm266.pankaj.aricent-lab.cisco.com/vmrest/users?templateAlias=voicemailusertemplate";
//String message = "Akanksha";
// System.out.println(message);
//try {
//byte[] wrapedMsg = gssClient.wrapMessage(message.getBytes());
//serviceAddress += Base64.encodeBase64URLSafeString(wrapedMsg);

System.out.println("The service address is:::"+serviceAddress);
//} catch (GSSException e) {
//e.printStackTrace();
//}
//File file1 = new File("C:/Documents and Settings/ssouser/Desktop/Code/user.xml");
//GetMethod get = new GetMethod(serviceAddress);
GetMethod get = new GetMethod(serviceAddress)
{
@Override
public boolean getFollowRedirects()
{
return true;
}
};
get.setRequestHeader("Authorization", theClientCred);
get.setRequestHeader("Content-type", "application/xml; charset=ISO-8859-1");
//post.setRequestBody(new FileInputStream(file1));
HttpClient httpclient = new HttpClient();
// httpclient.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);

try {
int result = httpclient.executeMethod(get);
String s = get.getResponseBodyAsString();
System.out.println("Response status code: " + result);
System.out.println("Response body: " + s);

//System.out.println("After decryptionm: " + new String(gssClient.unWrapMessage(Base64 .decodeBase64(get.getResponseBodyAsString()))));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/* finally {
// Release current connection to the connection pool once you are done
get.releaseConnection();
}*/
// Thread.sleep(1000000);
}

private static String authenticateAndGetKerberosToken() {
System.out.println("I'm INNNNNN");
gssClient = new GSSClient("akaagarwsso", "Ecsbulab1");
byte[] b = gssClient.login();
System.err.println("The bytes are::: " + b);
String serviceTicket = Base64.encodeBase64String(b);
return serviceTicket;
}
}//End of Class

And the Code for GSSClient.java:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Properties;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.callback.*;

import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.MessageProp;
import org.ietf.jgss.Oid;

public class GSSClient implements java.security.PrivilegedAction<byte[]> {

// Handles callback from the JAAS framework.
private BeanCallbackHandler beanCallbackHandler = null;

// The main object that handles all JAAS login.
LoginContext peerLC = null;

// Socket and streams used for communication.
Socket socket = null;
DataInputStream inStream;
DataOutputStream outStream;

// This and remote clients.
String clientName = null;
String serverName = null;

// Address and port of remote server.
String serverAddress = null;
int serverPort;

// The name of the client configuration.
String confName = null;

private GSSContext clientGSSContext = null;

/**
* @param clientName, Client SPN
* @param password, client password
*/
public GSSClient(String clientName, String password){
System.err.println("The clientname in GSSClient ::"+ clientName);
Properties env = new Properties();
try {
env.load(this.getClass().getClassLoader().getResourceAsStream("gssclient.properties"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.clientName = clientName;
this.serverName = (String)env.getProperty("Server.SPN");
this.serverAddress = (String)env.getProperty("Server.Address");
this.confName = (String)env.getProperty("JAAS.Config.Name");

beanCallbackHandler = new BeanCallbackHandler(clientName, password);
setSystemProperties((String)env.getProperty("KDC.Realm"),
(String)env.getProperty("KDC.Address"),
(String)env.getProperty("JAAS.Config.Path"));
}
/**
* The GSSClient constructor only sets all the required parameters.
*
* @param clientName, Client SPN
* @param password, client password
* @param serverName, Remote server/service SPN
* @param serverAddress, Remote Server address IP or Hostname
* @param kerberosRealm, KDC realm or domain name
* @param kdcAddress, KDC Server address IP or Hostname
* @param confFile, fll path of JAAS COnfig file
* @param confName, JAAS config name
*/
public GSSClient(String clientName, String password, String serverName,
String serverAddress, String kerberosRealm,
String kdcAddress, String confFile, String confName){
// The beanCallbackHandler will require the name and password of the
// client.
beanCallbackHandler = new BeanCallbackHandler(clientName, password);
this.clientName = clientName;
this.serverName = serverName;
this.serverAddress = serverAddress;
this.confName = confName;
setSystemProperties(kerberosRealm, kdcAddress, confFile);
}// KerberoseLoginBean

private void setSystemProperties(String kerberosRealm, String kdcAddress,
String confFile) {
System.setProperty("java.security.krb5.realm", kerberosRealm);
System.setProperty("java.security.krb5.kdc", kdcAddress);
System.setProperty("java.security.auth.login.config", confFile);
System.setProperty("sun.security.krb5.debug", "true");
}

public byte[] login() {
try {
System.out.println("I'm inside LOGIN");
peerLC = new LoginContext(confName, beanCallbackHandler);
peerLC.login();
System.err.println("2222222222222"+peerLC.getSubject());
System.err.println("3333333333333"+peerLC.getSubject().getPrincipals());
return Subject.doAs(peerLC.getSubject(), this);
} catch (Exception e) {
System.out
.println(">>>> GSSClient....Secure Context not established..");
e.printStackTrace();
return null;
}// catch

}// establishSecureContextWithServer

// This is the only method in PrivilegedAction interface.
// It receives control only in case of successful authentication of the
// client.
public byte[] run() {

try {
GSSManager manager = GSSManager.getInstance();
Oid kerberos = new Oid("1.2.840.113554.1.2.2");
System.err.println("INSIDE RUN!!!");
GSSName clientPeerName = manager.createName(
// Name of the client for which we want to create this GSSName
// object.
clientName,
// Type of GSSName. Our client is a Windows user,
// which we can specifiy using GSSName.NT_USER_NAME
// property.
GSSName.NT_USER_NAME);
// GSSName remotePeerName2 = manager.createName("FakeSERver",
// GSSName.NT_USER_NAME);
GSSName remotePeerName = manager.createName(serverName,
GSSName.NT_USER_NAME);
System.err.println(">>> GSSClient... Getting client credentials");

GSSCredential peerCredentials = manager.createCredential(
// The GSSName object of the client.
clientPeerName,
// Time for which credentials whill be valid.
10 * 600,
// Kerberos mecahnism identifier.
kerberos,
// The client only intiates the secure context request.
GSSCredential.INITIATE_ONLY);

System.err
.println(">>> GSSClient...GSSManager creating security context");
clientGSSContext= manager.createContext(remotePeerName, kerberos,
peerCredentials, GSSContext.DEFAULT_LIFETIME);

// peerContext.requestCredDeleg(true);
clientGSSContext.requestConf(true);
clientGSSContext.requestMutualAuth(false);// I don't want to authenticate the
// Server.
byte[] byteToken = new byte[0];

byteToken = clientGSSContext.initSecContext(byteToken, 0,
byteToken.length);
return byteToken;
}// try
catch (org.ietf.jgss.GSSException ge) {
ge.printStackTrace();
System.err.println(">>> GSSClient... GSS Exception "
+ ge.getMessage());
}

catch (java.lang.Exception e) {
e.printStackTrace();
System.err.println(">>> GSSClient... Exception " + e.getMessage());
}// catch
return null;
}// run

// It returns the established login context to client.
public LoginContext getLoginContext() {
System.err.println("INSIDE GET LOGIN CONTEXT");
return peerLC;
}// getloginContext

public byte[] wrapMessage(byte[] msg) throws GSSException {
MessageProp msgProp = new MessageProp(0, false);
return clientGSSContext.wrap(msg, 0, msg.length, msgProp);
}

public byte[] unWrapMessage(byte[] msg) throws GSSException {
MessageProp msgProp = new MessageProp(0, false);
return clientGSSContext.unwrap(msg, 0, msg.length, msgProp);
}

}// End of GSSClient

Thanks in advance!

Best Regards,
Akanksha A
reply
    Bookmark Topic Watch Topic
  • New Topic