Skip to content

Commit

Permalink
Remove support for API v3 and v4 (#79)
Browse files Browse the repository at this point in the history
* python: move v5 to src and delete v3

* python: remove v5 prefix from imports

* python: move v5 test files to src and remove v3

* python: remove version import handling from scripts and fix lint issues

* python: fix lint issues

* python: v5 unit tests and one integration test working

* fix analytics integration test and remove get_businesses

* python: test_refresh_example working for v5

* python: remove v3-specific code

* python: remove ApiConfig.version

* python: merge access_token_common into access_token

* python: delete ad_metrics_async_report

* python: move ad_metrics_async_report_common to src/ad_metrics_async_report

* python: ad_metrics_async_report working again

* python: remove user_me

* python: remove v3 raw option from unpack

* lint fixes for python, no more e2e tests for v3

* nodejs: move v5 to src and delete v3

* nodejs: adjust imports and jest mocks for v5 only code

* nodejs: alphabetize imports

* nodejs: remove get_businesses

* remove v3-specific code

* remove ApiConfig.version

* nodejs: merge access_token_common into access_token

* nodejs: remove ad_metrics_async_report

* nodejs: move ad_metrics_async_report_common to ad_metrics_async_report

* ad_metrics_async_report working again

* nodejs: remove user_me

* nodejs: lint fixes

* scripts: lint fixes

* bash: remove v3 and version-independent scripts

* bash: move v5 script into scripts directory

* remove more instances of v3 and v4 from README and other files

* update link to delivery metrics doc

* fix comment in help doc generator

* README: refer to v1.1 of this repo for v3/v4 code

Co-authored-by: David Chaiken <[email protected]>
  • Loading branch information
davidchaiken and David Chaiken authored Nov 1, 2022
1 parent 7b35b29 commit 60b6a2a
Show file tree
Hide file tree
Showing 150 changed files with 1,017 additions and 5,044 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Code that makes it easy to get started with the Pinterest API.

## Purpose

This repository has code that is intended to provide a quick start for working with the [Pinterest API v5](https://developers.pinterest.com/docs/api/v5/), and also supports [Pinterest API v3](https://developers.pinterest.com/docs/redoc/) plus [Pinterest Marketing API v4](https://developers.pinterest.com/docs/redoc/adtech_ads_v4/). Note that all newly-created apps should use [Pinterest API v5](https://developers.pinterest.com/docs/api/v5/) and (when necessary) [Pinterest Marketing API v4](https://developers.pinterest.com/docs/redoc/adtech_ads_v4/). There is currently python code that implements a number of use cases, JavaScript (nodejs) code with essentially the same functionality, and a bash script that demonstrates the OAuth authentication and authorization flow. Over time, we plan to add more demonstrations of API functionality and possibly additional languages -- likely Ruby and maybe Go or PHP.
This repository has code that is intended to provide a quick start for working with the [Pinterest API v5](https://developers.pinterest.com/docs/api/v5/). There is currently python code that implements a number of use cases, JavaScript (nodejs) code with essentially the same functionality, and a bash script that demonstrates the OAuth authentication and authorization flow.

This quickstart used to support Pinterest API version v3 and v4, but that code has been removed so that everyone can focus on v5. If you're interested in code that shows the differences between using v3/v4 and v5, see [version 1.1](https://github.com/pinterest/api-quickstart/releases/tag/v1.1) of this repo.

## Quick Start

Expand Down Expand Up @@ -47,7 +49,7 @@ This repository has code that is intended to provide a quick start for working w

## OAuth 2.0 Authorization

Access to Pinterest APIs via User Authorization requires following a flow based on [OAuth 2.0](https://tools.ietf.org/html/rfc6749). To learn about how to use OAuth 2.0 with the Pinterest API, check out the [Glitch-based tutorial](https://pinterest-oauth-tutorial.glitch.me/). For details regarding OAuth, please refer to our [v5 developer docs](https://developers.pinterest.com/docs/getting-started/authentication/) or [v3 developer docs](https://developers.pinterest.com/docs/redoc/#section/User-Authorization). The code in this repo demonstrates how to initiate the flow by starting a browser, and then handling the OAuth redirect to the development machine (localhost). The browser is used to obtain an authorization code, and then the code invoked by the redirect exchanges the authorization code for an access token.
Access to Pinterest APIs via User Authorization requires following a flow based on [OAuth 2.0](https://tools.ietf.org/html/rfc6749). To learn about how to use OAuth 2.0 with the Pinterest API, check out the [Glitch-based tutorial](https://pinterest-oauth-tutorial.glitch.me/). For details regarding OAuth, please refer to our [v5 developer docs](https://developers.pinterest.com/docs/getting-started/authentication/). The code in this repo demonstrates how to initiate the flow by starting a browser, and then handling the OAuth redirect to the development machine (localhost). The browser is used to obtain an authorization code, and then the code invoked by the redirect exchanges the authorization code for an access token.

An access token is used to authenticate most API calls. In general, access tokens are valid for relatively long periods of time, in order to avoid asking users to go through the OAuth flow too often. When an access token expires, it is possible to refresh the token -- a capability that the code in this repo also demonstrates.

Expand All @@ -62,9 +64,9 @@ Like users, most developers do not want to have to go through the OAuth flow too
The precedence order in this repo for obtaining an access token is: environment, file, execute the OAuth 2.0 flow.

Code that implements OAuth is available for each language in this repo. The location of the code is as follows.
* One bash script for each version of the Pinterest API provide complete examples: [bash/scripts/v3/get_access_token.sh](bash/scripts/v3/get_access_token.sh) and [bash/scripts/v5/get_access_token.sh](bash/scripts/v5/get_access_token.sh).
* In python, the version-independent code in [python/src/user_auth.py](python/src/user_auth.py) opens a browser and handles the redirect to obtain an authorization code. The version-dependent code to exchange the authorization code for an access token is in [python/src/v3/access_token.py](python/src/v3/access_token.py) and [python/src/v5/access_token.py](python/src/v5/access_token.py). These two files also implement access token refresh.
* In JavaScript, the version-independent code in [nodejs/src/user_auth.js](nodejs/src/user_auth.js) opens a browser and handles the redirect to obtain an authorization code. The version-dependent code to exchange the authorization code for an access token is in [nodejs/src/v3/access_token.js](nodejs/src/v3/access_token.js) and [nodejs/src/v5/access_token.js](nodejs/src/v5/access_token.js). These two files also implement access token refresh.
* A bash script that provides a complete example: [bash/scripts/get_access_token.sh](bash/scripts/get_access_token.sh).
* In python, the code in [python/src/user_auth.py](python/src/user_auth.py) opens a browser and handles the redirect to obtain an authorization code. The code to exchange the authorization code for an access token is in [python/src/access_token.py](python/src/access_token.py). This file also implements access token refresh.
* In JavaScript, the code in [nodejs/src/user_auth.js](nodejs/src/user_auth.js) opens a browser and handles the redirect to obtain an authorization code. The code to exchange the authorization code for an access token is in [nodejs/src/access_token.js](nodejs/src/access_token.js). This file also implements access token refresh.

## Security Notes

Expand All @@ -86,7 +88,6 @@ Code that implements OAuth is available for each language in this repo. The loca
* `scripts` are executable files that demonstrate one or more use cases.
* `src` contains code that is used by the scripts and that you can incorporate into your own applications.
* `tests` contains unit and integration tests.
* Code that is specific to versions of the Pinterest API is in subdirectories of `src` (in the case of python and nodejs) or `scripts` (in the case of bash). The two versions supported by this quickstart are v3 and v5.

## Code Conventions

Expand Down
2 changes: 1 addition & 1 deletion bash/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SCRIPTS=scripts/*.sh scripts/*/*.sh
SCRIPTS=scripts/*.sh
lint:
shellcheck $(SCRIPTS)

Expand Down
94 changes: 83 additions & 11 deletions bash/scripts/get_access_token.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,89 @@
#!/usr/bin/env bash

#
# This script uses curl, openssl, and some helper utilities to demonstrate how to
# use OAuth authentication with the Pinterest API.
#
# OAuth is version specific, so this script just calls the appropriate
# version-specific script, based on the PINTEREST_API_VERSION environment
# variable. More documentation is available in each version-specific script.
# To see the communications at any stage of this script, use echo to show the
# relevant variable. For example, echo "$REDIRECT_SESSION" to see the complete
# web browser session for the redirect.
#
: "${PINTEREST_API_VERSION:=v5}"
# Prerequisites: curl, openssl, base64, jq, grep, cut
#

# Get configuration from environment or defaults.
: "${REDIRECT_PORT:=8085}"
: "${PINTEREST_API_URI:=https://api.pinterest.com}"
: "${PINTEREST_OAUTH_URI:=https://www.pinterest.com}"
: "${REDIRECT_LANDING_URI:=https://developers.pinterest.com/apps/${PINTEREST_APP_ID}}"
REDIRECT_URI="http://localhost:${REDIRECT_PORT}/"

# Note that the application id and secrect have no defaults,
# because it is best practice not to store credentials in code.
B64AUTH=$(echo -n "${PINTEREST_APP_ID}:${PINTEREST_APP_SECRET}" | base64)

# Get the authorization code by starting a browser session and handling the redirect.
echo 'getting auth_code...'

# Specify the scopes for the user to authorize via OAuth.
# This example requests typical read-only authorization.
# For more information, see: https://developers.pinterest.com/docs/getting-started/authentication/
SCOPE="user_accounts:read"

# This call opens the browser with the oauth information in the URI.
open "${PINTEREST_OAUTH_URI}/oauth/?consumer_id=${PINTEREST_APP_ID}&redirect_uri=${REDIRECT_URI}&scope=${SCOPE}&response_type=code" &

# 1. Use netcat (nc) to run the web browser to handle the redirect from the oauth call.
# 2. Wait for the response.
# 3. Redirect using a HTTP 301 response to the landing URI.
REDIRECT_SESSION=$(nc -l localhost ${REDIRECT_PORT} 2>&1 <<EOF
HTTP/1.1 301 Moved Permanently
Location: ${REDIRECT_LANDING_URI}
EOF
)

# Cut the authorization code from the output of the web server, which includes
# the redirect URI with the authorization code.
AUTH_CODE=$(echo "${REDIRECT_SESSION}" | grep GET | cut -d ' ' -f 2 | cut -d '=' -f 2)

# Exchange the authorization code for the access token.
echo 'exchanging auth_code for access_token...'

# Execute the curl PUT command to exchange the authorization code for the access token.
# 1. Use basic authorization (constructed above) with the application id and secret.
# 2. Note that it is necessary to send x-www-form-urlencoded data.
OAUTH_RESPONSE=$(curl --silent -X POST --header "Authorization:Basic ${B64AUTH}" --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=authorization_code' --data-urlencode "code=${AUTH_CODE}" --data-urlencode "redirect_uri=${REDIRECT_URI}" "${PINTEREST_API_URI}/v5/oauth/token")

RESPONSE_TYPE=$(echo "$OAUTH_RESPONSE" | jq -r '.["response_type"]')
echo response_type: "$RESPONSE_TYPE"

# Parse the JSON returned by the exchange call and retrieve the access token.
ACCESS_TOKEN=$(echo "$OAUTH_RESPONSE" | jq -r '.["access_token"]')

# The scope returned in the response includes all of the scopes that
# have been approved now or in the past by the user.
SCOPE=$(echo "$OAUTH_RESPONSE" | jq -r '.["scope"]')
echo scope: "$SCOPE"

SCRIPT_NAME="${BASH_SOURCE[0]}"
# Demonstrate how to use the access token to get information about the associated user.
echo 'getting user data using the access token'
USER_RESPONSE=$(curl --silent -X GET --header "Authorization:Bearer ${ACCESS_TOKEN}" "${PINTEREST_API_URI}/v5/user_account")

# get the location of this script
# shellcheck disable=SC2164 # because the directory definitely exists
SCRIPT_DIR=$(cd "$(dirname "${SCRIPT_NAME}")"; pwd)
# An alternative for the above command is to use the OAuth2 bearer authentication
# that is built into curl. Replace these arguments:
# --header "Authorization:Bearer ${ACCESS_TOKEN}"
# with these arguments:
# --oauth2-bearer "${ACCESS_TOKEN}"

VERSION_SPECIFIC_SCRIPT="${SCRIPT_DIR}/${PINTEREST_API_VERSION}/get_access_token.sh"
echo running version specific script: "${VERSION_SPECIFIC_SCRIPT}"
exec "${VERSION_SPECIFIC_SCRIPT}"
# Parse the JSON response and print the data associated with the user.
ACCOUNT_TYPE=$(echo "${USER_RESPONSE}" | jq -r '.["account_type"]')
USERNAME=$(echo "${USER_RESPONSE}" | jq -r '.["username"]')
PROFILE_IMAGE=$(echo "${USER_RESPONSE}" | jq -r '.["profile_image"]')
WEBSITE_URL=$(echo "${USER_RESPONSE}" | jq -r '.["website_url"]')
echo '--- User Summary ---'
echo Account Type: "$ACCOUNT_TYPE"
echo Username: "$USERNAME"
echo Profile Image: "$PROFILE_IMAGE"
echo Website URL: "$WEBSITE_URL"
echo '--------------------'
100 changes: 0 additions & 100 deletions bash/scripts/v3/get_access_token.sh

This file was deleted.

Loading

0 comments on commit 60b6a2a

Please sign in to comment.