Unable to validate issuer when trying to access API - android

so here's a quick explanation of my issue - my current setup is and IdentityServer4 implementation with ASP.NET Core Identity, an API resource protected by it and a Xamarin.Android application that is the client. My current issue is that the client(Android) cannot get anything from the API because of the following error(from the API logs):
"Bearer" was not authenticated. Failure message: "IDX10205: Issuer validation failed. Issuer: 'http://10.0.2.2:5000'. Did not match: validationParameters.ValidIssuer: 'null' or validationParameters.ValidIssuers: 'http://127.0.0.1:5000'."
Basically, since I'm using the Android emulator, in order to call something that's on localhost on my machine, I need to use the 10.0.2.2 URL for it. Then the problem pops up - the Identity Server is fine with authenticating, I can login fine, I get an access token, but after that I need to call the API. And that's where the error happens - it's expecting an issuer that is with the same authority(127.0.0.1:5000) but receives the 10.0.2.2:5000, which is the authority for the Android client.
So, my question is - is there a way to somehow specify that 10.0.2.2 is also a valid issuer, or do I have to start thinking about deploying both the API and the Identity Server just so I can test the client. I'd really like it if there was a way to have the whole solution running on my local machine rather than having to deploy for every little thing I want to try out.
Any help will be appreciated very much.

First: Given the standard, you manage just one Issuer.
Are you managing your own Identity / Token generation? It sounds like this isn't the case.
You could customize your API for creating your tokens explicitly. Then, you can indicate a global Issuer (like your project url) so anyone can validate against the same.
var token = new JwtSecurityToken(
issuer: "http://my-perfect-proj.net",
claims: ...,
notBefore: DateTime.Now,
expires: DateTime.Now.AddHours(1),
signingCredentials: ...)
);
After your token is created and sent, validate your incoming request based on your tastes (checking time, user's data, issuer).
ASP.NET Core JWT Bearer Token Custom Validation
Creating RESTful API with Authentication
EDIT: Using Xamarin and Visual Studio on the same machine, didn't gave me this kind of problems but in that case, I was using Visual Studio Emulator. You could give it a try and avoid doing other types of workarounds.

So, I managed to work around the issue by simply running the Web part of it so it's visible on my local network. What I did in more detail - in the Program.cs where I create the host, I use the .UseUrls("http://*:5001") method, and then I run the app with dotnet run.
In this way your app is accessible in your local network via the IP address of your machine and the port you've specified. Also, in order for this to work, you'd have to define a new Outbound Rule in your Firewall to allow traffic through that port you're using. Hope this helps someone else as well, this turned out to be the easiest way to get what I need to work, and that's after fighting with IIS for a while trying to get it to work through there as well.

Short answer: In IIS, don't leave the site binding host name set as blank.
Longer explenation:
I received a similar error, but could see that for some reason it was trying to match the issuer domain name vs IP (the domain does point to the IP, but I guess it tries to validate the two strings). I could see this error after allowing logging : IdentityModelEventSource.ShowPII = true.
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidIssuerException:
IDX10205: Issuer validation failed. Issuer: 'http://ec2XXXXXom'. Did
not match: validationParameters.ValidIssuer: 'http://34.111.111.29' or
validationParameters.ValidIssuers: 'null'. at
Microsoft.IdentityModel.Tokens.Validators.ValidateIssuer(String
issuer, SecurityToken securityToken, TokenValidationParameters
validationParameters)
In IIS I previously had the host name set as blank (I am using the server name as domain name) - and therefore it set the issuer using the IP of the server. When I specifically set the site domain name, it worked.

Related

Custom IoT Endpoint

We need to use a custom IoT endpoint due to firewall restrictions and needing to utilize Static Ips. We followed this AWS doc to get our endpoint with static Ips.. From here we are attempting to call the CreateKeysAndCertificate via Java. Now when we call IoT with our custom domain name, iot.custom.domain.name.com, with the regular Java SDK it works fine. However, whenever we try to use the Android SDK and call setEndpoint with our custom domain we get the following error
com.amazonaws.services.iot.model.ResourceNotFoundException: Not Found (Service: AWSIot; Status Code: 404; Error Code: ResourceNotFoundException
Any help or guidance on this would be appreciated.
When using the Android SDK for establishing IOT connections, the CreateKeysAndCertificateRequest API is available through the AWSIotClient class. If you are using the AWSIotClient for creating new certs/keys, the SDK places this request on the generic iot.<region>.amazonaws.com endpoint. The setEndpoint method just allows you to change the region. This is because the request goes to the Control plane, whereas the endpoint that you have created would mostly likely be on the Data plane. There is no way around to create new certs/keys using the AWSIotClient on the custom endpoint.
There is an alternate option that you can make use of. Almost all "requests" that you place on the IOT endpoint are messages that are published to "reserved topics". If you open up the Java SDK's PublishCreateKeysAndCertificate API, you will see that it is ultimately publishing a message over a reserved topic. You can do something similar on Android using the Android SDK as well.
First, you will have to establish an authenticated connection. We cannot use CognitoCredentialsProvider because of that auth request going to the Control Plane. Instead, you can use the provisioning certificates for the first time authentication. This is through provision certificates generated for a Provisioning Fleet. You can create a Provisioning Fleet and use those certificates in your device's keystore (or, a PKCS12 cert file). Using that, you can create a new awsIotMqttManager object and publish a message on the reserved topic meant for creating new certs/keys. You can also subscribe to reserved topics meant for receiving the "accepted"/"rejected" responses for this request.
TL;DR
Create an awsIotMqttManager using the provision certs
Subscribe to topic for listening for accepted/rejected response for CreateKeysAndCertificates request
Publish a message over the reserved topic meant for CreateKeysAndCertificates
Register the thing using the ownershipToken received in the response
Store the new certs and use them for all future connections (make sure the policy attached to the certs have the necessary permissions)

Http failure response for (unknown url): 0 Unknown Error on android

I have an ionic app that when I run that on iOS then it works perfectly fine but when I run that on Android I get this error
Http failure response for (unknown url): 0 Unknown Error
Any reason I am getting this one? I have allowed CORS on server side as it is working on iOS devices.
Any help?
EDIT
This is what I have in my app.js file
const cors = require('cors');
And then I simply use it with default options.
app.use(cors());
If you are using localhost, change it to the IP address of the localhost. Android doesn't seems to support it where iOS do.
Try actual host name in case it didn't work too.
First you dont need CORS to call API from your android device.
Second probably your server is not accepting your request. If you are using Cloud then your server must accept request from any IP. There must be a option for allow IP address, place there from 0.0.0.1 to 254.254.254.254 so that each and every user can call your API.
Third you need to allow origin from your config.xml and also in header for CROS request. Check your API header and config file.
And fourth If your service is running under http then it will also could be the problem. Secure your service by adding SSL certificate. This could fix your problem.
We had experienced the same Error several times in our App. In our case it was a problem with the headers of the request and also a CORS problem on the serverside.
Are you able to reproduce this error in the browser if you emulate a android device? Then you could compare them with the headers of the iOS request.
Or you can try to log the incoming requests on the server-side to see if the requests reach the server and what headers are set.
Hope my ideas help :)
The solution is to add NODE_TLS_REJECT_UNAUTHORIZED=0 to your environment to disable the SSL verification in Node.js.
Note : You should only set this in development, Don't do this in production
EDIT
In that case it indicates that CORS has not been properly setup on your server. Go through the issue here

Why does android get the wrong ssl certificate? (two domains, one server)

I have two domains: foo.net and bar.com. They both have SSL certificates, and they work well in all desktop and mobile browsers. They are hosted on the same server configured with nginx.
However, when I make a request to a domain from within a native android app, it somehow gets the certificate from the wrong domain! This results in an IO Exception:
request = new HttpPost("https://foo.net/api/v1/baz");
request.setHeader("Authorization", "user:pass");
response = httpClient.execute(request);
...
javax.net.ssl.SSLException: hostname in certificate didn't match: <foo.net> != <bar.com> OR <bar.com> OR <www.bar.com>
What would cause android/java to try using the certificate from bar.com when every other measure seems to indicate that the server is correctly configured? Nothing appears in the nginx access or error log. There is no mention of bar.com anywhere in my android project.
Edit: I'm not sure why, but it appears that the server is using the certificate for bar.com for the server IP https://198.245.xx.xxx
The most likely cause for this problem is that the server uses Server Name Indication to choose which certificate to send. If the client doesn't support SNI, the server cannot choose which certificate to send during the SSL/TLS handshake (before any HTTP traffic is sent). SNI is required when you want to use multiple certificates on the same IP address and port, but not all clients support it (notoriously, IE on any version of Windows XP, and a number of mobile browsers).
You're also visibly using the Apache HTTP Client library (not HttpsURLConnection, for which there can be SNI support with some Android versions.
Support for SNI in the Apache HTTP Client library is quite recent, and certainly hasn't made it into the Android stack.
You may find the workaround described in this article useful (although it seems only to work for Android 4.2+).
Another two options would be:
to use a distinct IP address for each host (so as not to need SNI), if you're in control of server, or
to use another HTTP Client library (e.g. HttpsURLConnection).
A solution for Apache, more like a trick:
the SSL certificates are loaded based on the vhost name from /etc/apache2/sites-enabled. So, to trick that check make sure the problematic certificate is loaded first (remember that the vhosts are loaded by name).
It looks like the certificate of foo.net is misconfigured, and is using the same hostname as bar.com
Try to run an online certificate validation tool, like https://www.digicert.com/help/ on foo.net, just to be sure.
I think that you need to regenerate the certificate of foo.net with the right hostname, or reconfigure ngix to make sure that nginx serve the right certificate for the right host.

JSch: How to ssh into a server using ssh-keys

I want to ssh into a server from behind another ssh server. The gateway server requires a username/password and I can do this. I am using a tunnel to get into the next server, but this one requires only an ssh key. I've generated the key through PuTTY, so it exists for my username but I'm not sure how to retrieve it for my Java program. Is it a configuration? i.e. setConfig("userauth.publickey", "com.jcraft.jsch.UserAuthPublicKey") then how do I use this or something else? Documentation seems to be sparse and I appreciate any help. Anything I've tried gives me an error :"Auth fail" when I connect this session
Thanks!
The tunnel method I use is: http://sourceforge.net/apps/mediawiki/jsch/index.php?title=ProxySSH so thanks to the guy who wrote it!
For context, I'd like to read/write to a server at my school from my Android phone.
To enable public-key authentication, you have to use one of the JSch.addIdentity methods.
These take the public and private key in the OpenSSH key format - so make sure you export it from PuTTY in this format. (JSch doesn't understand PuTTY's native format, though you could write an adapter implementing the Identity interface, parsing it yourself).
The identities added to JSch are global, not per-session. This is normally not a problem, as JSch will try all authentication methods which are supported both by itself and the server in order, and public-key authentication is normally before password authentication.
All authentication methods need a user name (usually the name of the account to be logged into).
With public-key authentication, the public key must be somehow previously available to the server. For OpenSSH's sshd, the public key should be listed in ~/.ssh/authorized_keys. (If you have only one public key, simply copy it to this file, if you have multiple ones (each of which will be allowed), each should be on one line.)
So it should work out-of-the box after setting the identity.
If you want to make sure the first session uses password authentication and the second (tunneled) one uses public-key, you can use the per-session configuration, overriding the global one:
tunnelSession.setConfig("PreferredAuthentications", "password");
innerSession.setConfig("PreferredAuthentications", "publickey");
(These are comma-separated lists, here of one element each.)
About the ProxySSH example, that is by me (with some help by JSch's author, Atsuhiko Yamanaka). I should add this information to the Wiki page, maybe.

How to debug http calls on Android devices?

I'm writing a Lovefilm client for Android, and it's not going too badly except I keep having problems with the remote calls to retrieve data from the API.
Does anyone have any tips for debugging remote calls like this? Can I tcpdump on Android or is there a native way of doing it?
For example, I'm using the Scribe-java library for OAuth to access the Lovefilm API, I can authenticate find and retrieve a list of films on the users account fine when the device is running Gingerbread, but trying to retrieve the accessToken on Froyo causes a blank response & and apparent response code of -1, I'd like to be able to see what's going on under the cvers their.
Another example I'd like to be able to the raw http for is trying to run a search, I get and IOError that says "Received authentication challenge is null"
I've used Fiddler (http-proxy for debugging http calls) with the android emulator in these cases. Just start the proxy, and start the emulator with the correct proxy address (-http-proxy ).
Fiddler is the most useful option. On the emulator #Scythe answer will work, but on a real device you will need to set the proxy in the Apache Http Client. The following code will do that:
HttpHost proxy = new HttpHost("youripaddr", 8888);
params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
If you are using https, fiddler is not so useful. In that case can enable the build in logging support in Apache Http Client. The following code does that:
Headers only:
java.util.logging.Logger apacheHeaderLog = java.util.logging.Logger.getLogger("org.apache.http.headers");
apacheHeaderLog.setLevel(java.util.logging.Level.FINEST);
Headers & Wire:
java.util.logging.Logger apacheWireLog = java.util.logging.Logger.getLogger("org.apache.http.wire");
apacheWireLog.setLevel(java.util.logging.Level.FINEST);
Note that this will have to have a java.util.logging Handler configured at finest level and the default handler is configured to log to logcat, which will filter DEBUG (finest) entries by default.
If your system can share the wi-fi connection you should be able to route packets from any device through your system and then using wireshark you can get monitor your calls or get a tcpdump.
Also , and more importantly , it would be best if you log your network calls and responses as suggested by #Matthew
Windows 7 wi-fi connection sharing : http://www.winsupersite.com/article/faqtip/windows-7-tip-of-the-week-use-wireless-hosted-networking-to-share-an-internet-connection-wirelessly.aspx
Since I always run into similar troubles and it seems a lot of people having the same issues over and over again I wrote up a quick tutorial for debugging client-server communication by using netcat and cURL.
That of course only works for the simplified case that you always 'fake' on side of the connection.
For eavesdropping you can use tools like tcpdump or Wireshark. Which will definitely be easier if you're able to run the server instance directly on your local machine.
Stetho is a great tool from FB which helps in debugging android Apps. You can have access to local data and have a check on your network using this.
http://facebook.github.io/stetho/

Categories

Resources