I've set up an ejabberd server that I want to use as a game server only.
What things do I have to pay attention to regarding security and which steps are needed so that I can start using it as a game server? Of course, I want to enable communication between local users only, no communication to JIDs from other servers may be possible.
How can I disable features such as IRC and server-to-server? This has to be done in the ejabberd.cfg, right? Do I have to comment these paragraphs out or fill in empty brackets for their options?
I've defined the following access control list:
[{acl, admin, {user, "admin", "localhost"}},
{acl, admin, {user, "admin", "***.***.***.***"}},
{acl, local, {server, "localhost"}},
{acl, local, {server, "***.***.***.***"}}].
Regarding the access rights, is the following definition okay or should I disable all communication channels except for PubSub?
[{access, c2s, [{deny, blocked}, {allow, all}]},
{access, pubsub_createnode, [{allow, all}]},
{access, s2s_shaper, [{fast, all}]},
{access, c2s_shaper, [{none, admin}, {normal, all}]},
{access, muc, [{allow, all}]},
{access, max_user_sessions, [{2, all}]},
{access, configure, [{allow, admin}]},
{access, muc_admin, [{allow, admin}]},
{access, max_user_offline_messages,
[{5000, admin}, {100, all}]},
{access, announce, [{allow, admin}]},
{access, register, [{deny, all}]},
{access, local, [{allow, local}]}].
Afterwards, can I access the server via client libraries such as smack / asmack or do I need BOSH, HTTP-polling etc? Are XMPP ports open on mobile devices, usually?
Those security considerations above are most important to me, as I don't want to run a game server with potential security risks. But apart from that, I can't really get PubSub running yet.
On the client side, in the Android application, I use the asmack library and the following code to initiate a new XMPP session and send a message:
private void startXMPP() {
new Thread(new Runnable() {
public void run() {
try {
org.jivesoftware.smackx.ConfigureProviderManager.configureProviderManager();
ConnectionConfiguration xmppConfig = new ConnectionConfiguration("123.123.123.123");
xmppConfig.setDebuggerEnabled(true);
if (Build.VERSION.SDK_INT >= 14) {
xmppConfig.setTruststoreType("AndroidCAStore");
xmppConfig.setTruststorePassword(null);
xmppConfig.setTruststorePath(null);
xmppConfig.setSendPresence(true);
xmppConfig.setSecurityMode(SecurityMode.disabled);
}
else {
xmppConfig.setTruststoreType("BKS");
String path = System.getProperty("javax.net.ssl.trustStore");
if (path == null) {
path = "/system/etc/security/cacerts.bks";
}
xmppConfig.setTruststorePath(path);
}
SASLAuthentication.supportSASLMechanism("PLAIN", 0);
XMPPConnection xmpp = new XMPPConnection(xmppConfig);
xmpp.connect();
xmpp.login("john", "password");
PubSubManager xmppPubsub = new PubSubManager(xmpp);
ConfigureForm form = new ConfigureForm(FormType.submit);
form.setPersistentItems(false);
form.setDeliverPayloads(true);
form.setAccessModel(AccessModel.open);
form.setPublishModel(PublishModel.open);
form.setSubscribe(true);
LeafNode xmppNode;
try {
xmppNode = (LeafNode) xmppPubsub.createNode("TESTNODE", form);
}
catch (XMPPException e) {
xmppNode = (LeafNode) xmppPubsub.getNode("TESTNODE");
}
SimplePayload payload = new SimplePayload("book", "pubsub:test:book", "");
xmppNode.addItemEventListener(new ItemEventCoordinator<Item>());
xmppNode.subscribe("john#123.123.123.123");
xmppNode.publish(new PayloadItem<SimplePayload>(payload));
}
catch (Exception e) {
System.out.println("XMPP Connection failed!");
e.printStackTrace();
}
}
}).start();
}
Unfortunately, this does not work. Do you see why? As I have debugging enabled, I can see the following error message in LogCat:
<iq from='pubsub.123.123.123.123' to='john#123.123.123.123/Smack' id='Jf****6' type='result'><pubsub xmlns='http://jabber.org/protocol/pubsub'><subscription jid='john#123.123.123.123' subscription='subscribed' subid='53******B2'/></pubsub></iq>
<iq id="Je4Mf-7" to="pubsub.123.123.123.123" type="set"><pubsub xmlns="http://jabber.org/protocol/pubsub"><publish node='TESTNODE'><item></item></publish></pubsub></iq>
<iq from='pubsub.123.123.123.123' to='john#123.123.123.123/Smack' type='error' id='Jf****7'><pubsub xmlns='http://jabber.org/protocol/pubsub'><publish node='TESTNODE'><item/></publish></pubsub><error code='400' type='modify'><bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><payload-required xmlns='http://jabber.org/protocol/pubsub#errors'/></error></iq>
Edit:
I've not set the PubSub node name to home/server/username/whatever as described in the documentation. But at least the creation of the node is working, though, isn't it? I don't want a name in that format because I need names such as "game234234" so that all participating users can join that PubSub node.
Moreover, there seem to be attempts to contact pubsub.***.***.***.*** which is not there, as I have not created the subdomain pubsub. Is that the cause of the problem? Is PubSub only available via that subdomain? I don't know what to set up for that subdomain and would prefer to use PubSub just on the IP without subdomain.
You are getting an error on your publish() command since you have not specified the actual payload. Ideally, an exception should have been thrown since you created an invalid payload, but that seems to be the source of the error you are getting from the server.
Change
SimplePayload payload = new SimplePayload("book", "pubsub:test:book", "");
to:
SimplePayload payload = new SimplePayload("book", "pubsub:test:book", "<book xmlns='pubsub:test:book'>Romeo and Juliet</book>");
and it should successfully publish.
Now there are a couple of other problems you need to address.
You are creating your connection within the run method which ends after the publish(), thus your connection passes out of scope and is eligible for GC.
Try doing a getNode() before creating. In your current order, after the first time your code is run you will always be hitting the exception case. You should simply do a getNode() first and then create one if an exception is thrown, or you could avoid the exception altogether by doing a discoverNodes() first to determine if the node exists.
As for your point about the pubsub subdomain. This is the commonly used subdomain for pubsub in many (maybe all) XMPP servers, including ejabberd. You don't have to create it as the pubsub module already does that. It does exist already since you are already getting replies from it.
Related
I am building an Android App which communicates with my REST API that is protected by Spring Security.
Since the Android App is "public" and no keys etc is secure I want to create diffrent obstacles and make things complicated to protect my API as much as possible.
One way in which I would like to add more security is to make sure that the one calling my API has a certificate. I don't want to create thousands of certificates in my APIs trust-store so I just want to make sure that the caller have one single certificate that I hid away in a keystore in my Android app.
In the examples I have found it seems like a "normal" X509Certificate authentication in Spring Security requires a unique certificate for every user and then this certificate replaces Basic auth or JWT auth. I would like to have individual client JWT tokens but make sure that every call brings my ONE Android App certificate to make (more) sure that someone is calling my API from my Android app.
Is this possible or is it just not what it is for?
When you create a RestTemplate you can configure it with a keystore and trust-store so in that end it should be easy. But as for protecting my REST API it seems more difficult since I want both certificate + JWT token or Basic auth.
I am not using XML configuration for my securityconfig. I instead extend WebSecurityConfigurerAdapter. It would be great if this was configurable in the configure(HttpSecurity http) method, but I'm thinking that maybe I could achieve this in a OncePerRequestFilter somehow? Perhaps configure a filter before my JwtAuthFilter?
Edit:
In all the examples I have found for configuration of spring security they always seems to use the certificate as an authentication. I just want to configure so that when someone call example.com/api/** it checks so that the certificate is approved by my custom trust store (so that I "know" it is probably a call from my app) but if someone call example.com/website it should use the default java trust store.
If someone call example.com/api/** I would like my server to
check certificate and kill the connection if the certificate is not approved in my custom truststore.
If certificate is ok, establish https (or move on if I can't kill the connection before it have already established https-connection) to user auth with Basic-/JWT-authentication.
I think I figured it out. Here is how I configured it and it seems to work.
The "/**" endpoint is the website which should work with any browser without any specific certificate, but it requires Admin authority (you need to login as admin).
The "/api/**" and "/connect/**" endpoints require the correct certificate, the correct API-key and valid Basic- or JWT-token authentification.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/loginForm")
.loginProcessingUrl("/authenticateTheUser")
.permitAll()
.and()
.logout()
.permitAll().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
http.requestMatchers()
.antMatchers("/connect/**","/api/**")
.and()
.addFilterBefore(new APIKeyFilter(null), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JwtAuthorizationFilter(), BasicAuthenticationFilter.class)
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/connect/**").hasAnyRole("MASTER,APPCALLER,NEGOTIATOR,MEMBER")
.antMatchers("/api/**").hasAnyRole("MASTER,MEMBER,ANONYMOUS");
}
The ApiKeyFilter class is the one that check the api-key and also make sure that the certificate used in the call is approved in my server trust-store. The api-key check is all that I had to configure, the extended X509AuthenticationFilter will automatically check the request certificate. My ApiKeyFilter looks like this:
public class APIKeyFilter extends X509AuthenticationFilter {
private String principalRequestHeader = "x-api-key";
private String apiKey = "XXXX";
public APIKeyFilter(String principalRequestHeader) {
if (principalRequestHeader != null) {
this.principalRequestHeader = principalRequestHeader;
}
setAuthenticationManager(new AuthenticationManager() {
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if(authentication.getPrincipal() == null) {
throw new BadCredentialsException("Access Denied.");
}
String rApiKey = (String) authentication.getPrincipal();
if (authentication.getPrincipal() != null && apiKey.equals(rApiKey)) {
return authentication;
} else {
throw new BadCredentialsException("Access Denied.");
}
}
});
}
#Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
return request.getHeader(principalRequestHeader);
}
#Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
X509Certificate[] certificates = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
if (certificates != null && certificates.length > 0) {
return certificates[0].getSubjectDN();
}
return super.getPreAuthenticatedCredentials(request);
}
}
Cred goes to these resources that helped me put things together:
Spring Boot - require api key AND x509, but not for all endpoints
spring security http antMatcher with multiple paths
Android grpc client is receiving GOAWAY from server with "too many pings" error. Now I realise that this is probably a server side issue, but I think the issue is that the client channel settings do not match that of the servers.
I have a C# gRPC server with the following settings:
List<ChannelOption> channelOptions = new List<ChannelOption>();
channelOptions.Add(new
ChannelOption("GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS",
1000));
channelOptions.Add(new
ChannelOption("GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA", 0));
channelOptions.Add(new
ChannelOption("GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS", 1));
this.server = new Server(channelOptions) {
Services = { TerminalService.BindService(this) },
Ports = {new ServerPort("0.0.0.0", 5000,
ServerCredentials.Insecure)}
};
On Android I have the following channel setup:
private val channel = ManagedChannelBuilder.forAddress(name, port)
.usePlaintext()
.keepAliveTime(10, TimeUnit.SECONDS)
.keepAliveWithoutCalls(true)
.build()
After a few min (however seems to be a random time). I get the goaway error. I noticed that if I stream data on the call then the error never happens. It is only when there is no data on the stream. This leads me to believe the issue is that the GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA needs to be set on the Android client aswell. Problem is for the life of me I cannot find where to set these channel settings on gRPC java. Can someone point out to me where I can set these channel settings? There are no examples where these have been set.
The channel options being specified are using the wrong names. Names like GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA are the C-defines for things like "grpc.http2.max_pings_without_data".
You can map from the C name to the key string by looking at grpc_types.h. You should prefer using one of the C# constants in ChannelOptions when it is available, but that doesn't seem to be an option in this case.
These options are not visible in the Java ManagedChannelBuilder API because they are server-specific settings. So instead they are visible on the ServerBuilder. See A8 client-side keepalive for reference to the Java keepalive API.
I've been wracking my brain these past two days to try and understand how to use the authentication built into ASP.NET's WebAPI 2 using Google as an external authentication, and not being familiar with OAuth 2, I'm quite lost. I have followed this tutorial to set up the sign-in button on my Android client and send the "idToken" to the Web API. I've also followed this (now out of date) tutorial on setting up Google as an external login.
The problem happens when I try to send it I get {"error":"unsupported_grant_type"} as a response. Some other tutorials lead me to believe that the POST to mysite.com/token does not contain the correct data. This means I'm either building the request incorrectlyon the client, I'm somehow handling it incorrectly on the backend, I'm sending it to the wrong url, or I'm doing something entirely else wrong.
I found this SO answer which says to get a URL from /api/Accounts/ExternalLogins, but the sign-in button already gives me the access token that would supply to me (if I understand that correctly).
If someone could help me out here on what the exact process should be from start to finish, that would be amazing.
UPDATE: Okay, so here are some things that I've learned since I asked this question.
website.com/token URI is the redirect for the built in OAuth server in the WebAPI2 template. This is not useful for this particular problem.
The id_token is an encoded JWT token.
The website.com/signin-google URI is the redirect for normal Google login, but does not accept these tokens.
I may have to write my own AuthenticationFilter that uses the Google Client library to authorize through the Google API.
UPDATE 2: I'm still working on getting this AuthenticationFilter Implementation. Things seem to be going well at this point, but I'm getting stuck on some things. I've been using this example to get the token verification code, and this tutorial to get the AuthenticationFilter code. The result is a mix of both of them. I'll post it here as an answer once it's complete.
Here are my current problems:
Producing an IPrincipal as output. The verification example makes a ClaimPrincipal, but the AuthenticationFilter example code uses a UserManager to match the username to an existing user and returns that principal. The ClaimsPrincipal as created in the verification example directly does not auto-associate with the existing user, so I need to attempt to match some element of the claims to an existing user. So how do I do that?
I still have an incomplete idea of what a proper flow for this is. I'm currently using the Authentication header to pass my id_token string using a custom scheme: "goog_id_token". The client must send their id_token for every method called on the API with this custom AuthenticationFilter. I have no idea how this would usually be done in a professional environment. It seems like a common enough use case that there would be tons of information about it, but I haven't seen it. I have seen the normal OAuth2 flow, and since I'm only using an ID Token, and not an Access Token I'm a bit lost on what an ID Token is supposed to be used for, where it falls in a flow, and where it's supposed to live in an HTTP packet. And because I didn't know these things, I've kind of been making it up as I go along.
Wow, I did it. I figured it out. I... I can't believe it.
As metioned in my question Update 2, this code is assembled from Google's official API C# example and Microsoft's Custom AuthenticationFilter tutorial and code example. I'm going to paste the AuthorizeAsync() here and go over what each block of code does. If you think you see an issue, please feel free to mention it.
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
bool token_valid = false;
HttpRequestMessage request = context.Request;
// 1. Look for credentials in the request
//Trace.TraceInformation(request.ToString());
string idToken = request.Headers.Authorization.Parameter.ToString();
The client adds the Authorization header field with the scheme followed by a single space, followed by the id token. It looks something like Authorization: id-token-goog IaMS0m3.Tok3nteXt.... Putting the ID token in the body as given in the google documentation made no sense in this filter so I decided to put it in the header. For some reason it was difficult to pull custom headers from the HTTP packets so I just decided to use the Authorization header with a custom scheme followed by the ID token.
// 2. If there are no credentials, do nothing.
if (idToken == null)
{
Trace.TraceInformation("No credentials.");
return;
}
// 3. If there are credentials, but the filter does not recognize
// the authentication scheme, do nothing.
if (request.Headers.Authorization.Scheme != "id-token-goog")
// Replace this with a more succinct Scheme title.
{
Trace.TraceInformation("Bad scheme.");
return;
}
This whole point of a filter is to ignore requests that the filter doesn't govern (unfamiliar auth schemes, etc), and make judgement on requests that it's supposed to govern. Allow valid authentication to pass to the downstream AuthorizeFilter or directly to the Controller.
I made up the scheme "id-token-goog" because I had no idea if there was an existing scheme for this use case. If there is, somebody please let me know and I'll fix it. I guess it doesn't particularly matter at the moment as long as my clients all know the scheme.
// 4. If there are credentials that the filter understands, try to validate them.
if (idToken != null)
{
JwtSecurityToken token = new JwtSecurityToken(idToken);
JwtSecurityTokenHandler jsth = new JwtSecurityTokenHandler();
// Configure validation
Byte[][] certBytes = getCertBytes();
Dictionary<String, X509Certificate2> certificates =
new Dictionary<String, X509Certificate2>();
for (int i = 0; i < certBytes.Length; i++)
{
X509Certificate2 certificate =
new X509Certificate2(certBytes[i]);
certificates.Add(certificate.Thumbprint, certificate);
}
{
// Set up token validation
TokenValidationParameters tvp = new TokenValidationParameters()
{
ValidateActor = false, // check the profile ID
ValidateAudience =
(CLIENT_ID != ConfigurationManager
.AppSettings["GoogClientID"]), // check the client ID
ValidAudience = CLIENT_ID,
ValidateIssuer = true, // check token came from Google
ValidIssuer = "accounts.google.com",
ValidateIssuerSigningKey = true,
RequireSignedTokens = true,
CertificateValidator = X509CertificateValidator.None,
IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
{
return identifier.Select(x =>
{
// TODO: Consider returning null here if you have case sensitive JWTs.
/*if (!certificates.ContainsKey(x.Id))
{
return new X509SecurityKey(certificates[x.Id]);
}*/
if (certificates.ContainsKey(x.Id.ToUpper()))
{
return new X509SecurityKey(certificates[x.Id.ToUpper()]);
}
return null;
}).First(x => x != null);
},
ValidateLifetime = true,
RequireExpirationTime = true,
ClockSkew = TimeSpan.FromHours(13)
};
This is all unchanged from the Google example. I have almost no idea what it does. This basically does some magic in creating a JWTSecurityToken, a parsed, decoded version of the token string, and sets up the validation parameters. I'm not sure why the bottom portion of this section is in it's own statement block, but it has something to do with the CLIENT_ID and that comparison. I'm not sure when or why the value of CLIENT_ID would ever change, but apparently it's necessary...
try
{
// Validate using the provider
SecurityToken validatedToken;
ClaimsPrincipal cp = jsth.ValidateToken(idToken, tvp, out validatedToken);
if (cp != null)
{
cancellationToken.ThrowIfCancellationRequested();
ApplicationUserManager um =
context
.Request
.GetOwinContext()
.GetUserManager<ApplicationUserManager>();
Get the user manager from the OWIN context. I had to dig around in context intellisense until I found GetOwinCOntext(), and then found that I had to add using Microsoft.Aspnet.Identity.Owin; in order to add the partial class that included the method GetUserManager<>().
ApplicationUser au =
await um
.FindAsync(
new UserLoginInfo(
"Google",
token.Subject)
);
This was the very last thing I had to fix. Again, I had to dig through um Intellisense to find all of the Find functions and their overrides. I had noticed from the Identity Framework-created tables in my database that there is one called UserLogin, whose rows contain a provider, a provider key, and a user FK. The FindAsync() takes a UserLoginInfo object, which contains only a provider string and a provider key. I had a hunch that these two things were now related. I had also recalled that there was a field in the token format that included a key-looking field that was a long number that started with a 1.
validatedToken seems to be basically empty, not null, but an empty SecurityToken. This is why I use token instead of validatedToken. I'm thinking there must be something wrong with this, but since the cp is not null, which is a valid check for a failed validation, it makes enough sense that the original token is valid.
// If there is no user with those credentials, return
if (au == null)
{
return;
}
ClaimsIdentity identity =
await um
.ClaimsIdentityFactory
.CreateAsync(um, au, "Google");
context.Principal = new ClaimsPrincipal(identity);
token_valid = true;
Here I have to create a new ClaimsPrincipal since the one created above in validation is empty (apparently that's correct). Took a guess on what the third parameter of CreateAsync() should be. It seems to work that way.
}
}
catch (Exception e)
{
// Multiple certificates are tested.
if (token_valid != true)
{
Trace.TraceInformation("Invalid ID Token.");
context.ErrorResult =
new AuthenticationFailureResult(
"Invalid ID Token.", request);
}
if (e.Message.IndexOf("The token is expired") > 0)
{
// TODO: Check current time in the exception for clock skew.
Trace.TraceInformation("The token is expired.");
context.ErrorResult =
new AuthenticationFailureResult(
"Token is expired.", request);
}
Trace.TraceError("Error occurred: " + e.ToString());
}
}
}
}
The rest is just exception catching.
Thanks for checking this out. Hopefully you can look at my sources and see which components came from which codebase.
I'm using Eclipse to (try to) build an Android client to get reuse a restlet service I developed using GAE and GWT.
My service is running at
http://127.0.0.1:8888/abc/audits
I can test this by going directly to this url, and by using my GWT client - both work.
However, the following code returns a communication error
private AuditsResource resource;
private Audits audits;
ClientResource cr = new ClientResource("http://127.0.0.1:8888/abc/audits");
resource = cr.wrap(AuditsResource.class);
try {
// Get the remote contact
audits = resource.retrieve();
// The task is over, let the parent conclude.
handler.sendEmptyMessage(0);
} catch (Exception e) {
Message msg = Message.obtain(handler, 2);
Bundle data = new Bundle();
data.putString("msg", "Cannot get the contact due to: "
+ e.getMessage());
msg.setData(data);
handler.sendMessage(msg);
}
I have no idea where to look next. I've instrumented the server implementation of AuditsResource, and it is never touched (by the Android application).
The AuditsResource class has one method, to keep things simple for now
#Get
public Audits retrieve();
It appears the problem is that the Andriod Emulator cannot connect to either 127.0.0.1 or 10.0.2.2. The solution is to use your PC's IP address.
I am able to connect from Android to my local Google App Engine through Android/Restlet using 10.0.2.2 instead of localhost.
Hello Everyone i am new to android and i am currently stuck on this.
I have to return list of public rooms created on xmpp server. The problem i am having is that the code below works fine for java but there is a null pointer exception in case of android.
Any help regarding this would be appreciated.
I am using an openfire server and testing it on local machine so that is the reason why i am using ip Address instead of domain name.
I am using smack library for JAVA and Asmack Library for android
String server_name = "192.168.3.113";
ConnectionConfiguration config = new ConnectionConfiguration(
server_name, 5222);
XMPPConnection connection = new XMPPConnection(config);
try {
connection.connect();
connection.login("s1", "123");
Collection<HostedRoom> rooms = MultiUserChat.getHostedRooms(
connection, "conference.geekoid");
for (HostedRoom room : rooms) {
System.out.println(room.getName());
}
} catch (XMPPException e) {
System.out.println("Error" + e.getMessage() + "\n"); //for JAVA
log.e("Android Error",e.getmessage()); // For Android
}
The problem is that the static block of the ServiceDiscoveryManager class has to be evaluated before any connection is created. In smack this is done via an configuration file, but this approach does not work on Android and therefore on aSmack.
The workaround mentioned in the answer is somehow ugly, since you really don't want to use the Constructor to fetch the SDM object, instead the get() method should be used. But the get() method only works if there was actually a SDM created for the connection.
So in order to init the SDM correctly on Android you need to call the full forName notation to init the static blocks of the class before you create the first (XMPP)Connection object.
Class.forName("org.jivesoftware.smackx.ServiceDiscoveryManager", true, ClassLoader.getSystemClassLoader()):
This is tracked as aSmack Issue 8
I have found the Solution to the problem.
The Android asmack library was using this in
getHostedRooms(Connection connection,
String serviceName) method
ServiceDiscoveryManager discoManager =ServiceDiscoveryManager.getInstanceFor(connection);
i replaced it with
ServiceDiscoveryManager discoManager = new ServiceDiscoveryManager(connection);
For those who are confused where this method is its in
Package: org.jivesoftware.smackx.muc
File: MultiUserChat.java
After you have done this. We have to register all the providers in Android whose detail can be found here. These providers are automatically registered when are using JAVA's smack library (In java Development) but in Android we have to register them ourself.