I have an xmpp Client which is trying to authenticate by SSO through SAML authentication. But client send request to the openfire server, It could not send challeng
I referred this documentation https://tools.ietf.org/html/rfc6595#section-5.1
I get this out put :
SEND: <stream:stream xmlns:stream=“http://etherx.jabber.org/streams” xmlns=“jabber:client” to=“skovdevof01” version=“1.0” >
RCV: <stream:stream xmlns:stream=“http://etherx.jabber.org/streams” xmlns=“jabber:client” from=“dkodev060” id=“cfc0102d” xml:lang=“en” version=“1.0” >
RCV: <stream:features xmlns:stream=“http://etherx.jabber.org/streams”>
SAML20
EXTERNAL
DIGEST-MD5
ANONYMOUS
CRAM-MD5
</stream:features>
SEND:
RCV:
SEND: <stream:stream xmlns:stream=“http://etherx.jabber.org/streams” xmlns=“jabber:client” to=“skovdevof01” version=“1.0” >
RCV: <stream:stream xmlns:stream=“http://etherx.jabber.org/streams” xmlns=“jabber:client” from=“dkodev060” id=“cfc0102d” xml:lang=“en” version=“1.0” >
RCV: <stream:features xmlns:stream=“http://etherx.jabber.org/streams”>
SAML20
EXTERNAL
DIGEST-MD5
ANONYMOUS
CRAM-MD5
zlib
</stream:features>
SEND: biwsc2tvdmRldm9mMDE=
RCV: </stream:stream>
SEND: </stream:stream>
I am currently using below Java method handle(…) of SASLAuthentication.java class.
public static Status handle(LocalSession session, Element doc) throws UnsupportedEncodingException {
Status status;
String mechanism;
if (doc.getNamespace().asXML().equals(SASL_NAMESPACE)) {
ElementType type = ElementType.valueof(doc.getName());
switch (type) {
case AUTH:
mechanism = doc.attributeValue(“mechanism”);
// Store the requested SASL mechanism by the client
session.setSessionData(“SaslMechanism”, mechanism);
//Log.debug("SASLAuthentication.doHandshake() AUTH entered: "+mechanism);
if (mechanism.equalsIgnoreCase(“ANONYMOUS”) &&
mechanisms.contains(“ANONYMOUS”)) {
status = doAnonymousAuthentication(session);
}
else if (mechanism.equalsIgnoreCase(“EXTERNAL”)) {
status = doExternalAuthentication(session, doc);
}
else if (mechanisms.contains(mechanism)) {
// The selected SASL mechanism requires the server to send a challenge
// to the client
try {
Map<String, String> props = new TreeMap<String, String>();
props.put(Sasl.QOP, “auth”);
if (mechanism.equals(“GSSAPI”)) {
props.put(Sasl.SERVER_AUTH, “TRUE”);
}
SaslServer ss = Sasl.createSaslServer(mechanism, “xmpp”,
JiveGlobals.getProperty(“xmpp.fqdn”, session.getServerName()), props,
new XMPPCallbackHandler());
// evaluateResponse doesn’t like null parameter
byte[] token = new byte[0];
if (doc.getText().length() > 0) {
// If auth request includes a value then validate it
token = StringUtils.decodeBase64(doc.getText().trim());
if (token == null) {
token = new byte[0];
}
}
if (mechanism.equals(“DIGEST-MD5”)) {
// RFC2831 (DIGEST-MD5) says the client MAY provide an initial response on subsequent
// authentication. Java SASL does not (currently) support this and thows an exception
// if we try. This violates the RFC, so we just strip any initial token.
token = new byte[0];
}
byte[] challenge = ss.evaluateResponse(token);
if (ss.isComplete()) {
authenticationSuccessful(session, ss.getAuthorizationID(),
challenge);
status = Status.authenticated;
}
else {
// Send the challenge
sendChallenge(session, challenge);
status = Status.needResponse;
}
session.setSessionData(“SaslServer”, ss);
}
catch (SaslException e) {
Log.info("User Login Failed. " + e.getMessage());
authenticationFailed(session);
status = Status.failed;
}
}
else {
Log.warn(“Client wants to do a MECH we don’t support: '” +
mechanism + “’”);
authenticationFailed(session);
status = Status.failed;
}
break;
case RESPONSE:
// Store the requested SASL mechanism by the client
mechanism = (String) session.getSessionData(“SaslMechanism”);
if (mechanism.equalsIgnoreCase(“EXTERNAL”)) {
status = doExternalAuthentication(session, doc);
}
else if (mechanism.equalsIgnoreCase(“JIVE-SHAREDSECRET”)) {
status = doSharedSecretAuthentication(session, doc);
}
else if (mechanisms.contains(mechanism)) {
SaslServer ss = (SaslServer) session.getSessionData(“SaslServer”);
if (ss != null) {
boolean ssComplete = ss.isComplete();
String response = doc.getTextTrim();
try {
if (ssComplete) {
authenticationSuccessful(session, ss.getAuthorizationID(),
null);
status = Status.authenticated;
}
else {
byte[] data = StringUtils.decodeBase64(response);
if (data == null) {
data = new byte[0];
}
byte[] challenge = ss.evaluateResponse(data);
if (ss.isComplete()) {
authenticationSuccessful(session, ss.getAuthorizationID(),
challenge);
status = Status.authenticated;
}
else {
// Send the challenge
sendChallenge(session, challenge);
status = Status.needResponse;
}
}
}
catch (SaslException e) {
Log.debug(“SASLAuthentication: SaslException”, e);
authenticationFailed(session);
status = Status.failed;
}
}
else {
Log.error(“SaslServer is null, should be valid object instead.”);
authenticationFailed(session);
status = Status.failed;
}
}
else {
Log.warn(
“Client responded to a MECH we don’t support: '” + mechanism + “’”);
authenticationFailed(session);
status = Status.failed;
}
break;
default:
authenticationFailed(session);
status = Status.failed;
// Ignore
break;
}
}
else {
Log.debug("SASLAuthentication: Unknown namespace sent in auth element: " + doc.asXML());
authenticationFailed(session);
status = Status.failed;
}
// Check if SASL authentication has finished so we can clean up temp information
if (status == Status.failed || status == Status.authenticated) {
// Remove the SaslServer from the Session
session.removeSessionData(“SaslServer”);
// Remove the requested SASL mechanism by the client
session.removeSessionData(“SaslMechanism”);
}
return status;
}
Kindly suggest me to resolve this Issue. Thank you