Retrieving All User Wallets through Coinbase iOS SDK - ios

I've recently been experimenting with the Coinbase iOS SDK and I've been having issues retrieving a user's Ethereum, Litecoin and Bitcoin Cash balances and historic transactions. Currently, I've only managed to do this with Bitcoin, USD and EUR, which seems to be consistent with the behaviour of the demo app supplied by Coinbase.
I have configured an application on the Coinbase API Access page using OAuth2 and the generated client ID and secret are being used within the app.
The issue seems to stem from the fact that I modified the Coinbase iOS SDK to allow me to pass the account parameter as
‘all’. This, I had hoped, would allow me to view details of all user accounts (ETH, BTC, LTC etc.) however, I only get BTC, USD and EUR when calling ‘getAccountsList’ on the Coinbase object.
NSString *accessToken = [response objectForKey:#"access_token"];
Coinbase *client = [Coinbase coinbaseWithOAuthAccessToken:accessToken];
[client getAccountsList:^(NSArray *accounts, CoinbasePagingHelper *paging, NSError *error) {
for (CoinbaseAccount *account in accounts) {
// Only BTC, USD and EUR are in the accounts array at this point.
}
}];
This is surprising as the permissions request page correctly asks the user for all wallets, as you can see in the screenshot below:
I suspect a solution to this would be to use API keys, as you are able to specify exactly which accounts to grant access to. I plan to distribute the app however, so this technique should not be used.
Here is an example of the URL I am sending:
https://www.coinbase.com/oauth/authorize?response_type=code&client_id=CLIENT_ID_GOES_HERE&account=all&scope=balance%20transactions%20user&redirect_uri=com.example-name.example-app.coinbase-oauth%3A%2F%2Fcoinbase-oauth
Does anyone know how I can request access to all of a users accounts using OAuth and be able to retrieve details for each? Is the scope I defined incorrect in some way? The only alternative I can think of would be to request access one by one to each wallet and store individual access tokens. This wouldn't be a great user experience however.
Thanks!

Add the parameter
account=all
to the oAuth endpoint: https://coinbase.com/oauth/authorize?account=all&response_type=code.‌​..
Here are the details: https://developers.coinbase.com/docs/wallet/coinbase-connect/permissions
Coinbase Connect applications can request different access to user’s wallets. This access is defined by account parameter on OAuth2 authorization URL. Available options are:`
select - (default) Allow user to pick the wallet associated with the application
new - Application will create a new wallet (named after the application)
all - Application will get access to all of user’s wallets

I believe the iOS SDK is in need of an update. It still connects to old API version.
I'm using the original Coinbase SDK. No fork. in stead, next to the wallet:accounts:read scope, I also add ["accounts": "all"] as meta argument to the startAuthentication method.
AND. I am NOT using the getAccountList method, but instead the more general .doGet method with the api v2 accounts endpoint (so coinbase.doGet("https://api.coinbase.com/v2/accounts", parameters: nil) {(response, error) -> Void in
This gives me account info for all wallets. You do need to do some json processing on the response object in this case though.

First if you don't have one, you need to create an account on Coinbase
Then, please take a look first on the Coinbase digital api documentation, and I agree with you that it maybe easier to use the API to get data (if the target account is only your own personal account)
Because according to Coinbase:
API Key authentication should only be used to access your own account or merchant orders. If your application requires access to other Coinbase users’ accounts, do not use API Key. To securely access other Coinbase users’ accounts, use Coinbase Connect (OAuth2)
You have two possibilities:
USE API
Assuming user has grant wallet:accounts:read to the API key ( which allow you to List user’s accounts and their balances) according to the wallet permission documentation.
Once done, you may use the official wallet client libraries for iOS - coinbase is available through CocoaPods - by adding the following line to your Podfile: :
pod "coinbase-official"
USE OAuth2 PROTOCOL
According to this,
It is a slightly more complex integration than the API Key authentication method, but is more flexible. OAuth2 works well for web applications, as well as desktop and mobile apps.
You will find a lot of informations in the coinbase-connect integrating documentation, and you may also take a look on the official OAuth2 protocol website first.
Assuming you are OK with OAuth2, you will also have to ask user to grant you permission before requesting data.
As you need access to user wallet, you still have to request access token and add a scope parameter in the authorization request (Comma separated list of permissions (scopes) your application requests access to), if you need to see the full scopes list please refer yourself to this page.
The required scope is the same as API method: wallet:accounts:read, and your request will look like this:
GET https://www.coinbase.com/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URL&state=SECURE_RANDOM&scope=wallet:accounts:read
After a successful request, a valid access token will be returned in the response (like this):
{
"access_token": "6915ab99857fec1e6f2f6c078583756d0c09d7207750baea28dfbc3d4b0f2cb80",
"token_type": "bearer",
"expires_in": 7200,
"refresh_token": "73a3431906de603504c1e8437709b0f47d07bed11981fe61b522278a81a9232b7",
"scope": "wallet:user:read wallet:accounts:read"
}
Once you get the access token, you can make any API call corresponding to the previous scope if you add the following header to the request:
Authorization: Bearer 6915ab99857fec1e6f2f6c078583756d0c09d7207750baea28dfbc3d4b0f2cb80
Finally, you may refer to the API reference documentation to see all possible API call and the relative scopes.
To conclude, you need to grant permission, then list the user accounts, then you may get any account resource:
Account resource represents all of a user’s accounts, including bitcoin, bitcoin cash, litecoin and ethereum wallets, fiat currency accounts, and vaults.
Regards

Still no luck.
Tried with adding param account=all. It gave me access to all wallets (exactly same as op). However, in code, I can only get BTC Wallet, BTC Vault, EUR Wallet and newly created BTC Wallet. The new wallet was created by adding param account=new.
Tried with adding param account_currency=BTC,ETH and chose ETH Wallet on oAuth authorization. Did getAccountsList which returned 0 objects and no errors from the server.
Tried with revoking all API application access in my Coinbase account (Settings->Security).
Scope: balance transactions user
Endpoint: .../oauth/authorize?account=all&response_type=code&client_id=%...

Related

Unable to access users calendar using application daemon token

I have been trying to access a user's data using the MS graph API. I have been following the official documentation and I have correctly configured the apps and the permission.
I am also following this code_sample and using this I have been able to fetch the daemon token for the application.
Using the token I am able to successfully fetch the data against the following endpoint:
https://graph.microsoft.com/v1.0/users/204e3e4f-xxxx-xxxx-xxxx-509934e1
The data looks like:
{"#odata.context":"https://graph.microsoft.com/v1.0/$metadata#users/$entity","businessPhones":[],"displayName":"developers#outlook.com Tiwari","givenName":"developers#outlook.com","jobTitle":null,"mail":null,"mobilePhone":null,"officeLocation":null,"preferredLanguage":null,"surname":"Tiwari","userPrincipalName":"developers_outlook.com#EXT##webdevelopers.onmicrosoft.com","id":"204e3e4f-x-xxxxx-xxxxxxx-509934e14fa8"}
However, I can't fetch any more data than this. All the other endpoints throw a 401 Unauthorised exception even when I have checked all the Application permission for my app.
I am trying to hit the following endpoints for fetching calendar of the above user:
https://graph.microsoft.com/v1.0/users/204e3e4f-xxxx-xx-xxxxz-509934e14fa8/calendar
https://graph.microsoft.com/v1.0/users/204e3e4f-xxx-xxx-xxxxx-509934e14fa8/calendars
both of these give 401.
Can someone suggest if I am missing something. I even decompiled my jwt token and it clearly shows all the following scopes added:
"roles": [
"Schedule.ReadWrite.All",
"OnlineMeetings.Read.All",
"Mail.ReadWrite",
"OnlineMeetings.ReadWrite.All",
"User.ReadWrite.All",
"Calendars.Read",
"Mail.ReadBasic.All",
"Files.ReadWrite.All",
"User.Read.All",
"Schedule.Read.All",
"Files.Read.All",
"Organization.ReadWrite.All",
"Mail.Read",
"Calendars.ReadWrite",
"Mail.Send",
"Organization.Read.All",
"Mail.ReadBasic"
],
Please help.
To get access to calendar events you should call the following endpoint:
GET /users/{id | userPrincipalName}/events
The documentations for calendars is here: https://learn.microsoft.com/en-us/graph/api/user-list-events
From your comment on Chris Johnson's answer, you're using a personal account. App-only tokens won't work to access a personal account, and you shouldn't be able to even obtain one using a personal account, since there's no concept of an admin.
App-only requires an admin to consent, and when she does, she grants access to all resources in her tenant. Personal accounts are not in work/school tenants, so they aren't in scope. Even if you've added that personal account as a guest in the work/school tenant, their calendar is hosted outside of the tenant, and is off limits.

Getting full access to DynamoDB from my ios app using AWS Cognito Developer Identities

I have implemented a AWS Lambda function and used the gateway to return the fulling data:
var param =
{
IdentityPoolId: "actualIdentityPoolId",
Logins: {} // To have provider name in a variable
};
param.Logins["com.testing.userLogin"] = userId;
cognitoidentity.getOpenIdTokenForDeveloperIdentity(param,
function(err, data)
{
if (err) return fn(err); // an error occurred
else fn(null, data.IdentityId, data.Token); // successful response
});
So the identityId and token get sent back to the ios device. In my device I try to connect to an AWS DynamoDB table but access is denied. How do I use the identityId and token to gain access to the tables?
I have set up roles in IAM for Unauth which denies Dydnamo and Auth which gives access to the tables through its policies.
I am trying to implement authentication using: http://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html
I see there are two flows which are Basic and Enhanced. The documentation says most users will use the enhanced flow and that implements GetCredentialForIdentity.
How is that implemented in my ios code so that I can switch my role from unauth to auth and can access to dynamodb? How long will this access last? I would like to do this all in my ios code instead of using lambda or something else like that.
If your user is unauthenticated, then logs in you need to clear your credentials, and your 'logins' method should now return a properly updated logins map.
Here is the documentation to help you:
http://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html
Double check your DynanoDB Roles for authenticated access your DynamoDB resource. An example role for this are on the following page of the developer guide you referenced. The page is called "IAM Roles" and the last section is the important one: "Fine-Grained Access to Amazon DynamoDB".
Stick with your plan to use the Enhanced Authflow. It is recommended and makes less calls to authenticate (your users will appreciate this). Just make sure you mobile clients call GetCredentialsForIdentity from iOS.
From the Enhanced Authflow documentation further down your page:
The GetCredentialsForIdentity API can be called after you establish an identity ID. This API is functionally equivalent to calling GetOpenIdToken followed by AssumeRoleWithWebIdentity.
The AssumeRoleWithWebIdentity is the important piece that allows your user to assume the Role that gets access to the DynamoDB resource. Cognito will take care of the rest as long as you set up the Roles correctly within the Cognito console:
In order for Amazon Cognito to call AssumeRoleWithWebIdentity on your behalf, your identity pool must have IAM roles associated with it. You can do this via the Amazon Cognito Console or manually via the SetIdentityPoolRoles operation (see the API reference)

Widget LTI -> API Authentication

I am working on an LTI widget, that then needs to authenticate to the API to get additional information.
I'm struggling with trying to figure out how to process the API user authentication, and redirect back retaining the LTI information.
The request string that is returned looks like:
Array ( [x_a] => **********************
[x_b] => **********************
[x_c] => *********************************** )
The issue is that I have my PHP LTI script setup to only load if it meets the following condition:
if(!isset($_REQUEST['lis_outcome_service_url'])
|| !isset($_REQUEST['lis_result_sourcedid'])
|| !isset($_REQUEST['oauth_consumer_key'])
)
x_a is the user id, x_b is the user key .. what is x_c?
Any suggestions appreciated!
My answer is referring to the detailed topic on the IDKey Auth scheme for the Valence dev platform.
The part of the auth sequence you are referring to here is equivalent to the second stage of the sequence, just after the user has successfully authenticated themselves (when you chain on the back of an LTI launch like this, you know that the user driving the user-agent has already authenticated, because they wouldn't have otherwise been able to do the LTI launch) and the service sends back the long-lived user tokens to your service.
See steps 5 to 7 in the sequence notes, in the section called Using a third-party web application in the IDKey Authentication docs topic:
x_a={tokenID} – Unique ID associated with the long-lived token: the web application can provide this ID so that the service can precisely locate the web application/user context.
x_b={tokenKey} – Key associated with the long-lived token: the web application can use this as a key to generating session signatures.
x_c={tokenSig} – Token identity signature: the service joins (and delimits with an ampersand) the User ID (tokenID) and the User Key (tokenKey) to use as the base-string, and uses the Application Key as the key.
Note that you will need to use your Valence Application ID/Key pair in order to verify the token signature contained in x_c.
Remote plugins. Note that the Brightspace Remote Plugin service is a convenience service wrapper around LTI/external learning tools. The docs about Remote Plugins contain a fairly detailed walkthrough/sample that showcases a simple Python web-service Tool Provider implementation that receives a Brightspace LTI launch, and can turn around and use Valence API calls to get more information. You might find it useful to have a close look at that.

Instagram API: do scopes work with OAuth2 implicit authentication flow?

I'm making requests against the Instagram API from a mobile app. Currently, I'm just directing the user to the Instagram auth url and specifying the response type to be "access_token". Specifying this response_type is known as implicit auth.
Explicit auth: response_type=code
Implicit auth: response_type=access_token
I'm trying to get around needing to stand up a web service to facilitate explicit auth. This would be necessary because in explicit auth flow, the Instagram API needs to make a call to a redirect URL and pass in a "code" parameter. The code would then be used by my server-side code to make a final request to Instagram for an access token.
It's much more efficient for a mobile app to use implicit flow because no extra privately-maintained auth service needs to be stood up to handle it.
Instagram supports the following scopes:
basic - to read any and all data related to a user (e.g.
following/followed-by lists, photos, etc.) (granted by default)
comments - to create or delete comments on a user’s behalf
relationships - to follow and unfollow users on a user’s behalf
likes - to like and unlike items on a user’s behalf
When I make any other type of scope specification besides "basic", I get the following response when the user provides the credentials at the auth URL:
{"code": 400, "error_type": "OAuthException", "error_message": "Invalid scope field(s): basic+likes"}
Any combination of scopes other than "basic" gives the same response.
So, my question are these:
Is explicit auth required in order to specify scopes beyond "basic"??
Do I need to specify response_type=code in order for extended scopes to work?
Is this an Instagram limitation, or is it a limitation of OAuth 2.0?
Thanks in advance.
I just tried with implicit oauth flow with my client_id and scope=basic+likes and it worked. Replace the url below with your client_id and redirect_uri, and try.
https://instagram.com/oauth/authorize/?client_id=CLIENT_ID&redirect_uri=REDIRECT-URI&response_type=token&scope=basic+likes
May be Instagram is not allowing scope other than basic with new client accounts...
The answer here is that YES, scopes can be requested by implicit auth flow just fine. My problem was related to an OAuth component that I was using. The component was silently URL-encoding the value of the scope param, which was rejected by the Instagram auth endpoint. I updated the component (Xamarin.Auth) to accomodate a non-encoded scope param and issued a pull request.
Thanks to #krisak for providing a working URL that I could test.
So I had similar issues regarding the encoding of the + when trying to get permission for multiple scopes (basic, likes, comments). The solution I found was to use spaces between the individual scopes:
In the config/initializers/omniauth.rb file:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :instagram, 'TOKEN', 'SECRETKEY' , {:scope => "basic likes comments"}
end
Unfortunately starting from April 14th 2015 new clients cannot get access for any scope but basic. Official message could be found at the client configuration page:
Starting April 14th 2015, new clients need to request access to be able to post likes, follows, and comments. For more information please read the Developer Blog at http://developers.instagram.com.
The message refers following blog entry: http://developers.instagram.com/post/116410697261/publishing-guidelines-and-signed-requests
Instagram requires personal request to be sent to enable scopes for your application (client ID), but your app has to meet certain conditions described in the blog entry.
i have the same problem i found this solution and works fine
Go to Manage clients under instagram/developer. Then click edit under your app and uncheck Disable Implicit OAuth. It will now work as intended.
Instragram changed this for a reason though, so should probably think twice before going public with your app: http://instagram.com/developer/restrict-api-requests/
At this time, May 2015, YES.
As explained on instagram documentation about authentication:
The Instagram API uses the OAuth 2.0 protocol for simple, but
effective authentication and authorization. OAuth 2.0 is much easier
to use than previous schemes and developers can start using the
Instagram API almost immediately. The one thing to keep in mind is
that all requests to the API must be made over SSL (https:// not
http://).
You first need to register your app here and then, with CLIENT ID provided by instagram, you can do this request:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code
Where you have to put your client_id and redirect_uri.
Just for information, in redirect_uri field you can insert also
http://localhost
you must be add "+" between scopes like that is "basic+comments+follower_list+likes+public_content+relationships"

How to make API requests with an access_token for a Service Account

My end goal is to be able to retrieve place details from Google's API.
I need to do this as a Service Account, since this is kicked off as a background task on my server. Service Accounts require you to exchange a JWT (JSON Web Token) for an access_token. I finally got that working and am receiving an access_token. Phew.
Now however, I don't know what to do with this access_token.
The Place Details API says that the key parameter is required, but I don't have a key. Just an access_token. Using that value for key or changing the name of the paramater to access_token is not working.
Ultimately I need to be able to hit a URL like so:
https://maps.googleapis.com/maps/api/place/details/json?reference={MY_REFERENCE}&sensor=false&key={MY_ACCESS_TOKEN}
How do I use my Access Token to make a request to the Google Place Detail APIs?
Update 1
Still no success, but I thought I'd post the details of my request in case there's something wrong with what I'm submitting to Google.
I'm using the JWT Ruby library, and here are the values of my claim set:
{
:iss => "54821520045-c8k5dhrjmiotbi9ni0salgf0f4iq5669#developer.gserviceaccount.com",
:scope => "https://www.googleapis.com/auth/places",
:aud => "https://accounts.google.com/o/oauth2/token",
:exp => (Time.now + 3600),
:iat => Time.now.to_i
}
Looks sane to me.
Create the service account and its credentials
You need to create a service account and its credentials. During this procedure you need to gather three items that will be used later for the Google Apps domain-wide delegation of authority and in your code to authorize with your service account. These three items are your service account:
• Client ID.
• Private key file.
• Email address.
In order to do this, you first need a working Google APIs Console project with the Google Calendar API enabled. Follow these steps:
Go to the Google APIs Console.
Open your existing project or create a new project.
Go to the Service section.
Enable the Calendar API (and potentially other APIs you need access to).
You can now create the service account and its credentials. Follow these steps:
Go to the API Access section.
Create a client ID by clicking Create an OAuth 2.0 client ID...
Enter a product name, specify an optional logo and click Next.
Select Service account when asked for your Application type and click Create client ID.
At this point you will be presented with a dialog allowing you to download the Private Key as a file (see image below). Make sure to download and keep that file securely, as there will be no way to download it again from the APIs Console.
After downloading the file and closing the dialog, you will be able to get the service account's email address and client ID.
You should now have gathered your service account's Private Key file, Client ID and email address. You are ready to delegate domain-wide authority to your service account.
Delegate domain-wide authority to your service account
The service account that you created now needs to be granted access to the Google Apps domain’s user data that you want to access. The following tasks have to be performed by an administrator of the Google Apps domain:
Go to your Google Apps domain’s control panel. The URL should look like: www.google.com/a/cpanel/mydomain.com
Go to Advanced tools... > Manage third party OAuth Client access.
In the Client name field enter the service account's Client ID.
In the One or More API Scopes field enter the list of scopes that your application should be granted access to (see image below). For example if you need domain-wide access to the Google Calendar API enter: www.googleapis.com/auth/calendar.readonly
Click the Authorize button.
Your service account now has domain-wide access to the Google Calendar API for all the users of your domain, and potentially the other APIs you’ve listed in the example above.
Below is a description that uses a service account to access calendar data in PHP
The general process for service account access to user calendars is a follows:
• Create the Google client
• Set the client application name
• If you already have an Access token then check to see if it is expired
• If the Access token is expired then set the JWT assertion credentials and get a new token
• Set the client id
• Create a new calendar service object based on the Google client
• Retrieve the calendar events
Note: You must save the Access token and only refresh it when it is about to expire otherwise you will receive an error that you have exceeded the limit for the number of access tokens in a time period for a user.
Explanation of Google PHP Client library functions used:
The client object has access to many parameters and methods all of the following are accessed through the client object:
Create a new client object:
$client = new Google_Client();
Set the client application name:
$client->setApplicationName(“My Calendar App”);
Set the client access token if you already have one saved:
$client->setAccessToken($myAccessToken);
Check to see if the Access token has expired, there is a 30 second buffer, so this will return true if the token is set to expire in 30 seconds or less. The lifetime of an Access token is one hour. The Access token is actually a JSON object which contains the time of creation, it’s lifetime in seconds, and the token itself. Therefore no call is made to Google as the token has all of the information locally to determine when it will expire.
$client->isAccessTokenExpired();
If the token has expired or you have never retrieved a token then you will need to set the assertion credentials in order to get an Access token:
$client->setAssertionCredentials(new Google_AssertionCredentials(SERVICE_ACCOUNT_NAME,array(CALENDAR_SCOPE), $key,'notasecret','http://oauth.net/grant_type/jwt/1.0/bearer',$email_add));
Where:
SERVICE_ACCOUNT_NAME is the the service account email address setup earlier.
For example:’abcd1234567890#developer.gserviceaccount.com’
CALENDAR_SCOPE is the scope setup in the Google admin interface.
For example: ‘https://www.googleapis.com/auth/calendar.readonly’
$key is the content of the key file downloaded when you created the project in Google apps console.
$email_add is the Google email address of the user for whom you want to retrieve calendar data.
Set the client id:
$client-setClientId(SERVICE_CLIENT_ID);
Where:
SERVICE_CLIENT_ID is the service account client ID setup earlier.
For example: ‘abcd123456780.apps.googleusercontent.com’
Create a new calendar service object:
$cal = new Google_CalendarService($client);
Several options can be set for calendar retrieval I set a few of them in the code below, they are defined in the api document.
$optEvents = array('timeMax' => $TimeMax, 'timeMin' => $TimeMin, 'orderBy' => 'startTime', 'singleEvents' => 'True');
Get the list of calendar events and pass the above options to the call:
$calEvents = $cal->events->listEvents('primary', $optEvents);
Loop through the returned event list, the list is paged so we need to fetch pages until the list is exhausted:
foreach ($calEvents->getItems() as $event) {
// get event data
$Summary = $event->getSummary();
$description = $event->getDescription();
$pageToken = $calEvents->getNextPageToken();
if ($pageToken) { // if we got a token the fetch the next page of events.
$optParams = array('pageToken' => $pageToken);
$calEvents = $cal->events->listEvents('primary', $optParams);
} else {
break;
}
}
Get the Access token:
$myAccessToken=$client->getAccessToken();
Save the access token to your permanent store for the next time.
The language isn't important php, ruby, .net, java the process is the same. The api's console shows the Places API as supporting service accounts so it should be possible to access it.
As far as using the token please have a look at https://code.google.com/p/google-api-ruby-client/ code as the usage is clearly defined in the code repository. Doesn't make any difference if the access token is for a service account or a single user the process for using the token is the same. See the section titled "Calling a Google API" in the following link: https://developers.google.com/accounts/docs/OAuth2InstalledApp
The access token is sent in the http authorization header along with the request.For a calendar request it would look something like the following:
GET /calendar/v3/calendars/primary HTTP/1.1
Host: www.googleapis.com
Content-length: 0
Authorization: OAuth ya29.AHES6ZTY56eJ0LLHz3U7wc-AgoKz0CXg6OSU7wQA

Resources