android client Not able to authorize signalR request using bearer-token - android

I am trying to connect signalR from the android client. I have already setup signalR hub and its working properly with javascript client on the browser. javascript client able to sent bearer-token and on the server side, I am able to get user identity.
But android java client is not able to send bearer token on. I am using https://github.com/SignalR/java-client library (As I am not using SIgnalR-core so not using latest SIgnalR core library)
connection = new HubConnection(serverUrl);
connection.getHeaders().put("Authorization","Bearer XYZ");
proxy = connection.createHubProxy(hubName);
When I run this code, I got an error
java.lang.InterruptedException: Operation was canceled
But when I don't send AUthorization header with the request then on server-side SIgnalR OnConnected() method called successfully.
The issue seems to be with sending Authorization header with the request.
For reference, the following is code to show how token authentication is implemented on the server-side
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
Provider = new QueryStringOAuthBearerProvider()
});
var hubConfiguration = new HubConfiguration
{
Resolver = GlobalHost.DependencyResolver,
};
map.RunSignalR(hubConfiguration);
});
ConfigureAuth(app);
I have tried calling it by removing authorization from the server. Then it called successfully. But not works when called with Authorization header.
When I tried connection without Authorization then on server-side OnCOnnected method called but Context. Identity is null.
android Java code for connecting to SignalR client
Platform.loadPlatformComponent(new AndroidPlatformComponent());
// Create Connection
connection = new HubConnection(serverUrl);
connection.getHeaders().put("Authorization","Bearer XYZ");
// Create Proxy
proxy = connection.createHubProxy(hubName);
// Establish Connection
ClientTransport clientTransport = new
ServerSentEventsTransport(connection.getLogger());
SignalRFuture<Void> signalRFuture = connection.start(clientTransport);
try {
signalRFuture.get();
} catch (InterruptedException e) {
return false;
} catch (ExecutionException e) {
return false;
}
return true;

If you are using Websocket, try this
https://github.com/doctorcareanywhere/java-client
build signalr-client-sdk and import the jar to your project
eg.
implementation files('libs/signalr-client-sdk.jar')

Related

Incorrect encoding exception when connecting to FCM using Smack Library

I am trying to connect to FCM using the smack library:
Here's what I've tried. It works, but I get an exception when the connection tries to login.
new Thread(new Runnable(){
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
private Handler umm;
#Override
public void run() {
configBuilder.setSecurityMode(XMPPTCPConnectionConfiguration.SecurityMode.disabled );
configBuilder.setServiceName("fcm-xmpp.googleapis.com");
configBuilder.setHost("fcm-xmpp.googleapis.com");//MAYBE PROBLEM HERE??
configBuilder.setPort(5236);
configBuilder.setCompressionEnabled(false);
configBuilder.setSendPresence(true);
configBuilder.setSocketFactory(SSLSocketFactory.getDefault());
InterfaceClass.FCMconnection = new XMPPTCPConnection(configBuilder.build());
umm = yes;
try {
InterfaceClass.FCMconnection.connect();
Log.v("pony", "white horse");
//InterfaceClass.FCMloggin.start();
android.os.Message y4 = android.os.Message.obtain();
y4.what = LOGINTOFCM;
umm.sendMessage(y4);
//the rest of the thread is just exception handling in catch clauses
Once my handler receives the message I attempt to login with the connection
like this:
try { FCMconnection.login("senderId#gcm.googleapis.com","SERVER_KEY");
Log.d("black","r2d2");
} catch (XMPPException e) {//exception thrown here
e.printStackTrace();
Log.d("black","maity "+e);
I get the following excecption:
"smack.sasl.SASLErrorException: SASLError using X-OAUTH2: incorrect- encoding"
Now from the documentation it says clearly to implement SASL plain mechanism,
but I don't know how? Here's what the documentation says:
"The connection has two important requirements:
You must initiate a Transport Layer Security (TLS) connection. Note that CCS doesn't currently support the STARTTLS extension.
CCS requires a SASL PLAIN authentication mechanism using #gcm.googleapis.com (FCM sender ID) and the Server key as the password, where the sender ID and Server key are the values you gathered when configuring your client app. See the client documentation for your platform for information on obtaining these credentials."
Does anybody have any idea what could be causing this exception? How should I connect to FCM with the smack library?
Thank you for any advice.
As per documentation connecting to FCM over XMPP protocol needs:
1) TLS connection in transport layer, to achieve this create SSLContext using TLS protocol extension
2) Plain SASL protocol, make sure "smack-sasl-javax-4.1.8.jar" is integrated into your build setup. This took me lot of time to figure out
3) Host, service name and port number are correct(refer code snippet below)
Below code snippet works perfectly for me:
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
} catch (Exception e) {
//Failed to get default ssl context with TLS enabled... something can't proceed further
}
XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration.builder();
config.setConnectTimeout(CONNECTION_TIMEOUT);
config.setSendPresence(true);
config.setCustomSSLContext(sslContext);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
config.setServiceName("gcm.googleapis.com");
config.setHost("fcm-xmpp.googleapis.com");
config.setPort(5236);//not production server
config.setDebuggerEnabled(true);
config.setCompressionEnabled(true);
config.setSocketFactory(sslContext.getSocketFactory());
(mConnection = new XMPPTCPConnection(config.build())).addConnectionListener(ConnectionSession.this);
mConnection.setPacketReplyTimeout(REPLY_TIMEOUT);
mConnection.connect();
mConnection.login(userID, password); //use your app server credential here
Smack version 4.8.1 implemented and tested from openfire setup.
Hope this help someone!!

How to attach POST variables to socket.io connection?

I have a webchat application which is running on Node.js and Socket.io. After user logins on main homepage port 80, he gets redirected to port 3000 (chat application) along with POST data containing his ID, username etc... On chat application page it validates details and registers user as new client.
However, now I am building android chat application and I get immediately disconnected from chat because basically android client fails validation since there is no POST data attached.
How can I add POST data along with connection request?
Here is a code that does it all in android:
try {
IO.Options opts = new IO.Options();
opts.forceNew = true;
final Socket socket = IO.socket("http://host:3000", opts);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener(){
#Override
public void call(Object... args){
socket.emit("mobile_ping", sf.getTextValue(MainActivity.this, R.id.editText));
}
});
socket.connect();
} catch (Exception e) {
Log.d("ERR", String.valueOf(e));
}

WebSocket Server Implementation at Xamarin Studio 5 Android Project

I am working on WebSocket server implementation on Xamarin for an Android project, here I have Monoframework MDK 3.10.0.23 and Xamarin.android 4.18 which are latest ones.
For server implementation I'm using HttpListener and HttpListenerContext and evaluating the context.Request.IsWebSocketrequest, which is always getting false, when I run it on a Google Nexus 10.
{
Console.WriteLine("WS Server Started Waiting for connection");
HttpListenerContext httpListenerContext = await httpListener.GetContextAsync();
if (!httpListenerContext.Request.IsWebSocketRequest)
{
WebSocketContext webSocketContext;
Console.WriteLine("Got a Valid WebSocket connection request");
try
{
webSocketContext = await httpListenerContext.AcceptWebSocketAsync(subProtocol:null);
}
catch (Exception e)
{
httpListenerContext.Response.StatusCode = 500;
httpListenerContext.Response.Close();
Console.WriteLine("Exception: {0}", e);
return;
}
WebSocket webSocket = webSocketContext.WebSocket;
if (webSocket == null)
Console.WriteLine ("WebSocket obj is null");
//ProcessRequest(httpListenerContext);
}
else
{
Console.WriteLine("Got a Bad WebSocket connection request");
httpListenerContext.Response.StatusCode = 400;
httpListenerContext.Response.Close();
}
}
Please help and suggest the problem here creating the HttpListener object for http:// local host at 9090
websockets initiates connection via http with the request to upgrade. if the server do not reply with the 101 response code, it is a sign that there is a problem in connection. the request to connect via websockets uses ws://yourdomain.com/nameOfApplicationEndPoint or wss in cases of ssl connection. i used this for my android project org.java-websocket:Java-WebSocket:1.3.0 and you can get a simple example here http://www.elabs.se/blog/66-using-websockets-in-native-ios-and-android-apps

Android - unable to use OAuth access token to retrieve Google Reader feeds

I need to obtain OAuth2 authentication token to pass it to the server so it can fetch list of Google Reader feeds for the user. Server is .NET - I have no access to it or to it's code but most likely it is using unofficial Reader API
I was able to use Android Account manager to obtain valid token for this purpose with the following code (notice that authTokenType="reader")
Account account = accounts[0];
manager.getAuthToken(account, "reader", null, this, new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
// If the user has authorized your application to use the tasks API
// a token is available.
String token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
// Now you can send the token to API...
cacheManager.putString(GOOGLE_AUTH, token);
GoogleReaderManager.startAddFeedActivity(AddGoogleReaderSourcesActivity.this);
finish();
} catch (OperationCanceledException e) {
Log.e(TAG, "User cancelled", e);
finish();
} catch (Exception e) {
Log.e(TAG, "Failed to obtain Google reader API_KEY", e);
}
}
}, null);
The code above works fine when I send token to the server side .Net app: the app is able to retrieve the list of Reader feeds.
The problem is that this only works for "Google inside" devices. On Nook I have no such luck since there's no way that I was able to find to add Google account to the account manager. So I'm trying to it using OAuth 2 protocol as described here
It works fine as far as obtaining the token: User approves the app from the mobile page which returns the code token which then mobile app exchanges for the Auth token. However this token will not work with the server process. I have a feeling that perhaps I'm using the wrong scope in this URL:
https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.google.com/reader/api/0/subscription/list&redirect_uri=http://localhost&approval_prompt=force&state=/ok&client_id={apps.client.id}
Scopes that I did try in various combinations:
https://www.google.com/reader/api
https://www.google.com/reader/api/0
https://www.google.com/reader/api/0/subscription/list
https://www.google.com/reader/api+https://www.google.com/reader/atom
Here's example of JSON that is returned from get token POST
{"expires_in":3600,
"token_type":"Bearer",
"access_token":"ya29.AHES6ZSEvuUb6Bvd2DNoMnnN_UnfxirZmf_RQjn7LptFLfI",
"refresh_token":"1\/bUwa5MyOtP6VyWqaIEKgfPh08LNdawJ5Qxz6-qZrHg0"}
Am I messing up scope or token type? Not sure how to change a token type. Any other ideas?
P.S. Google account login page asks: Manage your data in Google Reader, that's why I suspect that the scope is wrong
I got it working for https://www.google.com/reader/api/0/subscription/list. So thought of sharing with you.
I have valid access_token:
This is what i tried to resolve it (partially) :
Google provides OAuth 2.o playgound; where they actually simulate all aspects of OAuth 2.0 as well as final API call to fetch data.
I found this very helpful as it clearly shows what is being sent to request.
Here is the URL : https://developers.google.com/oauthplayground/
Using this, i tweaked my api call below and it works :)
public static String getReaderContent(String accessToken){
String url = "https://www.google.com/reader/api/0/subscription/list" ;
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(url);
String response="";
method.setRequestHeader("Authorization", "OAuth "+accessToken);
try {
int statusCode = client.executeMethod(method);
String response= method.getResponseBodyAsString();
System.out.println("response " + responseStr);
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
So this works properly fine for getting subscription list; but have not been able to make it work for reader api which you have mentioned in your question.
Let me know if you have got way around google reader API.

SIP Stack registration packet with authorization

we want to create SIP application on Android 2.3.3 and have some issues with android.sip stack (default sip stack). Our mobile app sends register sip packet, but
1.) by default OpenIMS core responds 400 Bad request P-Visited-Network-ID Header missing
2.) in the case that we set port number to 4060 -PCSCF /builder.setPort(4060)/ OpenIMS core sends this request from 4060 to 4060 (same port, same IP, same CSCF, same packet) and this is cykling until OpenIMS core send respond to mobile app - 504 Server Time-out.
We also tried SipDemo, CSipSimple and we had same problems.
When we tried Monster Communicator or IMSDroid, then it works!
There is one difference between working and problematic applications - working apps send register packet also with Authorization field.
Part of the code:
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
builder.setDisplayName(username);
builder.setProfileName(username + "#" + domain);
port = Integer.parseInt(4060);
builder.setProtocol(protocol);
mSipProfile = builder.build();
...
try { mSipManager.open(mSipProfile);} catch (SipException e) { ...}
try {
mSipManager.register(mSipProfile, 30, new SipRegistrationListener(){
public void onRegistering(String localProfileUri) {
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
}
public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage) {
}
});
} catch (SipException e) {
....
}
How to give authorization field to register packet in classic SIP stack?
We also tried J-SIP but it display error: Conversion to dalvik format failed with error 1.
Every answer would be very appreciated.
Your problem is not related to missing Authorization header.
Registration is done in the following matter:
the client send Register request without "Authorization" header.
server response with 401 response code which includes an header named "WWW-Authnticate", that header hold parameters as realm, opaque, qop and hashing algorithm type.
using these parameters with the username and passord an Authorication header is generated automatically by SIP stacks. and a second Register request is sent which includes the "Authorication" header.
the if the request is send in the correct manner the server return 200 OK response code which means that you are now registered.
Your problem is something else, you don't even get to step 3 (Authorization step), you fail in step 1, for your initial Register request you receive 400 Bad Request response code - which almost always mean that you have a syntax error in your request.

Categories

Resources