Search code examples
javaauthenticationservletswebspherejaas

Using a configured JAAS subject to authenticate a HttpURLConnection?


A few times in the past, I've had to make an authenticated HTTP or HTTPS connection in an app running on WebSphere Application Server.
I've typically created some custom way of storing a username and password for the connection - using a text or XML file or, for testing, just hard-coding - and added those details to an Authorization header in a HttpURLConnection, to perform HTTP Basic authentication.

I've recently considered that the WAS Integrated Solutions Console has a way of configuring usernames and passwords (under Security -> Java Authentication and Authorization Service -> J2C authentication data), and it makes sense to use a built-in feature (if possible) instead of always doing this in a custom way, but I haven't been able to figure out how to do so after an hour or so of searching.

So, does anyone know if it's possible, and how to do it if so, to use configured WAS J2C authentication data to authenticate arbitrary HTTP or HTTPS connections?

I assume it requires WebSphere APIs to:

  • Retrieve an object representing a J2C authentication entry by its alias; and
  • Do one of:
    • Get an authenticated HttpURLConnection or HttpsURLConnection object from the JAAS/J2C object;
    • Get the plain-text username and password so they can be added to an Authorization header; or
    • If the connection is to an IBM platform in the same domain: Get an LTPA token from the JAAS/J2C object, which can then be added to a cookie in the connection.

Also: If Apache HttpClient would make this any easier, I'm fine with using that, but appropriate WebSphere APIs would still be needed.

I have found a class that might be useful for WebSphere Portal (com.ibm.wps.portletservice.credentialvault.credentials.LtpaTokenCredential), but I need to do this in a non-Portal environment, so I can't use any Portal-specific classes or interfaces.

I would also need this to work in at least the following types of application: Servlets, and WebSphere Trust Association Interceptors.


Solution

  • I just tried the following (Modified from here) in a servlet and it worked to grab the auth alias user/pwd.

    import com.ibm.websphere.security.NotImplementedException;
    import com.ibm.wsspi.security.auth.callback.Constants;
    import com.ibm.wsspi.security.auth.callback.WSMappingCallbackHandlerFactory;
    import javax.resource.spi.security.PasswordCredential;
    import javax.security.auth.Subject;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.login.LoginContext;
    import javax.security.auth.login.LoginException;
    
    Map map = new HashMap();
    map.put(Constants.MAPPING_ALIAS, "REPLACE_WITH_YOUR_AUTH_ALIAS");
    CallbackHandler callbackHandler = null;
    try {
        callbackHandler = WSMappingCallbackHandlerFactory.getInstance().getCallbackHandler(map, null);
    } catch (NotImplementedException e) {
    }
    
    LoginContext loginContext = null;
    try {
    loginContext = new LoginContext("DefaultPrincipalMapping", callbackHandler);
        loginContext.login();
    } catch (LoginException e) {
    }
    
    Subject subject = loginContext.getSubject();
    Set credentials = subject.getPrivateCredentials();
    
    PasswordCredential passwordCredential = (PasswordCredential) credentials.iterator().next();
    
    String user = passwordCredential.getUserName();
    String password = new String(passwordCredential.getPassword());
    
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<h1>User: " + user + " --- Password: " + password+"</h1>");