Expo / React Native Basic Authorization - react-native

I'm new to React native and Expo, but started to write my own app on it, with the same backend i used with my Cordova app.
Unfortunately i hit a roadblock trying to recreate the btoa() function from browsers, that i use to authenticate users with Basic authorization.
No matter what i try, i can't seem to get the same result as i did with btoa. I tried researching the subject, but i can't find a solid answer what's the difference between Base64.encode() and btoa().
I know i'm doing something wrong. When i try out the post request with Postman, i get the correct Basic auth token with it. But when i do it in code with base64 encoding(tried multiple libraries), the result differs.
Example:
test#test.com:asdasd
in postman: "dGVzdEB0ZXN0LmNvbTphc2Rhc2Rhc2Q="
in app(to utf8, then base64): "W29iamVjdCBBcnJheUJ1ZmZlcl0="
Relevant part of my code:
const utf8_enc = utf8.encode(email+':'+password);
const b64_enc = base64.encode(utf8_enc);
console.log(b64_enc);
Used libraries:
Base64- https://www.npmjs.com/package/base-64
UTF8 - https://github.com/mathiasbynens/utf8.js
Please tell me why are the two different, and how can i recreate the Postman version.
Thank you!

Ok, I see what's happening now. If you follow the docs for that utf8 package, it won't import correctly in React Native. You can see that it's not imported correctly by trying to access decode() or version as both will give you undefined. I think the reason is because they don't support es2015 modules (see this rejected PR). This package will however work fine in Node.js or in the browser.
Oddly enough, you do have access to encode() when you import. It just doesn't do what you think it does. When you attempt to use encode(), all it actually returns is the string: [object ArrayBuffer]. In fact, no matter what string you pass to it, it'll always return the same result. Now if you use btoa() on this string (with or without UTF-8 conversion since there's no difference in this case), you will see that you get that same output in the browser: W29iamVjdCBBcnJheUJ1ZmZlcl0=
So, how to get around this?
If all you expect are extended ASCII strings, then you don't need to encode it in UTF-8 as they will all be within the valid character set. So you can just do:
base64.encode(email+':'+password);
However, if you anticipate supporting all Unicode characters, then you have a few options to convert that string:
Fork the utf8 package to have it support modules/exporting.
Copy paste the entirety of the utf8 source and put it in your own local library and export the functions.
Write your own UTF-8 encoder/decoder using the method suggested here which itself is from the MDN Documentation.
So there's a reference to a solution, here is the relevant encode part of the code from the MDN documentation turned into a function:
function utf8encode(str) {
return encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(
match,
p1
) {
return String.fromCharCode(parseInt(p1, 16));
});
}

Related

Why can't I read properties from a JSON cookie in express, when I see them in the console?

I have the following code in express middleware...
const cert = req.cookies.Thing
console.log(` cookie is`, cert);
console.log("We got a cookie! "+ cert.property_a);
but the console shows...
cookie is {"property_a":"blah","scope":"thing"}
We got a cookie! undefined
If it is there, why can't I access the property? I even tried the JSON.parse(JSON.stringify) hack but no luck.
This may be helpful, if the issue is because of lazy resolving like promise.
Can't access object property, even though it exists. Returns undefined
Looks like the answer is although it displays like a JSON object it is a string. I solved this by using Object.values. This showed me a bunch of commas and I realized it wasn't getting parsed as JSON. Still trying to figure that last part out.
Object.values(cert)

How to consume a graphql API with Vue

Pretty simple you'd think given the popularity of both, but I am encountering a few hurdles.
I am using scaphold.io to be able to quickly show off a working UI. That is, if Vue can interact with Scaphold.
I have investigated two resources:
https://github.com/kristianmandrup/vue2-apollo-scaphold
Which seems to be a Scaphold production. Tried it. Many, many vague bugs.
Then there is also:
https://github.com/Akryum/vue-apollo
But this is too much. I don't need a server, the server is on Scaphold.
I also tried building the whole thing up by using the tutorial on howtographql, but this one is also outdated.
Ideally I want to instantiate an as up to date Vue 2 app using (I guess) the npm vue-cli, then install only the required apollo (or whatever, but I guess apollo) add-ons that I need. The minimum.
Shouldn't be too hard, I'll figure it out eventually, but some help is more than welcome.
You can consume a graphql api using your favorite regular request module (ajax, fetch, axios). Take the scalphold docs for example, but in the callback do this.vueUserData = body.data.getUser;
instead of
console.log(JSON.stringify(body, null, 2));
(edited to add one gotcha I remembered: if you encounter a problem where the callback doesn't know that this is supposed to be the component, you can do var self = this before the request function, then reference self.vueUserData instead.)

Do not encode parameters in RestSharp

I am using RestSharp to access a RubyOnRails API.
As you might know, RoR likes when the parameters names are in the form model_name[property]. RestSharp, on the other hand, does not like it.
Fiddler says I send this to the server :
user%5Bemail%5D=user%40email.com&user%5Bpassword%5D=test
It looks like R# encodes both the parameters and values when it sends the data (unlike Curl, which looks like it encodes selectively).
While that's fine most of the time I guess, in this particular case, it makes the API return a 401 because it doesn't understand the parameters.
Is it possible to ask R# to not encode the request's parameters ?
Thank you !
Edit
Ok, in the R# sources, I found the method RestClient.EncodeParameters, so it looks like the parameter's name is always encoded. I guess I will have to fork it :(
Since RestSharp version 106.4.0 you can just use ParameterType.QueryStringWithoutEncode in request.AddParameter() function:
request.AddParameter("user_id", #"45454545%6565%65", ParameterType.QueryStringWithoutEncode);
I know this has already been answered, but I wanted to add this answer since it worked for me. There is an (albeit hacky) solution to this. Build your own uri for parameters that should not be encoded.
var uri = string.Concat("/path/to/your/api", "?paramThatShouldNotBeEncoded=", DateTime.Now.Date.AddDays(1).ToString("O"));
var restRequest = new RestRequest(uri, Method.GET);
In the RestSharp sources I found out that the parameters are always encoded (both the name and the value), so I guess that I will have to fork it if I want to add an additional parameter.
See this PR from the project site:
https://github.com/restsharp/RestSharp/pull/1157
However, as far as I can tell, it's not yet in a release on NuGet.
Update: probably doesn't work in most cases from comments.
I found an interesting solution... Just decode the parameters you want to pass in and restsharp will encode back to what it should be. For example, I have an api key that uses %7 in it and RestSharper further encodes it. I decoded the api key and passed that into RestSharp and it seems to work!
This solution worked for me
request.AddQueryParameter("sendEndDate", "string:data,something-else", false);
This is the function in the metadata of RestSharp.IRestRequest:
IRestRequest AddQueryParameter(string name, string value, bool encode);

no callback function in cross domain json file

i'm trying to use cross domain jsonp. i have done this before using the callback function in the json file from the other domain. i'm looking at an example json data file that google uses in one of its tutorials:
http://earthquake.usgs.gov/earthquakes/feed/geojsonp/2.5/week -- here obviously the callback function here is eqfeed_callback. in the json file i'm trying to use, there is no callback function that kicks everything off, there is just a bracket [. the file starts off like:
[{"Address":"4441 Van Nuys Blvd","City":"Sherman Oaks" ...
and ends like:
}]
what should i do? is there another way to get at the data without a callback function? i can't edit this file. it's a service that i have a subscription to.
thx.
If it's not your server, and the server doesn't support JSONP, there's no way you can force it to return jsonp. You could try adding ?callback=callback to your url to see if that convinces the server to wrap it in a callback, but if it doesn't, you're out of luck.
Well, almost. There is actually a really dirty hack that you shouldn't use, which is to override javascript's standard Array constructor to assign the contents of the array to a global variable. But that's pretty hideous and I strongly advise against it.
Better ask the maintainer of the service if they're willing to support JSONP. Or better yet, add a CORS header.

How to access Firefox Sync bookmarks without Firefox

Firefox 4 syncs bookmarks and other settings to a host run by mozilla.
How do I access my bookmarks there (without Firefox)?
Is there a documented API?
It seems https://developer.mozilla.org/en/Firefox_Sync should contain the neccessary documentation but all links except the first point to empty pages.
I found a script called weave.py here https://github.com/mozilla/weaveclient-python/blob/master/weave.py that is supposed to be able to access those bookmarks but it is unable to use my credentials. It seems to expect usernames without "#" characters.
Is there any documentation out there on how to access Firefox sync data. Preferably with examples.
Right now I don't even know the entry point to this supposed web service.
When I go to https://services.mozilla.com/ I can change my password and presumably remove everything.
If you look at https://wiki.mozilla.org/Services/Sync, I think that's the documentation you want. More detail is at https://wiki.mozilla.org/Labs/Weave/Sync/1.1/API.
Indeed, the username is sha1 + base32. Python code:
import base64
import hashlib
base64.b32encode(hashlib.sha1('myemail#gmail.com').digest()).lower()
The WeaveID returned by ID.get("WeaveID").username is indeed SHA-1 hashed and base32 encoded.
A nice way to do this in Java is to use Apache Commons Codec, which includes Base32 since version 1.5:
public String getWeaveID(String email) throws UnsupportedEncodingException
{
byte[] sha = DigestUtils.sha(email.getBytes("UTF-8"));
Base32 b32 = new Base32(64, new byte[]{ }, false);
return b32.encodeToString(sha).toLowerCase();
}