I'm developing a Mac app that uses CloudKit as its back-end. Some of my users are requesting the ability to ingest and extract data via an automation/integration service such as Zapier. For this, I need to introduce a web API.
I am planning to use CloudKit Web Services to access the app's data. This data is user-specific and hence, resides in a private database. As a result, CloudKit requires user authentication as described here.
Essentially the user needs to be redirected to an Apple-hosted authentication page. After successful authentication, an authentication token is provided that can be used for data operations. Similar to how OAuth2 works, but different enough to not work with Zapier's (or probably any other similar services) supported authentication schemes.
Who has done something similar? What are my options? I want to keep things as simple as possible and make my web API's implementation as thin as possible.
Thanks.
Niels
This is definitely doable and you are on-track with your thinking. Here's how I envision it working:
You could do all of this with a front-end web app (no server-side app needed). I personally prefer Vue.js but you probably have something in mind already.
Your app will need to authenticate the user to CloudKit using the flow you mentioned. I highly recommend you use the Web Services API and not try to wrestle Apple's neglected CloudKit JS API. For this, you are going to need to generate an API token in the CloudKit Dashboard.
You app would then prompt the user to authenticate to Zapier.
You should now have user credentials for both CloudKit and Zapier in place in the user's browser cache (you can save, for example, the CloudKit token to sessionStorage and likewise with Zapier).
Make API calls to Zapier, pull down the data, and then save it to CloudKit all within your JS app. It's all API transactions at this point. I'm a fan of Axios for making the HTTP requests.
If you are downloading files, transacting huge amounts of data, or doing processor-intensive stuff, you might consider using a server for that work. But if you just need a place to pull and push reasonable chunks of data, I see no reason why you can't do it all in a front-end app.
Alternatively, if you don't want a web app at all, and want to only have the user work in the Mac app, that can be done, too. Just make API calls directly to Zapier from within your Cocoa app. Whether or not this is feasible depends some on how you want it to work.
If you have more specific questions or need help with any of the implementation details, feel free to add a follow-up comment or ask a new question.
Good luck!
I think the other answer is mostly correct. I don't know much about CloudKit, but we can talk through what you'd need for it to work.
Let's say you had a simple iOS app that stored contacts. On the iOS side, Apple presumably abstracts the upload and download operations.
If you wanted to make a web viewer for synced contacts using CloudKit, you'd need an endpoint to fetch all rows belonging to the authenticated user (each of which would have a UUID, name, and a phone number). I believe that's possible with CloudKit code Apple provides (but let me know if I'm off base).
Now, we want to integrate with Zapier. Say, a "New Contact" trigger. You make some sort of authenticated HTTP request from Zapier to Apple on behalf of an authenticated user. It gives back a list of contacts and Zapier can trigger on the ones it hasn't seen before. To do that, Zapier needs some sort of user token.
That's where the little front-end page the other answerer mentioned comes into play. If you've got a web page that can surface a user's token to them, they can paste it into Zapier and all of the above becomes possible. I'm not sure what the lifespan of the token is, but hopefully it can be automatically refreshed as needed (rather than the user needing to take any manual action).
I'm not sure if what I've described is possible, but do let me know if it is. It would be huge if it were possible to integrate Zapier and the iOS ecosystem!
Edit to respond to comments:
Zapier won't be able to interact with CloudKit in a way sufficient for me (some minor business logic is needed)
I'm not sure what that entails for you, but it's common to put logic in the Zapier integration to structure data in a way Zapier expects. There's a full Node.js execution environment, so the sky's the limit here.
I don't think Zapier can authenticate against CloudKit as it uses a non-standard authentication scheme
Once you've got a user's token (described above, which is unusual), you will almost certainly be able to use it in requests to cloudkit. Zapier provides a "custom" authentication scheme which lets you do basically anything you want. So unless Apple uses something that fetch can't handle (unlikely), it should be fine (once you get the token).
I would like to push data directly from my app into Zapier and have it done whatever magic the user has configured
This is also probably possible. Zapier ingests data in two ways:
polling, where Zapier frequently makes a web request, store the IDs of items we've seen before, and act on the new ones. You can read more about that here. Assuming you can work your business logic into the integration, this is doesn't require an external server besides Apple's
webhooks, where Zapier registers a subscription with you and you send new data, on demand, to that address. This would probably require a webserver on your end to handle. It's optional though - you can do polling instead.
Hopefully this cleared it up a bit. Feel free to reach out to partners#zapier.com and reference this question to talk more about it.
As a beginner I have a few questions that I would like to ask. I am working on an iOS project which is going to be consuming API's such as Twitter and Instagram. I mainly do this to learn how to work with APIs, learn working with HTTP, learn some libraries like Alamofire etc. and at the same time get more familiar with Swift and UI building in iOS in general.
My specific question is about my consumer keys (in this case from Twitter). Similar questions were asked in a lot of places and I have researched them as well, but I couldn't find a definitive answer.
Obviously, I don't want my client secret and client key to be visible in my code and in my github page. I have read about using environment variables for this, but (although I'm not that experienced in all this) it sounds like the secret is still "shipped" with the app, and could be decompiled in some way.
In short, how should I handle the keys and secrets? If I manage to store it safely somewhere and access it from within my code, will someone still be able to see the key and the secret from the HTTP requests being sent to the key provider (e.g. Twitter in this case)?
Also, a small side question is about the callback URL rules I've seen at Twitter (here), where if you use a URL scheme for your app, they require you to use something like this:
myURLScheme-CONSUMERKEY://
How sensitive is the consumer key compared to the secret? Is it safe to use this in the safari view to redirect a user back to the app? Could it be interrupted/stolen by the users of the app?
I hope the question is clear. All remarks and suggestions are really welcome.
Wanted to give to Siesta a try and I've started using it within a side project.
I was wondering if any of you have got any advice about storing the login credentials (either username+psw or just the token) and how these have been integrated within the API structure proposed by Siesta.
Did you simply use the KeychainItemWrapper? Something else worth sharing?
Thanks ;)
Folks,
Designing an ios application, and would like to confirm my strategy. There is a database (dynamo/mongo/etc) i am building up, which the app needs to make use of. Is it smart to front the database with an API, and have the ios app authenticate against the api.
This way the app makes calls to the api instead of directly to the database?
Would you suggest node.js be a good place to start crafting the web api with?
Thanks!
Yes, access the data via an API. Whether fancy authentication is needed, depends on what is stored in your database, and what your application is designed to do. Here is one resource (among millions) on API design: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
Also, here is a popular networking library for iOS: https://github.com/AFNetworking/AFNetworking
As for what technology to use, that too open ended and you will get 10 answers for every technology available. This should help though: https://softwareengineering.stackexchange.com/q/154519/44948
It's now trivial to create a web app that sits atop Parse.com. Now that I have this webapp, I want to expose parts of it to other developers via an oauth accesible api. So, they can develop an app that lets my site users 'give them permission' via oauth and they can now access the api.
How would I start going about doing this?
Update: After #Mubix response, I felt the following clarification would help
Currently I am accessing Parse from the server via a REST api, to get around any javascript security issues re:api keys etc. So, the api would be served of a server other than Parse. Also, the server code is in javascript / nodejs. I came across https://github.com/jaredhanson/oauth2orize which seems a likely candidate, was wondering how others are doing it and if anyone has actually gone a further step and integrated Parse access.
Hmmm .. Intereesting question!
Legal:
First of all their ToS doesn't seem to prohibit what you are trying to do but you should read it carefully before you start.
Implementation:
While parse doesn't provide feature to build your own APIs you could implement something yourself. You could treat the third party developers as users of your app. And you can use the ACL to control access.
Problems:
I don't see any way to implement oAuth entirely within parse.
How will third party apps access your API? Ideally you would like them to use a REST interface but with the parse.com REST API you won't be able to manage access to different parts of your data.
Conclusion:
It seems like too much trouble to implement the API entirely within parse. I would suggest that you write a thin API layer that takes care of auth and uses parse as the backend. You can use one of the service side libraries available for parse. eg. PHP Library, Node Parse.