Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yahoo Fantasy Sports example using OAuth2

I'd like to build an application to query the data in my Yahoo! Fantasy league but can't make it past the 3-legged OAuth authentication and was hoping someone could give me a quick demo, or point me to a relevant tutorial.

I'm willing to use NodeJS, Python or PHP.

I've registered an API and gotten a Consumer Key and Consumer Secret.

Their documentation contains two PHP examples (that I couldn't get to work) and references OAuth.net's list of libaries.

But let's take Python. The rauth documentation only lists the first leg, how am I supposed to complete the other 2 legs?

from rauth import OAuth2Service

yahoo = OAuth2Service(  
client_id='mykey',
client_secret='mysecret',
name='yahoo',
authorize_url='https://api.login.yahoo.com/oauth/v2/request_auth',
access_token_url='https://api.login.yahoo.com/oauth/v2/get_token',
base_url='https://api.login.yahoo.com/oauth/v2/')

url = yahoo.get_authorize_url()

Almost all of the examples I found on GitHub.com are years old and have compatibility problems, although yahoofantasysandbox seemed almost there.

This tutorial recommens using fantasy-sports but I didn't see a lot of details on implementation or examples.

Can someone either point me in the right direction on this or give me a demo of working code?

like image 963
OrdinaryHuman Avatar asked Jan 14 '18 23:01

OrdinaryHuman


1 Answers

One year later I've managed to do this myself.

TL;DR: If you want to access the Yahoo Fantasy API just use this NodeJS tool I've created: https://github.com/edwarddistel/yahoo-fantasy-baseball-reader

If you want to create your own app in NodeJS or PHP however, here's how:

  1. Go to https://developer.yahoo.com/apps/create/, get a Consumer Key and Consumer Secret

  2. Put the Consumer Key into https://api.login.yahoo.com/oauth2/request_auth?client_id=YOUR-CONSUMER-KEY-GOES-HERE&redirect_uri=oob&response_type=code&language=en-us and Agree to allow access, then grab the authorization code

  3. Construct the Auth header, a Base64 encoding of CONSUMER_KEY:CONSUMER_SECRET:

const AUTH_HEADER = Buffer.from(`${CONSUMER_KEY}:${CONSUMER_SECRET}`, `binary`).toString(`base64`);
  1. Yahoo requires x-www-form-urlencoded, so if using an HTTP request library like Axios you'll need to stringify the data as per the docs

  2. Make a request to Yahoo. Here's an example:

function getInitialAuthorization () {
    return axios({
        url: `https://api.login.yahoo.com/oauth2/get_token`,
        method: 'post',
        headers: {
            'Authorization': `Basic ${AUTH_HEADER}`,
            'Content-Type': 'application/x-www-form-urlencoded',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
        },
        data: qs.stringify({
            client_id: CONSUMER_KEY,
            client_secret: CONSUMER_SECRET,
            redirect_uri: 'oob',
            code: YAHOO_AUTH_CODE,
            grant_type: 'authorization_code'
        }),
        timeout: 1000,
        }).catch((err) => {
            console.error(`Error in getInitialAuthorization(): ${err}`);
        });
}
  1. Take that response and write it to a file. You'll need those credentials to re-authorize the app every 60 minutes of usage.

  2. Make normal HTTP requests to the Yahoo API. Check the response, if the authorization token has expired, re-authorize using a slightly different set of parameters:

function refreshAuthorizationToken (token) {
    return axios({
        url: `https://api.login.yahoo.com/oauth2/get_token`,
        method: 'post',
        headers: {
            'Authorization': `Basic ${AUTH_HEADER}`,
            'Content-Type': 'application/x-www-form-urlencoded',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
        },
        data: qs.stringify({
            redirect_uri: 'oob',
            grant_type: 'refresh_token',
            refresh_token: token
        }),
        timeout: 10000,
    }).catch((err) => {
        console.error(`Error in refreshAuthorizationToken(): ${err}`);
    });       
}
  1. An example of making an API request and checking authorization:
// Hit the Yahoo Fantasy API
async function makeAPIrequest (url) {
    let response;
    try {
        response = await axios({
        url: url,
            method: 'get',
            headers: {
                'Authorization': `Bearer ${CREDENTIALS.access_token}`,
                'Content-Type': 'application/x-www-form-urlencoded',
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
            },
            timeout: 10000,
        });
        const jsonData = JSON.parse(parser.toJson(response.data));
        return jsonData;
    } catch (err) {
        if (err.response.data && err.response.data.error && err.response.data.error.description && err.response.data.error.description.includes("token_expired")) {
            const newToken = await refreshAuthorizationToken(CREDENTIALS.refresh_token);
            if (newToken && newToken.data && newToken.data.access_token) {
                CREDENTIALS = newToken.data;
                // Just a wrapper for fs.writeFile
                writeToFile(JSON.stringify(newToken.data), AUTH_FILE, 'w');
                return makeAPIrequest(url, newToken.data.access_token, newToken.data.refresh_token);

             }
        } else {
            console.error(`Error with credentials in makeAPIrequest()/refreshAuthorizationToken(): ${err}`);
            process.exit();
        }
    }
}

Here is an example in PHP:

function getInitialAuthorizationToken() {

    $ch = curl_init();

    $post_values = [
        "client_id" => $GLOBALS['consumer_key'],
        "client_secret" => $GLOBALS['consumer_secret'],
        "redirect_uri" => "oob",
        "code" => $GLOBALS['initial_auth_code'],
        "grant_type" => "authorization_code"
    ];

    curl_setopt_array($ch, array(
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_URL => $GLOBALS['auth_endpoint'],
        CURLOPT_POST => 1,
        CURLOPT_HTTPHEADER => array(
        'Authorization: Basic ' . $GLOBALS['auth_header'],
        'Content-Type: application/x-www-form-urlencoded',
        'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'),
        CURLOPT_POSTFIELDS => http_build_query($post_values)
    ));

    $answer = curl_exec($ch);
    if (isset($answer)) writeToFile($answer);

    if (!isset($access_token)) {
        echo "Error!";
        die;

    }
    else {
        return $token;
    }

}

Hope this helps others.

like image 65
OrdinaryHuman Avatar answered Sep 29 '22 12:09

OrdinaryHuman