Discussion:
JAAS: configuring Websphere web-application to a custom realm/LoginModule
(too old to reply)
K***@csp-sw.de
2006-08-04 13:34:27 UTC
Permalink
Hi,

i´ve got to set up a Apache MyFaces 1.1 Webapplication on a WebSphere 5.1. My problem is to configure the JAAS-Login. The application has a custom LoginModule wich handles User-Authentication self by hibernate. It works fine on Tomcat´s and JBoss.
I´ve installed the application with the Websphere AdminConsole (it works fine) and configured JAAS Applications Login with the correct realm-name and LoginModules of my application.
Now if i want to log in, my own Login-Form only accepts the windows-user login but not uses my custom LoginModule/realm.

code-fragment form web.xml:

<security-constraint>
<display-name>MyUser</display-name>
<web-resource-collection>
<web-resource-name>MyLogin</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>MyUser</role-name>
</auth-constraint>
</security-constraint>

<login-config>
<auth-method>FORM</auth-method>
<realm-name>MyLogin</realm-name>
<form-login-config>
<form-login-page>/login.jsf</form-login-page>
<form-error-page>/error.jsf</form-error-page>
</form-login-config>
</login-config>

<security-role>
<role-name>MyUser</role-name>
</security-role>

an from server.xml configuration of tomcat:

<Realm className="org.apache.catalina.realm.JAASRealm"
appName="MyLogin"
userClassNames="MyLogin.UserNamePrincipal"
roleClassNames="MyLogin.RolePrincipal"
debug="99"
useContextClassLoader="true" />

jaas.config:

MyLogin {
MyLogin.auth.module.MyLoginModule requisite;
};

How could i configure this realm-assignment in WebSphere 5.1 (AdministratorConsole or config-file)?

Pls help me, i´m searching for a solution for a long time

kiliang.
Paul Ilechko
2006-08-04 14:04:12 UTC
Permalink
Post by K***@csp-sw.de
Hi,
i´ve got to set up a Apache MyFaces 1.1 Webapplication on a WebSphere
5.1. My problem is to configure the JAAS-Login. The application has a
custom LoginModule wich handles User-Authentication self by
hibernate. It works fine on Tomcat´s and JBoss.
I'm getting really close to refusing to answer any questions that make
this statement ...
Post by K***@csp-sw.de
I´ve installed the
application with the Websphere AdminConsole (it works fine) and
configured JAAS Applications Login with the correct realm-name and
LoginModules of my application. Now if i want to log in, my own
Login-Form only accepts the windows-user login but not uses my custom
LoginModule/realm.
Please read this article which explains how JAAS works in WebSphere, and
how to integrate with WAS security.

http://www-128.ibm.com/developerworks/websphere/techjournal/0508_benantar/0508_benantar.html
Ben_
2006-08-07 11:04:20 UTC
Permalink
Post by Paul Ilechko
hibernate. It works fine on TomcatŽs and JBoss.
I'm getting really close to refusing to answer any questions that make
this statement ...
Why ?

I use to take such statement as an indication that they have something
functional on another platform (vs. they are building up), and so the
problem they face is not about "creating" but about "migrating".
K***@csp-sw.de
2006-08-07 13:27:06 UTC
Permalink
Yes, Ben_ you´re right.

I want to migrate my existing web-application to Websphere 5.1, but i´m not able to configure the Websphere appropriate.
Maybe my first statement was slightly unpropitious formulated, i only want to use my application on Websphere for the Future.

I´ve read the tutorials and manuals about JAAS in Websphere but i even can´t assign my custom LoginModule to my application.

Thank you in advance,

kiliang.
d***@c-log.com
2006-08-08 06:36:05 UTC
Permalink
Hi,

I've seen this url which may be helpfull, where you can see you can configure your module for global security / system login configuration / WEB-INBOUND

http://www-128.ibm.com/developerworks/websphere/techjournal/0508_benantar/0508_benantar.html

Badfully, the interesting samples with WEB-INBOUND are made with TAI interface which are IBM proprietary however there are some clues to adapt them into JAAS.

If you manage to do something with jaas / WAS & web auth could you post it there ? Cause I'm facing the same problem.

Regards,
Denis.
K***@csp-sw.de
2006-08-10 07:58:16 UTC
Permalink
Hi,

now i could assign my own LoginModule to my Application. According to the explanations on
http://www-128.ibm.com/developerworks/websphere/techjournal/0508_benantar/0508_benantar.html
i defined the Login-Module in WEB_INBOUND and my Application-Login recognized it and called the initialize() and login() Method. Both don´t produce any Exceptions and login() returns true after authenticating the user. But before commit() is called there occures an error wich has the Errorcode "SECJ0369E".

SystemOut.log:
[10.08.06 09:39:52:558 CEST] 13df34cf SystemOut O login() succeeded
[10.08.06 09:39:52:819 CEST] 13df34cf LTPAServerObj E SECJ0369E: Authentication failed when using LTPA. The exception is .
[10.08.06 09:39:52:939 CEST] 13df34cf SystemOut O abort() started

"login() succeeded" is a system.out.println() in my LoginModule wich indicates that login() returns true.

Does anyone know what this Error means (i read that der should be the causing exceptions in "The exception is .", but i dont know why there aren´t any)

Thanks,

kiliang.
r***@filenet.com
2006-08-10 20:49:55 UTC
Permalink
There were three issues that I stumbled into when I implemented my own "pre-LTPA" type login module that were not addressed in that article mentioned earlier in the thread (and co-authored by Paul Ilechko, by the way). All of these caused the ltpaLoginModule to fail in ways similar to what you describe.

1) On WAS 5.1.1 (not sure about 5.1) the login() method needed to add an additional entry keyed by WSCREDENTIAL_LONGSECURITYKEY with the "long" name to the shared state. This extra entry is not needed by WAS 6.0.2+, but doesn't hurt if it's there.

2) The values for the security ID and the long security name (plus perhaps the unique ID) need to be ones that are acceptable for the current user repository (I used the user repository's getUniqueUserId and getUserSecurityName methods to get these values). Of course, this implies that one can't just assert any old identity but needs to use one that the user repository knows about.

3) Since I was using my own callback handler (not true in your case since you're using WEB_INBOUND), it needed to silently ignore WAS specific callbacks since ltpaLoginModule will use them.

Hope this info helps,

Rick
K***@csp-sw.de
2006-09-06 08:56:58 UTC
Permalink
Thanks Rick, it was very helpfully for me.

My LoginModule works now and i can login. But i have still a Problem with the LoginModule:

If i put the LoginModule with priority 1 and authenticationStrategy=REQUIRED on the WEB_INBOUND stack, all applications(e.g. adminconsole) try to login with my LoginModule. Defining my LoginModule anywhere else or with lower priority on the stack has the effect that the Module would be ignored. (initialize() oder constructor won´t be called)

Is there any possibility to link my LoginModule only to my Application an not to all? (adminconsole or other applications should not use my LoginModule)


Many thanks in advance,

kiliang.
Paul Ilechko
2006-09-06 23:32:27 UTC
Permalink
Post by K***@csp-sw.de
Thanks Rick, it was very helpfully for me.
If i put the LoginModule with priority 1 and
authenticationStrategy=REQUIRED on the WEB_INBOUND stack, all
applications(e.g. adminconsole) try to login with my LoginModule.
Defining my LoginModule anywhere else or with lower priority on the
stack has the effect that the Module would be ignored. (initialize()
oder constructor won´t be called)
Is there any possibility to link my LoginModule only to my
Application an not to all? (adminconsole or other applications should
not use my LoginModule)
Web Inbound is global, it affects all applications in the cell.

You can create a new application JAAS configuration and call it from
your code, but this is not as clean as piggybacking on the web inbound
config. You would need to do a subject.doAs after calling the app config
to set the identity on the current thread to the Subject created by the
login modules in your new configuration.
K***@csp-sw.de
2006-09-08 11:13:33 UTC
Permalink
Great, many thanks Paul.

Only my application calls the LoginModule now and passes through.
No Exception or Error occurs after submitting Login&Password. (initialize(), login() and commit() don´t produce any errors).

But after loggin in the Login-Page appears again. I don´t know why, because there are no warnings or errors, even in the logfiles.

I´ve wrote a customUserRegistry based on my own User-Database. login()-Method of the LoginModule creates this CustomUserRegistry and validates the username and password.


login() of my LoginModule:


public boolean login() throws LoginException {

Callback callbacks[] = new Callback[2];
callbacks[0] = new NameCallback("User:");
callbacks[1] = new PasswordCallback("Password:", false);
try {
callbackHandler.handle(callbacks);
} catch (IOException e2) {
throw new LoginException("IO error." + e2);
} catch (UnsupportedCallbackException e2) {
throw new LoginException("Callback unsupported." + e2);
}

String username = ((NameCallback) callbacks[0]).getName();
String password = new String(((PasswordCallback) callbacks[1]).getPassword());

this.subject.getPrincipals().add(new UserNamePrincipal(username));
final String encPWD = new CryptoAlgo().encrypt(password.toCharArray());
this.subject.getPublicCredentials().add(encPWD);

((PasswordCallback) callbacks[1]).clearPassword();
Hashtable hashtable = new Hashtable();
String uniqueid = null;
String longUserSecurityName = null;
final List users_roles_from_db = new ArrayList();

try {
UserRegistry reg = new CustomUserRegistry();
uniqueid = reg.getUniqueUserId(username);
longUserSecurityName = reg.getUserSecurityName(username);
} catch (Exception e1) {
e1.printStackTrace(System.out);
throw new LoginException(e1.getMessage());
}

final UserDao ud = new UserDao();
final LoginModuleUser user = ud.select(username);
final Set roles = user.getRoleSet();
boolean indic = false;

try {
// asserting
indic = UserDatabaseWrapper.getInstance().loginUser(this.subject);
} catch (LoginException e) {
e.printStackTrace();
throw new LoginException("Login Indicator failed." + e);
} catch (SecuritySubsystemException e) {
e.printStackTrace();
}

if(indic) {
for(final Iterator it = roles.iterator(); it.hasNext(); ) {
final LoginModuleRole o = (LoginModuleRole) it.next();
users_roles_from_db.add(o.getName());
}
} else {
throw new LoginException("Username oder Passwort incorrect!");
}

final List groups = new ArrayList();
if(users_roles_from_db.contains("applicationUser")) {
groups.add("applicationUser");
}

hashtable.put(AttributeNameConstants.WSCREDENTIAL_UNIQUEID, uniqueid);
hashtable.put(AttributeNameConstants.WSCREDENTIAL_SECURITYNAME, username);
hashtable.put(AttributeNameConstants.WSCREDENTIAL_GROUPS, groups);
hashtable.put(AttributeNameConstants.WSCREDENTIAL_CACHE_KEY,uniqueid);
sharedState.put("WSCREDENTIAL_LONGSECURITYKEY", longUserSecurityName);
subject.getPublicCredentials().add(hashtable);
return true;
}



Code of Login-Action-Method, wich is called from Login-Page:



public void loginAction() {
LoginContext lc = null;
try {
lc = new LoginContext("CWSLogin", new WSCallbackHandlerImpl(username, password));
} catch (LoginException le) {
System.out.println("Cannot create LoginContext. " + le.getMessage());
} catch (final SecurityException se) {
System.out.println("Cannot create LoginContext." + se.getMessage());
}

Subject.doAs(lc.getSubject(),
new PrivilegedAction() {
public Object run() {
final Subject s1 = Subject.getSubject(AccessController.getContext());
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
Subject s2 = Subject.getSubject(AccessController.getContext());
return null;
}
});
return null;
}});

try {
lc.login();
} catch (final LoginException le) {
System.out.println("Fails to create Subject. " + le.getMessage());
}
}


How could i tell the W.A.S. to store the Login or are my subject/publicCredentials entries wrong?

Many thanks in advance,

kiliang.
K***@csp-sw.de
2006-09-11 14:16:53 UTC
Permalink
here is toString() of my Subject&sharedState, perhapse anyone could tell me, if they´re okay? There are still no errors or exceptions which could tell me, why login doesn´t work :(

Subject toString():
Principal: UserNamePrincipal: kiliang
Principal: ***@71711eca
Principal: ***@ba719e99
public Credential: 69f102381617ce5337a06e04ff7de7bc
public Credential: {com.ibm.wsspi.security.cred.cacheKey=kiliangCWS, com.ibm.wsspi.security.cred.uniqueId=kiliang, com.ibm.wsspi.security.cred.longSecurityName=kiliang, com.ibm.wsspi.security.cred.securityName=kiliang, com.ibm.wsspi.security.cred.groups=[CWSUser]}

Shared State toString():
{com.ibm.wsspi.security.cred.longSecurityName=kiliang, com.ibm.wsspi.security.cred.propertiesObject={com.ibm.wsspi.security.cred.cacheKey=kiliangCWS, com.ibm.wsspi.security.cred.uniqueId=kiliang, com.ibm.wsspi.security.cred.longSecurityName=kiliang, com.ibm.wsspi.security.cred.securityName=kiliang, com.ibm.wsspi.security.cred.groups=[CWSUser]}, Callback=[Ljavax.security.auth.callback.Callback;@7eb7771}


thanks, kiliang
Paul Ilechko
2006-09-11 14:53:07 UTC
Permalink
Post by K***@csp-sw.de
public void loginAction() {
LoginContext lc = null;
try {
lc = new LoginContext("CWSLogin", new WSCallbackHandlerImpl(username, password));
} catch (LoginException le) {
System.out.println("Cannot create LoginContext. " + le.getMessage());
} catch (final SecurityException se) {
System.out.println("Cannot create LoginContext." + se.getMessage());
}
Subject.doAs(lc.getSubject(),
new PrivilegedAction() {
public Object run() {
final Subject s1 = Subject.getSubject(AccessController.getContext());
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
Subject s2 = Subject.getSubject(AccessController.getContext());
return null;
}
});
return null;
}});
try {
lc.login();
} catch (final LoginException le) {
System.out.println("Fails to create Subject. " + le.getMessage());
}
shouldn't lc.login come before Subject.doAs ? There's nothing in the
Subject yet, otherwise ...
Paul Ilechko
2006-09-11 14:54:29 UTC
Permalink
Also, you should be using WSSubject.doAs ...

Loading...