diff --git a/.gitignore b/.gitignore index edb4c63..c096ade 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ docs/_build/ target/ google.json fitbit.yaml + +# vim swap files +.*.swp diff --git a/README.md b/README.md index a39f655..abac786 100644 --- a/README.md +++ b/README.md @@ -20,17 +20,22 @@ Use `pip` to install the required packages, ### Fitbit Credentials -[Register a Fitbit application](https://dev.fitbit.com/apps/new). Note the client key and secret. +[Register a Fitbit application](https://dev.fitbit.com/apps/new) with: + * OAuth 2.0 Application Type: `Personal` + * Callback URL: `http://localhost:8080/` + * Default Access Type: `Read-Only` + * any values you want for application name, website, organization, and organization website +Note the resulting `OAuth 2.0 Client ID` and `Client Secret`. Run `auth_fitbit.py` to get credentials for read access to a user's data, - $ python auth_fitbit.py [FITBIT CLIENT KEY] [FITBIT CLIENT SECRET] + $ python auth_fitbit.py [FITBIT CLIENT ID] [FITBIT CLIENT SECRET] -This scripts open a browser window where you can log in to your Fitbit account and authorize the app to "access your profile and data". When you accept, the site will give you a string to copy and paste back into the script, which then writes the credentials to a local file named `fitbit.yaml`. +This scripts open a browser window where you can log in to your Fitbit account and authorize the app to "access your profile and data". When you accept, the script writes the credentials to a local file named `fitbit.yaml`. ### Google Credentials -[Create a project in Google Developers Console and enable the fitness API](https://console.developers.google.com/flows/enableapi?apiid=fitness). Create OAuth client ID with Other/Desktop type. Note the client id and client secret. +[Create a project in Google Developers Console and enable the fitness API](https://console.developers.google.com/flows/enableapi?apiid=fitness). Create an OAuth client ID with `Other UI` type and select `User data`. Note the client id and client secret. Run `auth_google.py` to get credentials for write access to a user's body data, diff --git a/auth_fitbit.py b/auth_fitbit.py index a1a591e..ac12dbb 100755 --- a/auth_fitbit.py +++ b/auth_fitbit.py @@ -1,78 +1,109 @@ #!/usr/bin/env python """ -This was taken, and modified from python-fitbit/gather_keys_cli.py, +This was taken, and modified from python-fitbit/gather_keys_oauth2.py, License reproduced below. -------------------------- -The MIT License +Copyright 2012-2015 ORCAS -Copyright (c) 2007 Leah Culver + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + http://www.apache.org/licenses/LICENSE-2.0 -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Example consumer. This is not recommended for production. -Instead, you'll want to create your own subclass of OAuthClient -or find one that works with your web framework. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. """ import os import sys +import threading +import traceback import webbrowser import yaml -from fitbit.api import FitbitOauthClient +from base64 import b64encode +import cherrypy +from fitbit.api import FitbitOauth2Client +from oauthlib.oauth2.rfc6749.errors import MismatchingStateError, MissingTokenError +from requests_oauthlib import OAuth2Session -def gather_keys(): - # setup - client = FitbitOauthClient(CLIENT_KEY, CLIENT_SECRET) +class OAuth2Server: + def __init__(self, client_id, client_secret, + redirect_uri='http://localhost:8080/'): + """ Initialize the FitbitOauth2Client """ + self.redirect_uri = redirect_uri + self.success_html = """ +
%s' % ('\n'.join(tb)) if tb else '' + return self.failure_html % (message, tb_html) + def _shutdown_cherrypy(self): + """ Shutdown cherrypy in one second, if it's running """ + if cherrypy.engine.state == cherrypy.engine.states.STARTED: + threading.Timer(1, cherrypy.engine.exit).start() + + +def main(): + if not (len(sys.argv) == 3): + print("Arguments 'client ID', 'client secret' are required") + sys.exit(1) + client_id = sys.argv[1] + client_secret = sys.argv[2] + + server = OAuth2Server(client_id, client_secret) + server.browser_authorize() + + credentials = dict( + client_id=client_id, + client_secret=client_secret, + access_token=server.oauth.token['access_token'], + refresh_token=server.oauth.token['refresh_token']) + yaml.dump(credentials, open('fitbit.yaml', 'w')) if __name__ == '__main__': - if not (len(sys.argv) == 3): - print("Arguments 'client key', 'client secret' are required") - sys.exit(1) - CLIENT_KEY = sys.argv[1] - CLIENT_SECRET = sys.argv[2] - - keys = gather_keys() - credentials = dict( - client_key=CLIENT_KEY, - client_secret=CLIENT_SECRET, - resource_owner_key=keys['oauth_token'].encode('ascii'), - resource_owner_secret=keys['oauth_token_secret'].encode('ascii')) - yaml.dump(credentials, open('fitbit.yaml', 'w')) + main() diff --git a/requirements.txt b/requirements.txt index 5f5c972..5a4e8d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,8 @@ -PyYAML==3.11 -fitbit==0.1.2 -google-api-python-client==1.3.1 -httplib2==0.9 -oauth2client==1.4.3 -oauthlib==0.7.2 -pyasn1==0.1.7 -pyasn1-modules==0.0.5 -python-dateutil==2.3 -requests==2.5.0 -requests-oauthlib==0.4.2 -rsa==3.1.4 -simplejson==3.6.5 -six==1.8.0 -uritemplate==0.6 -wsgiref==0.1.2 +oauthlib == 1.0.3 +google_api_python_client == 1.5.0 +cherrypy == 5.4.0 +python_dateutil == 2.5.3 +fitbit == 0.2.2 +httplib2 == 0.9.2 +requests_oauthlib == 0.6.1 +PyYAML == 3.11