I am trying to generate an Oauth signature in order to authenticate an user in flickr.com from my android app.
According to the article in flickr.com, I have to send a signing request in order to get the signature. The hyperlink to the flickr.com guide page is:
http://www.flickr.com/services/api/auth.oauth.html#request_token
According to the post, I have to send a request like this to the flickr server in order to receive the signature key:
http://www.flickr.com/services/oauth/request_token
?oauth_nonce=89601180
&oauth_timestamp=1305583298
&oauth_consumer_key=653e7a6ecc1d528c516cc8f92cf98611
&oauth_signature_method=HMAC-SHA1
&oauth_version=1.0
&oauth_callback=http%3A%2F%2Fwww.example.com
I have send a request from my app, in the above mentioned format, but all I received is an error saying oauth_problem=parameter_absent&oauth_parameter_absent=oauth_signature.
My request code is:
HttpGet get = new HttpGet("http://www.flickr.com/services/oauth/request_token?oauth_nonce="+nonce+"&oauth_timestamp="+ts+"&oauth_consumer_key=****&oauth_signature_method=HMAC-SHA1&oauth_version=1.0");
Actually the problem is that, the url through which I am requesting for the signature is responding in a wrong way. Where it should return the signature, its asking for the signature.
The signing step is no request. You take the URI you have so far and transform it into the base string as seen in the documentation (URL encoding its parts and the like). The you use the HMAC-SHA1 algorithm witch takes the 2 parameters key and data. Use the base string as data and key
is the concatenated values of the Consumer Secret and Token Secret, separated by an '&'.
The value you get back from the algorithm (the signature) is then appended to your URI with
&oauth_signature={ALGORITHM_OUTPUT}
Using this new URI you can then request tokens.
If you think this is too much work, check out some Java OAuth library, e.g. scribe-java.
Related
Team,
I have an requirement like i have to support to my partner (third party) portal to call us directly by making api call with credentials from their browser.
e.g.) Partner portal browser makes AJAX Call with below:
URL ---> https://example.com/request
HEADER ---> user_id : foo
HEADER ---> password : mypasswd
payload ---> {
"request_time" : 2232876435,
"request_name" : "get_user_info",
...
...
}
And their browser/portal is accessible/used by untrusted users of theirs. So now problem is since the call is from the front end; end user easily can inspect the browser to see the network api calls along with credential we have given to our partner to authorise at our side.
So i am planning to give suggestion to partner by asking them to encrypt the payload and headers in their portal backend server and render the encrypted information in the portal like below.
Encrypt (payload) using mypasswd.
Encrypt (password) using request_time <NOW OPTIONAL TO PASS>
So now,
e.g.) URL ---> https://example.com/request
HEADER ---> user_name : foo
HEADER ---> password : ENCRYPTED<mypasswd> <-- OPTIONAL
payload ---> ENCRYPTED<
{
"request_time" : 2232876435,
"request_name" : "get_user_info",
...
...
}
>
So in our system we will decrypt payload with mypasswd retrieved for user_id foo. so if decryption is successful, then the request is from valid resource.
Now the end portal user cannot understand the request from browser inspection.
NOTES:
I can't suggest my partner to call from their backend.
From the request payload i can identify repeated same request through unique transaction id, so they can't resubmit the same request. Hence avoiding replay attack.
Questions:
Q1) Any flaw or suggestion on this solution?
Q2) Is it possible to identify the decryption using passphrase is success or not in java? I am new to encryption, so could you please share any code or link to achieve this?
yours thoughts much valuable to me.
TLDR:
References:
Basic encryption details
https://blog.storagecraft.com/5-common-encryption-algorithms/
https://www.veracode.com/blog/research/encryption-and-decryption-java-cryptography
https://gooroo.io/GoorooTHINK/Article/13023/The-difference-between-encryption-hashing-and-salting/2085#.W2L_KdgzZD0
Java Encryption
How to encrypt and decrypt String with my passphrase in Java (Pc not mobile platform)?
Java Security: Illegal key size or default parameters?
Identifying decryption is successful through this exception:
Given final block not properly padded
EDIT: I misunderstood the question. If the information is encrypted by the third party before it reaches the end-user then this approach is generally safe. Replay attacks are the main thing to look out for. If the request being made is idempotent then you don't really need to worry, but otherwise you might need to implement a short-lived database for used tokens along with an expiry time or something similar.
You are solving this problem the wrong way. Having the end user make this request to you on behalf of the third party is silly - if the request comes from their browser then by definition they control the information they are sending and the way it is sent. Encryption does nothing to solve this since the encryption logic is also client side.
The solution to this problem is to eliminate the end-user. The request should come directly from the third party to you. This might be from the end-user making a request to the third party API or it might not - it doesn't matter.
I am trying to get the list of devices from azure IOT by using JAVA REST API.
when I use this URL
https:iothubhostname/devices/?maxCount=5&api-version=2015-07-01
It's giving response as:
ErrorCode:IotHubUnauthorizedAccess;Unauthorized
Can you anyone help us, how to make this request as authorized request?
From the error message, we can know that there is something wrong with your authorization header. The following screenshot is my result:
Here is the http request details:
For how to generate Authorization header, please refer to this article. Here is a key snippet from the article:
{signature} An HMAC-SHA256 signature string of the form: {URL-encoded-resourceURI} + "\n" + expiry. Important: The key is decoded from base64 and used as key to perform the HMAC-SHA256 computation.
Hope this could help your.
I am trying to use the Google Maps API for getting location, and subsequently nearby places.
I am sending the encoded URL to the API, for example, if I search for "Las Vegas, Nevada" the URL sent to API is: https://maps.googleapis.com/maps/api/geocode/json?address=Las+Vegas%2C+Nevada&client=gme-XXXXXXXXXX&signature=xxxxxxxxxxxxx.
Here, clientID is fixed and does not change, but the signature is generated on the basis of the address "Las+Vegas%2C+Nevada", or whatever is searched.
Note that in the URL, the keyword, written as the address, is UTF-8 encoded (space replaced by '+', and comma by '%2C').
However, the URL for which the API performs the search after the request is sent is: https://maps.googleapis.com/maps/api/geocode/json?address=Las+Vegas,+Nevada&client=gme-XXXXXXXXXX&signature=zzzzzzzzzzzzz.
Note that the spaces are still encoded as '+' but there is a comma present in this URL instead of '%2C' which results in a different signature being generated by the API, as the signature is generated on the basis of address.
I'm getting the following error because of this:
"Unable to authenticate the request. Provided 'signature' is not valid for the provided client ID, or the provided 'client' is not valid.
The signature was checked against the URL: /maps/api/geocode/json?address=Las+Vegas,+Nevada&clientID=gme-XXXXXXXXXX&signature=zzzzzzzzzzzzz.
If this does not match the URL you requested, please ensure that your request is URL encoded correctly. Learn more: developers.google.com/maps/documentation/business/webservices/auth"
Why is the comma not encoded in the URL that Maps API is using?
And is there any way to resolve this issue?
Simply wrap each paramater in the following
URLEncoder.encode(VARIABLE_NAME, "UTF-8")
this will cause it to be sent "url safe"!
Example:
URL url = new URL("https://maps.googleapis.com/maps/api/geocode/json?address=" + URLEncoder.encode("Las Vegas, Nevada", "UTF-8") + &client=gme-XXXXXXXXXX&signature=xxxxxxxxxxxxx");
I recently got to know about Json Web Token (JWT). Since I liked how it works I have started to implement it on my project. My project involves two apps to communicate. One is an android app and the other is Laravel web application.
The mobile app logs in after the user credential is authenticated from the server side.
I have sent the username and password to server from the mobile app and I have got the JWT in string format. But from this point onward I couldn't find a way to collect the JWT content.
I have gone through almost all possible shown (googled results) but I couldn't manage to get the contents, signature and header.
One of the method I have got a little bit further with, was using the following code, notice I have removed the setSigningKey():
try {
Claims claims = Jwts.parser().parseClaimsJwt(jwtHeaderAndClaim).getBody();
System.out.println("ID of the claims: " + claims.getId().toString());
}catch (Exception e){
Log.e("Exception: ", e.toString());
}
The above code generates the following error:
Exception: io.jsonwebtoken.PrematureJwtException: JWT must not be accepted before 2016-06-14T10:20:09+0300. Current time: 2016-06-14T10:19:37+0300´
the jwtHeaderAndClaim is the JWT String after removing the signature part only (i.e: "xxxxxx.yyyyyyyy."). if i put the jwtString (xxxxxxx.yyyyyyyy.ccccccc) instead of jwtHeaderAndClaim the following error will occur:
Exception: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are not supported
If I put the setSigningKey as shown in stormpath example:
Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret())).parseClaimsJwt(jwtString).getBody();.
The above code will not work for two reasons:
1. I don't have the library
import javax.xml.bind.DatatypeConverter;
2. I don't know how to get the key.
But know that I don't need the key since this time I am trying to login and collect the user information's (like firstname, lastname, phone, etc), and the signature (token) so that the next time I send data to be stored to the server side I have the token to get access to the backend.
Can anyone please help me?
You have many questions. I try to answer some of them
io.jsonwebtoken.PrematureJwtException: JWT must not be accepted before
2016-06-14T10:20:09+0300. Current time: 2016-06-14T10:19:37+0300´
You are using nbf (not before) attribute in JWT. Do not use it (it is optional) or sets a range of validity given that the clocks of the devices will not be synchronized
From RFC 7519
The "nbf" (not before) claim identifies the time before which the JWT
MUST NOT be accepted for processing. The processing of the "nbf" claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the "nbf" claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a NumericDate value. Use of this claim is OPTIONAL.
Signed JWS
Exception: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are
not supported
Do you want to validate the signing key at client side or at server side?
If you use the JWT for authentication replacing user & password, and you are sending token in each request, you can validate the signature at server side.
If you want to validate the key on the app, do not use a symmetric key, because it could be a big vulnerability if it fell into the wrong hands. See. You can use and asymmetric key pair. Sign the JWT in server with the private key and validate on device with public key.
I don't have the library import javax.xml.bind.DatatypeConverter
String base64 = Base64.encodeToString(data, Base64.DEFAULT);
byte[] data = Base64.decode(base64, Base64.DEFAULT);
I don't know how to get the key.
Your key probably was generated on server side in this way
Key key = MacProvider.generateKey(SignatureAlgorithm.HS256);
byte data[] = key.getEncoded();
Make available the key data[] to client in the way you prefer. Using assymetric keys, you only need to make available the public key.
KeyPair keyPair = RsaProvider.generateKeyPair();
byte data[] = keyPair.getPublic().getEncoded();
A common SO question, but no specific solid answers.
My setup:
I have a website running on Classic ASP with backed DB. Unfortunately, no SSL Certs are available
I have an Android application that will send a Google Volley to request data from the site using a bespoke but simple API
Currently:
I am still in testing, privately, so currently I just access the site as such:
On the app, the user enters a UserId and Password once.
User navigates to a Fragment which is associated with a specific ASP Page which will return some data
A Volley is sent to /mysite.com/_api/apage.asp?m=md5hashhereabcdefghijk
The server searches user records for a matching hash (built on UserID+SALT+pass). On matching record, it uses the found userid as the User's ID
apage.asp does some sql queries and returns a JSON object
app receives this JSON response and parses.
The problem:
Anyone packet sniffing, or MITM, would be able to plainly see the URLs being accessed (and server responses) and be able to replicate the query via their browser. This is what I'm trying to stop. Any SALTs or secret keys in the app would be easily seen by decompiling the APK.
Issues:
I've read all sorts of different solutions, but none of which really fit my environment. I can't use ASP session variables (RESTful being stateless), I cant use HTTPS(SSL/TLS) as there are no Certs on the Server. I can't use an App-based password as this can be decompiled and easily seen.
I appreciate that you will never get something 100% secure, but can only make people disinterested in hacking a system, or not make it worth while.
Proposed solution:
I want some feedback/thoughts on the following proposed method:
Each request will have its own handshake to authenticate the app
This will go as such:
User opens app for the first time and enters UserID/Password. This will remain with the app until it is uninstalled (or logged out), but I intend to keep the user's app logged in
User navigates in the app to a Fragment that corresponds with a specific page on the server
Volley is sent with :
UserAgent HTTP header 'some value'
generate the same authentication hash for (userid+salt+pass)
encrypt this hash with a public key
one query string /apage.asp?q=abcdefghijk.... sent to server
server decrypts using its private key
server checks this hash as I do currently.
page returns plaintext JSON values (not encrypted)
The same problem happens here whereby a MITM or sniffer could replicate the URL and get the same information back
A Second Proposed Solution:
Would it be better with every request actually starting with a whole handshake?
App sends volley to server requesting a handshake (HELO)
Server gross error check with UserAgent HTTP Header
Server logs the timestamp and IP of the request and generates a unique random code
App receives this code and builds a new hash using that unique code as a Salt
App sends second volley to /apage.asp?m=MD5(UserID+UniqueCode+Password)
Server Gross error check with originating IP, timestamp+-tolerance (30 seconds between the two requests?), UserAgent Request Header.
APage.asp uses this hash to authenticate the request, providing previous steps have successfully passed.
APage.asp returns a JSON object, as requested.
Server flags the log of originating IP/timestamp as EXPIRED, or, just remove the record.
This initial step would make it a lot harder for a sniffer or MITM to replicate the URL calls, as A) Each request would have a randomly returned code B) each code/hash combo can only be used once.
The only thing I can think of is someone decompiles the App, and sees the method of handshake, so could try to replicate this. However, the username/password hash would never match as that is the only thing they cannot get from the hash (as it is salted with the random code)
Thoughts? Could it be improved with some RSA public/private key cryptography? Could I generate my querystring apage.asp?m=abcdeghi..., Generate an MD5 Hash of that, append onto the end, then encrypt before sending?
Many thanks in advance