How to use Stripe Connect in an iOS app - ios

Has anyone had success using Stripe connect with an iOS app. I have a few questions:
I'm following the guidelines here: https://stripe.com/docs/connect/getting-started
Registering an Application: easy, no problem here
Then a little further down:
Send your users to Stripe: again, easy no problem here, I just have a button that opens up the link in a UIWebView. I assume having the client_id in the URL is fine? A lot of my uncertainty is what IDs/keys I should hard-code into the app
Then a little further down:
After the user connects or creates a Stripe account, we'll redirect them back to the redirect_uri you set in yourapplication settings with a code parameter or an error.
What I'm doing here is using the UIWebview's webView:shouldStartLoadWithReqest:navigationType delegate method to check for the string "code=" in the URL. If it finds that, then I'm able to grab the "code" parameter. So in reality, the redirect_uri is completely unnecessary for me. Is this the right way to handle this? Should I be doing this within my app or on my server?
After receiving the code, we are supposed to make a POST call to receive an access_token. Again, should this be done within the app or on the Server? It requires the use of a secret_key, so I'm guessing server? And how do I send credit card information along with this token if the token needs to be sent to the server? I know how to obtain the card number, exp date, and CVV. But in terms of passing it to the server (with or without the token) is something I'm not sure of.
Then when it comes to actually writing PHP, Ruby, or Python code on the server, I'm at a total loss.
Any help would be greatly appreciated.

You should setup a small web app to create stripe charges and storing you customers Authorization Code. Configure two routes in your web app for redirect_uri and webhook_uri and add the url in your Stripe Apps settings. The charges should be created from a server side app because it requires the secret_key / authorization_code which should not be stored in an iPad app. Otherwise they may lead to a security leak. I'm trying to describe the concept below:
Provide the stripe connect button in your app and set the link to open in Safari (not in an web view). You should add a state parameter to the url with an id which is unique to your users.
On tapping the button your user will be redirected to Stripe where s/he will be asked to authorize your application. Upon authorization stripe will hit your redirect_uri with a authorization_code and the state you previously provided. Do a post call according to Stripe Documentation with the authorization_code to get an access_token. Store the access_token mapped with the state in a database.
Define a custom url scheme in your app. Invoke the custom url from your web app. The user supposed to open the url in mobile safari. So invoking the custom url will reopen your application. You can pass an additional parameter to indicate failure / success. In your app update the view based on this parameter.
Now you are all set to create a charge on your server on behalf of the iPad user. Use stripe iOS sdk to generate a card_token from the card information. It'll require your stripe publishable_key. Then define an api in your web app which takes 3 parameters: card_token, user_id and amount. Call this api from your iPad app whenever you want to create a charge. You can also encrypt this information with a key if you're worried about security using any standard encryption method. You can easily decrypt the info in your web app as you know the key.
When this api is called from the iPad app you'll receive the user_id (which you saved as state previously), card_token and amount. Retrieve the access_token mapped to the user_id (or state). You can then made a charge on behalf of the user using the access_token, card_token and amount.
You can use ruby / php / python / node in the server as Stripe provides sdk for them. I assume other languages can be used as well as there is a REST interface.
Please note that this is just a concept. It should work like it but I haven't implemented it yet. I'll update this answer with sample code when I'm done.

You can use UIWebView. You will still need to use redirect urls and monitor the redirect using the delegate "webView:shouldStartLoadWithRequest:navigationType:"

Related

Typo3: FE Login with POST Request to external app server

I recently started getting into Typo3 but now I have to implement something for work and I have no clue where to start.
The requirements:
I have to add a separate page that can only be accessed by frontend
users. (so far no problem)
These frontend users should be able to login with the same password
as they got for their iOS app. (uh-oh)
The separate page should display data from the app. (less of an uh-oh
but connected to the previous point)
After talking to the developer of the app, he made a specific POST request that can be used for the webpage. I am also getting a json-file with the required data that I need to display upon successful login.
My question lies with the login. How do I go about implementing this? I use the extension felogin to provide the login form on the page.
The POST request is looking sort of like this:
https://domain.at/api/queryMediaItems. It needs user and password, declared as user and pwd. In the body there should be a json object with the language, e.g.:
{"language":"de-at"}
You need to implement a SSO (SingleSignOn) as your users need to identify against the iOS-app.
This might give you a concept.
You also can look inside the code of some extension

Can BigCommerce Private Apps use OAuth

I am very confused by the BC documentation on their API, because they let you create "Draft Apps" (private apps) and now I see that in their documentation they say "We do not currently provide a means of keeping OAuth apps private.".
My concern here is that they made some changes recently that might have affected a few of my Private Apps that I had running just fine a month ago. If anyone can provide some insight, I would appreciate it greatly!
https://developer.bigcommerce.com/api/guides/oauth-transition
There is nothing wrong with creating oAuth credentials with a "Draft App" for the sole purpose of accessing the API of your store. You do not ever have to publish your app and your app will never be made "public" in that case. You also don't have to bother with the 'Load Callback URL' and filling out the details on your draft app, unless you want to provide yourself an interface in the store.
The "Draft App" function was specifically meant to allow Developers building apps for the BC App Marketplace to test their apps in a store before submission. However, you can use it to make a private application that is only intended for your store - I'm including the process here for others!
Making a Private App with oAuth (or How to Generate oAuth Credentials for a Store)
What you will need
Access to the account listed as the "store owner" of the store where you want to install your app or the ability to get a person with access to complete a couple steps
Ability to setup a local or public URL to receive the 'Auth Callback Request'
Getting started
The first thing you should do is sort out making available a local or public URL that can receive an "Auth Callback" request. This resource must be able to work over an HTTPS connection but the SSL can be self-signed. The 'Auth Callback' request from Bigcommerce is a GET request that will have 3 query parameters on the URL: code, scope, and context.
It is described in greater detail here:
https://developer.bigcommerce.com/api/callback#get-req
Additional info
When building a public app it is important that the service receiving the Auth Callback request be configured to catch the 3 query values and combine them with information you already have. You would then send all of this information in a POST to the BC oAuth Token service to generate your API token for the store. In addition to that you would want to respond to the Auth Callback request with a 200 status and an interface, or instructions, for the user.
In the context of building a private application you don't need to worry about any of that. All you need to do is capture the query values. If you have this already then go ahead and jump down to the section on generating an API token below.
Before Moving On
You should have a URL path that can receive a GET request and captures query parameters. Test it out and make sure it works. Here are a couple example URLs:
https://example.com/auth-callback
https://localhost:8000/auth-service
Registering an App
The key point here is that the registration of the app must be completed by the store owner account of the store where you want to install the app. If you have access to the store owner account credentials then follow the steps at the bottom of this page:
https://developer.bigcommerce.com/api/registration
If you are working with the store owner then you can direct them to complete the steps above. You will need to provide them the Auth Callback URL you created for completing Step 9. The Load Callback URL does have to be filled in but the default example provided can be left in place.
SCOPES
When registering an app you are able to choose the scopes for the app. It is simple to just leave them all open but it is best practice to only enable the scopes you need. Here is a list of the scopes:
https://developer.bigcommerce.com/api/scopes
If you are not sure whether or not you will need a certain scope then leave it enabled because you will have to re-generate your API Token (perform a re-install of the app) if you have to change the scopes on your app.
Before Moving On
You need to have the client_id and client_secret. If someone else registered the app then you will need to ask them for this. There is a View Client ID button that will provide it after registering an app.
Generate the Auth Callback Request
You will need the person with store owner access again for this step. They will need to login to their store and go to the Apps section on the left side column. After that click on Marketplace -> then My Apps (in the top-right) -> then My Draft Apps
You should now see a list containing any "apps" that the store owner has registered. Choose the one relating to the client_id you plan to use. Click to install the app.
The Auth Callback request has now been sent and you are done here. You should expect to see just a blank or grey page as a result unless you are responding to the Auth Callback request with content. Your app is now awaiting authentication.
If using a self-signed certificate
When your Auth Callback URL has a self-signed certificate then you will see a "untrusted cert" error in your browser when you attempt installation of the app. You should choose to trust the certificate and continue.
Before Moving On
You should now have received the code, scope, and context at your Auth Callback URL. If you did not it was likely due to not having SSL/TLS at your server. You can replay the Auth Callback request as many times as needed by Cancelling Installation of the app in the same place where you started it. You can even open up a Dev tool and watch the request happen to see what errors show up in the console. If this is continuing to fail then you should reach out to Bigcommerce support or ask a new question on here!
Generating an API Token to Complete Installation
Follow the steps here:
https://developer.bigcommerce.com/api/callback#post-req
You should have all of the details needed to send a POST request to the BC Auth Token Service at https://login.bigcommerce.com/oauth2/token
Make sure to URL encode your content and you should be good! Here is a site that can URL encode and decode for you: http://meyerweb.com/eric/tools/dencoder/
Just be careful of it encoding & and = signs when those are actually being used as separators between fields or between field/value (respectively).
Before Moving On
You should have received a successful response from the Auth service which will include your API Token. Once you have this you are all set to access the API of the store. You no longer need to have your Auth Callback URL up and available and can take that down.
Also take note of the context to use to create your API path.
Accessing the API
Now that you have your API Token and context you are all set to access the API of a store. Start off with a simple request to the /time endpoint.
Make a GET request and include the following headers (minus the curly braces):
X-Auth-Client: {CLIENT_ID}
X-Auth-Token: {API_TOKEN}
Accept: application/json
Content-Type: application/json
Send your request to a URL path of (minus curly braces):
https://api.bigcommerce.com/{context}/v2/time
If you get back a 200 response then you are all set!
Additional Notes - Ways to Break Credentials
Once you have successfully generated an API Token for a certain app, that app will display in the Control Panel as an icon in the Apps section. The fact the app is there shows it is installed and allowing access. If you uninstall that app then the previously generated API token will stop working.
Changing the scopes on an already installed app will require it to be re-installed to correct the token.
Changing the store owner email on the store will cause the token to stop working. The API Token is specifically tied to the store owner that registered the app.
if you have apps in "My draft apps" and you used basic oauth, you will have to change to Oauth Authentication, but if only have private apps using "legacy api account", you will not need to change.

iOS safely pass content between apps

I'm curious if there is a way to safely pass content between apps on iOS. The ultimate goal is to implement oauth between two ios apps.
Since apps are not guaranteed to have unique url schemes, this option is out.
I have considered using keychain groups, but do not have experience with this. It looks like an app needs to specify exactly which apps can access the keychain items.
Are there any other options? Is there some sort of identifier (such as android bundle ID) that can be used to verify the apps during a request?
You can use URL schemes for this.
The basic process
You'll have a ServerApp and many ClientApps. The ServerApp listens to an URL-scheme like serverapp://. The client then can make a call to the server to ask it for authentication. The client has to implement an URL-scheme too. E.g. ClientAppOne implements the URL scheme clientapp1://. The server takes as parameter a backlink to the client app. E.g. the client calls the URL serverapp://auth?back=clientapp1%3A%2F%2Fserverapp-auth (here the backlink is clientapp1://serverapp-auth and has been urlencoded).
The server then checks the users identity, asks him for permission, password, etc. and then uses the backlink to provide the data. How the backlink works exactly is application specific, but you usually need at least 2 parts: an access token and a username. E.g. a backlink will then be clientapp1://serverapp-auth?success=1&token=fi83ia8wfzi3s8fi8s3f8si8sf&user=robert or maybe in case of error clientapp1://serverapp-auth?success=0&errno=421. The client then needs to verify the accesstoken through some public (or private) API, e.g. https://serverapp.example.com/userdetails?apikey=fai83jw93fj93389j&token=fi83ia8wfzi3s8fi8s3f8si8sf. The server will return some structured response.
Necessary components
an URL scheme on the server App
an URL scheme on each client App
an SDK that is to be included into each client app and that handels the details of authentication, and a standard UI component (e.g. facebook has a standard button that says "login with facebook", so the ServerApp needs some re-recognizable button that says something like "login with ServerApp")
a server that provides services that can be accessed through the access token.
a defined API that explains how the client has to communicate with the server
an SDK to be included into the client that handels such client-server-communication (should be part of the SDK mentioned in component 3.)
maybe a wiki that documents all of the steps above, so that you and other developers dont lose track
a way to invalidate access tokens, and a way for the client to detect if an access token has been invalidated. furthermore, if the user changes his password, all access tokens should be invalidated.
Random notes
in your client app you can check if the serverapp is installed by calling [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"serverapp://auth"]].
the URL schemes should be sufficently collission-free. These URLs are never seen by users, only by developers, so they don't have to be beautiful. You can e.g. append the iTunes-Connect-App-ID to your URL-scheme, like serverapp1234567://. This will greatly reduce the possibility that someday some other app will use the same URL scheme.

Shopify Rails App - Querystring Spoofing

I'm developing a Shopify App with Rails and have been using the query-string to detect which shop is accessing it. This seems vulnerable as users could alter the url to access someone else's settings.
Here's an example:
I click on the preferences link on my app and get redirect to http://example-app.com/preferences?shop=example.myshopify.com and get a page of settings related to the the store: example.myshopify.com
So what's to stop the user from changing the querystring to http://example-app.com/preferences?shop=notmystore.myshopify.com and logging in to a store that they don't own?
Should I use an authentication gem (https://www.ruby-toolbox.com/categories/rails_authentication) and make each user create a username and password to prevent spoofing attacks?
Interesting. There were live production Shopify App store Apps that did what you did Paul. When I found an App like that, I informed Shopify and they promptly knuckle wrapped the App developer. He learned his lesson pretty quick and was hopefully very embarrassed.
Shopify Partner accounts (free to get) provide you with a nice API token and a corresponding secret for your App that you can use to ensure when you get a merchant trying to access your App that the incoming shop
is actually a shop that installed your App and,
they have the right to use your App
You should really check that out.
I found the solution is to always retrieve the shop url from your session variables and not from the query string:
session[:shopify].url
also make sure this is at the top of each of your controllers to ensure the shopify session exists:
around_filter :shopify_session
as shown in this: https://github.com/Shopify/shopify_app/blob/f9aca7dfc9c29350f7f2c01bb72f77a54ece2b77/lib/generators/shopify_app/templates/app/controllers/home_controller.rb
This question may be too localized, but I'll try to give you a direction.
If you are using the query string as the only authentication method, then yes, you will get hacked/spoofed, etc. You need to do some form of authentication. - Shopify provides an API that can probably handle some/most of this for you.
https://github.com/shopify/shopify_api

Soundcloud OAuth2 API: Getting invalid_scope error after user connection

I'm trying to implement Soundcloud connect and having a weird issue.
First thing I do is send my users to
https://soundcloud.com/connect?client_id=MY_CLIENT_ID&redirect_uri=http://myredirecturl.example.com&state=RANDOM_STRING&display=page&response_type=code&scope=email
When users connect they get redirected to
http://myredirecturl.example.com?error=invalid_scope&error_description=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed.&state=RANDOM_STRING
The same happens if I use scope=*.
However, if I use scope=non-expiring it lets me go through, but I need the users email and that type of scope doesn't have enough grants.
I thought it had something to do with my app being in development mode, but Osman at Soundcloud said it doesn't.
Thanks.
The 'email' scope is not available to all integrations. It's used for a few custom integrations that have provided us with accepted terms of service / privacy policies. There is no way to get a user's email address using the SoundCloud API.
You should however be able to use the '*' scope to get an expiring access token. I'll check with our app team to see why this is giving you an error. I'll edit my answer once I have more information there.
For your purposes, I would stay with the 'non-expiring' scope and simply prompt a user for their email address (providing them with a way to agree to your terms of use / privacy information).
Using scope=* sometimes doesn't work because the url is not properly encoded. If you are getting this error while using the * wildcard, try properly encoding the url, using a function like urlencode() (for PHP).

Resources