Giter VIP home page Giter VIP logo

simpleauth's Introduction

non-maintenance mode

I'm not actively maintaining this library due to lack of time. If you think you'd be up for taking it over as a new maintainer, please open a new issue and say so.

Build Status

This python module provides a simple authentication wrapper for a Google App Engine app.

Supported specs:

  • OAuth 2.0
  • OAuth 1.0(a)
  • OpenID

Supported providers out of the box:

  • Google (OAuth 2.0, deprecated)
  • Google+ (OAuth 2.0)
  • Facebook (OAuth 2.0)
  • Windows Live (OAuth 2.0)
  • foursquare (OAuth 2.0)
  • Twitter (OAuth 1.0a)
  • LinkedIn (OAuth 1.0a, deprecated)
  • LinkedIn (OAuth 2.0)
  • OpenID, using App Engine users module API

Dependencies:

  • python-oauth2. This is actually a library implementing OAuth 1.0 specs.
  • httplib2 (as a dependency of python-oauth2)

Links:

Install

  1. Clone the source repo and place simpleauth module into your app root or a sub dir. If you do the latter don't forget to add it to your sys.path.

  2. Get oauth2 lib (e.g. pip install oauth2 or clone the repo) and copy it over to your app root or a sub dir.

  3. Get httplib2 and again, copy it to your app root.

Usage

  1. Create a request handler by subclassing SimpleAuthHandler, e.g.

    class AuthHandler(SomeBaseRequestHandler, SimpleAuthHandler):
      """Authentication handler for all kinds of auth."""
    
      def _on_signin(self, data, auth_info, provider, extra=None):
      """Callback whenever a new or existing user is logging in.
      data is a user info dictionary.
      auth_info contains access token or oauth token and secret.
      extra is a dict with additional params passed to the auth init handler.
    
      See what's in it with e.g. logging.info(auth_info)
      """
    
      auth_id = '%s:%s' % (provider, data['id'])
    
      # Possible flow:
      # 
      # 1. check whether user exist, e.g.
      #    User.get_by_auth_id(auth_id)
      #
      # 2. create a new user if it doesn't
      #    User(**data).put()
      #
      # 3. sign in the user
      #    self.session['_user_id'] = auth_id
      #
      # 4. redirect somewhere, e.g. self.redirect('/profile')
      #
      # See more on how to work the above steps here:
      # http://webapp-improved.appspot.com/api/webapp2_extras/auth.html
      # http://code.google.com/p/webapp-improved/issues/detail?id=20
     
      def logout(self):
        self.auth.unset_session()
        self.redirect('/')
    
      def _callback_uri_for(self, provider):
        return self.uri_for('auth_callback', provider=provider, _full=True)
    
      def _get_consumer_info_for(self, provider):
        """Should return a tuple (key, secret) for auth init requests.
        For OAuth 2.0 you should also return a scope, e.g.
        ('my app/client id', 'my app/client secret', 'email,user_about_me')
    
        The scope depends solely on the provider.
        See example/secrets.py.template
        """
        return secrets.AUTH_CONFIG[provider]

    Note that SimpleAuthHandler isn't a real request handler. It's up to you. For instance, SomeBaseRequestHandler could be webapp2.RequestHandler.

  2. Add routing so that /auth/<PROVIDER>, /auth/<PROVIDER>/callback and /logout requests go to your AuthHandler.

    For instance, in webapp2 you could do:

    # Map URLs to handlers
    routes = [
      Route('/auth/<provider>',
        handler='handlers.AuthHandler:_simple_auth', name='auth_login'),
      Route('/auth/<provider>/callback', 
        handler='handlers.AuthHandler:_auth_callback', name='auth_callback'),
      Route('/logout',
        handler='handlers.AuthHandler:logout', name='logout')
    ]
  3. That's it. See a sample app in the example dir. To run the example app, copy example/secrets.py.template into example/secrets.py, modify accordingly and start the app locally by executing dev_appserver.py example/

## OAuth scopes, keys and secrets

This section is just a bunch of links to the docs on authentication with various providers.

Google

Multiple scopes should be space-separated, e.g. profile email.

Multiple callback URLs on different domains are awesomely supported. If you're running two versions of the app, say one on localhost and another on example.org, simply add all of the callbacks including host, port and protocol to Redirect URIs list on API Access tab.

userinfo endpoint is deprecated, use Google+ (googleplus) provider.

Facebook

Multiple Scopes should be comma-separated, e.g. user_about_me,email.

Full list of scopes: http://developers.facebook.com/docs/authentication/permissions/

Multiple callback URLs on different domains are not supported by a single app registration. If you need to test your app on say, localhost and example.org, you should probably register two different applications and use the appropriate set of key/secret: one for localhost, and the other for example.org.

Also, there's a Sandbox Mode checkbox on Facebook's app settings page. Make sure it's disabled for a public/live website. Otherwise, almost nobody except you will be able to authenticate.

LinkedIn OAuth 2.0

Scopes are space-separated, e.g. r_fullprofile r_emailaddress r_network.

See Member Permissions section for more details: https://developer.linkedin.com/documents/authentication#granting

Windows Live

Scopes are space-separated, e.g. wl.signin wl.basic.

Full list of scopes: http://msdn.microsoft.com/en-us/library/live/hh243646.aspx

Multiple callback URLs on different domains are not supported by a single app registration. If you need to test your app on say, localhost and example.org, you should probably register two different applications and use the appropriate set of key/secret: one for localhost, and the other for example.org.

LinkedIn OAuth 1.0a (deprecated)

Scopes are not supported. This is OAuth 1.0a.

Even though LinkedIn will not give you any error about improper callback URI, it'll always use the value set in app's settings page. So, if you have two versions, say one on localhost and another on example.org, you'll probably want to register two applications (e.g. dev and production) and use appropriate set of key/secret accordingly.

Twitter

Scopes are not supported. This is OAuth 1.0a.

When registering a new app, you have to specify a callback URL. Otherwise, it is considered as an off-band app and users will be given a PIN code instead of being redirected back to your site.

OpenID

For OpenID to work you'll need to set AuthenticationType to FederatedLogin in App Engines application settings. Beware of this issue if you enable FederatedLogin.

CSRF protection

You can optionally enable cross-site-request-forgery protection for OAuth 2.0:

class AuthHandler(webapp2.RequestHandler, SimpleAuthHandler):

  # enabled CSRF state token for OAuth 2.0
  OAUTH2_CSRF_STATE = True

  # ...
  # rest of the stuff from step 4 of the above.

This will use the optional OAuth 2.0 state param to guard against CSRFs by setting a user session token during Authorization step and comparing it against the state parameter on callback.

For this to work your handler has to have a session dict-like object on the instance. Here's an example using webapp2_extras session:

import webapp2
from webapp2_extras import sessions

class AuthHandler(webapp2.RequestHandler, SimpleAuthHandler):
  # enabled CSRF state token for OAuth 2.0
  OAUTH2_CSRF_STATE = True

  @webapp2.cached_property
  def session(self):
    """Returns a session using the default cookie key"""
    return self.session_store.get_session()

  def dispatch(self):
    # Get a session store for this request.
    self.session_store = sessions.get_store(request=self.request)
    try:
      # Dispatch the request.
      webapp2.RequestHandler.dispatch(self)
    finally:
      # Save all sessions.
      self.session_store.save_sessions(self.response)

  # ...
  # the rest of the stuff from step 1 of Usage example.

This simple implementation assumes it is safe to use user sessions. If, however, user's session can be hijacked, the authentication flow could probably be bypassed anyway and this CSRF protection becomes the least of the problems.

Alternative implementation could involve HMAC digest. If anything serious pops up (e.g. see this SO question) please submit a bug on the issue tracker.

Catching errors

There are a couple ways to catch authentication errors if you don't want your app to display a Server Error message when something goes wrong during an auth flow.

You can use webapp2's built-in functionality and define handle_exception(self, exception, debug) instance method on the handler that processes authentication requests or on a base handler if you have one. Here's a simple example:

class AuthHandler(webapp2.RequestHandler, SimpleAuthHandler):
  # _on_signin() and other stuff
  # ...

  def handle_exception(self, exception, debug):
    # Log the error
    logging.error(exception)
 
    # Do something based on the exception: notify users, etc.
    self.response.write(exception)
    self.response.set_status(500)

You can also define global (app-wise) error handlers using app.error_handlers dict (where app is a webapp2.WSGIApplication instance).

Another solution is, if you're using webapp2's dispatch method like in the CSRF snippet above, you could do something like this:

  from simpleauth import Error as AuthError

  def dispatch(self):
    try:
      # Dispatch the request.
      webapp2.RequestHandler.dispatch(self)
    except AuthError as e:
      # Do something based on the error: notify users, etc.
      logging.error(e)
      self.redirect('/')

Alternatively, you can also use App Engine built-in functionality and define error handlers in app.yaml as described in Custom Error Responses.

Lastly, if nothing from the above works for you, override _simple_auth() and/or _auth_callback() methods. For instance:

from simpleauth import SimpleAuthHandler
from simpleauth import Error as AuthError

class AuthHandler(webapp2.RequestHandler, SimpleAuthHandler):
  def _simple_auth(self, provider=None):
    try:
      super(AuthHandler, self)._simple_auth(provider)
    except AuthError as e:
      # Do something based on the error: notify users, etc.
      logging.error(e)
      self.redirect('/')

CONTRIBUTORS

Just submit a PR to this repo.

There are so many people contributed to this project (which is awesome!) but I seemed to have lost track of some of them to put a complete and up-to-date list. Though I try keeping all commits with their authors intact, or just mention people in commit messages.

If you want to be mentioned here please do send me an email!

CHANGELOG

simpleauth's People

Contributors

bekt avatar elsigh avatar jchu1 avatar kinkykate92 avatar markuso avatar michaelolson avatar obeleh avatar okigan avatar pceccato avatar singingwolfboy avatar x1ddos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simpleauth's Issues

Provide a function that lists supported providers

Here's how it currently works:

# Map URLs to handlers
Route('/auth/<provider>',
         handler='handlers.AuthHandler:_simple_auth',
         name='auth_login'),
Route('/auth/<provider>/callback', 
         handler='handlers.AuthHandler:_auth_callback',
         name='auth_callback'),

Nice tip from @erichiggins:

Perhaps a convenience function could be written that simply supplies a list of
supported providers from the app's config file/dict. Then folks could make the above
route expression(s) programmatically.


Moved here from https://code.google.com/p/gae-simpleauth/issues/detail?id=5

Support multiple oauth 'scopes'.

Google OAuth separates the users' email address from the rest of their profile information. In order to get it, you must request both scopes.
https://developers.google.com/accounts/docs/OAuth2Login#scopeparameter

Currently, simpleauth expects the scope to be a string/single value. It should allow a tuple or list then add all defined scopes.

Some refactoring may be required, since simpleauth sends a dictionary mapping of parameters to urllib.urlencode. A list of tuples is also valid for the 'query' parameter, and would be more appropriate in this case.
http://docs.python.org/library/urllib.html#urllib.urlencode

LinedIn2, beyond basic profile

Hi,

I cannot find any way to get data other than the default profile using LinkedIn2.

For example, if I choose the following scopes (space separated as prescribed by the linkedin api)

r_basicprofile r_emailaddress

the authentication screen correctly displays that the application is requesting the basic profile and the email but the 'data' argument of the '_on_signin' method only contains the basic profile, not the email.

This is true of any other scope that I tried.

Has anybody successfully obtained more than basic profile with LinkedIn2?

Thanks,
Eric

Possibly spare 1 URL fetch call during _on_signin

I'm thinking to make _get_<provider>_user_info() call optional. This way one could spare a URL fetch call when existing users sign in as their profile data have probably been already stored during some previous logins.

Additionally, this could make it easier for a backend profile fetch instead of doing it during the user facing request.

Would this be a good idea?

SimpleAuth redirection issue

I'm seeing the production site not redirecting properly back to itself after authentication with Twitter. It's showing a local domain instead of the production URL. Is there any special setup I'm missing in regards to Twitter? BTW, everything is working as expected on the local development setup.

support HTTP Basic Authentication for client authentication

Hi, crhym3

It seems that simpleauth supports using client_id / client_secret in the request-body for client authentication.

Howerver, OAuth 2.0 protocol says,

http://tools.ietf.org/html/rfc6749#section-2.3.1

Including the client credentials in the request-body using the two
parameters is NOT RECOMMENDED and SHOULD be limited to clients unable
to directly utilize the HTTP Basic authentication scheme (or other
password-based HTTP authentication schemes)

Please support the HTTP Basic authentication scheme for client authentication, especailly at token endpoint

A way to store users data in GAE db

It would be great if we can store user data in order to consume the provider APIs later.
I was thinking about a model like this one but I can't figure out how to implement it.

class User(db.Model):
provider = db.StringProperty(required=True) // example (Facebook user id)
id = db.StringProperty(required=True) // example (Facebook, Google...)
created = db.DateTimeProperty(auto_now_add=True)
updated = db.DateTimeProperty(auto_now=True)
name = db.StringProperty(required=True)
profile_url = db.StringProperty(required=True)
access_token = db.StringProperty(required=True)

Support Twitter REST API v1.1.

When attempting to authenticate via Twitter, the last lines fails with an error due to 'screen_name' not being present in uinfo.

    resp, content = client.request(
      'https://api.twitter.com/1/account/verify_credentials.json'
    )
    uinfo = json.loads(content)
    uinfo.setdefault('link', 'http://twitter.com/%s' % uinfo['screen_name'])

uinfo is actually an error message:

The Twitter REST API v1 is no longer active. Please migrate to API v1.1. https://dev.twitter.com/docs/api/1.1/overview.

It'd be great if simpleauth could be updated to support the new Twitter REST APi version.

handle error on _oauth2_request

Hi @crhym3

in some condition _oauth2_request return an error. I think better if code have handle for error :

 def _oauth2_request(self, url, token, token_param='access_token'):
    """Makes an HTTP request with OAuth 2.0 access token using App Engine
    URLfetch API.
    """
    target_url = url.format(urlencode({token_param:token}))
    #return urlfetch.fetch(target_url).content
    resp = urlfetch.fetch(target_url)
    if resp.status_code != 200:
        raise AuthProviderResponseError(
          '%s (status: %d)' % (resp.content, resp.status_code))
    else:
        return resp.content

thank you

Failing for Google+

Logging into Google+ from https://simpleauth.appspot.com/ fails with:

"ValueError: No JSON object could be decoded".

image

I get the same error when using SimpleAuth in my own project, stacktrace below.

Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in call
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in call
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in call
return handler.dispatch()
File "/base/data/home/apps/smigraine-view/9.382668147855496066/app/authentication.py", line 32, in dispatch
webapp2.RequestHandler.dispatch(self)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(_args, *_kwargs)
File "/base/data/home/apps/s
migraine-view/9.382668147855496066/libs/simpleauth/handler.py", line 179, in _auth_callback
result = meth(provider, *cfg[-1:])
File "/base/data/home/apps/smigraine-view/9.382668147855496066/libs/simpleauth/handler.py", line 279, in _oauth2_callback
auth_info = _parser(resp.content)
File "/base/data/home/apps/s
migraine-view/9.382668147855496066/libs/simpleauth/handler.py", line 580, in _json_parser
return json.loads(body)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/json/init.py", line 338, in loads
return _default_decoder.decode(s)
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/json/decoder.py", line 365, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/json/decoder.py", line 383, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

Support for OpenID Connect

Hi for basic authentication OpenID Connect is now required for endpoints such as the Azure V2 endpoint. Any plans to implement this in Simpleauth - I am using it for several customer facing Apps and it works very well.

With the need to support Office 365 user authentication I now need to implement OpenID Connect and it is a real shame to have to move to another libary.

Any thoughts?
All the best,
Ian

easy_install simpleauth fails

Reported by montsamu


(On Windows 7, install Python 2.7.3 and GAE 1.7.6, and easy_install 0.6c11)

C:\Python27>set PYTHONPATH=C:\Google\google_appengine

C:\Python27>python.exe
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', 'C:\\Google\\google_appengine', 'C:\\windows\\system32\\python27.zip', 'C:\
\Python27\\DLLs', 'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Pytho
n27\\lib\\lib-tk', 'C:\\Python27', 'C:\\Python27\\lib\\site-packages']
>>> ^Z

C:\Python27>Scripts\easy_install.exe httplib2
Searching for httplib2
Reading http://pypi.python.org/simple/httplib2/
Reading http://code.google.com/p/httplib2/
Best match: httplib2 0.8
Downloading http://httplib2.googlecode.com/files/httplib2-0.8.zip
Processing httplib2-0.8.zip
Running httplib2-0.8\setup.py -q bdist_egg --dist-dir c:\users\ibm_ad~1\appdata\
local\temp\easy_install-r3ah_h\httplib2-0.8\egg-dist-tmp-yb3tvi
zip_safe flag not set; analyzing archive contents...
httplib2.__init__: module references __file__
Adding httplib2 0.8 to easy-install.pth file

Installed c:\python27\lib\site-packages\httplib2-0.8-py2.7.egg
Processing dependencies for httplib2
Finished processing dependencies for httplib2

C:\Python27>Scripts\easy_install.exe oauth2
Searching for oauth2
Reading http://pypi.python.org/simple/oauth2/
Reading http://github.com/simplegeo/python-oauth2
Best match: oauth2 1.5.211
Downloading http://pypi.python.org/packages/source/o/oauth2/oauth2-1.5.211.tar.g
z#md5=987ad7365a70e2286bd1cebb344debbc
Processing oauth2-1.5.211.tar.gz
Running oauth2-1.5.211\setup.py -q bdist_egg --dist-dir c:\users\ibm_ad~1\appdat
a\local\temp\easy_install-ucqgeb\oauth2-1.5.211\egg-dist-tmp-jfe94s
Adding oauth2 1.5.211 to easy-install.pth file

Installed c:\python27\lib\site-packages\oauth2-1.5.211-py2.7.egg
Processing dependencies for oauth2
Finished processing dependencies for oauth2

C:\Python27>
C:\Python27>Scripts\easy_install.exe simpleauth
Searching for simpleauth
Reading http://pypi.python.org/simple/simpleauth/
Reading http://code.google.com/p/gae-simpleauth
Reading http://code.google.com/p/gae-simpleauth/source/checkout
Best match: simpleauth 0.1.4
Downloading http://pypi.python.org/packages/source/s/simpleauth/simpleauth-0.1.4
.tar.gz#md5=9d8d2c821d0a7c18ae2dce7af4f2c03a
Processing simpleauth-0.1.4.tar.gz
Running simpleauth-0.1.4\setup.py -q bdist_egg --dist-dir c:\users\ibm_ad~1\appd
ata\local\temp\easy_install-hrj9re\simpleauth-0.1.4\egg-dist-tmp-ekwtca
Traceback (most recent call last):
  File "C:\Python27\Scripts\easy_install-script.py", line 8, in <module>
    load_entry_point('setuptools==0.6c11', 'console_scripts', 'easy_install')()
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
1712, in main
    with_ei_usage(lambda:
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
1700, in with_ei_usage
    return f()
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
1716, in <lambda>
    distclass=DistributionWithoutHelpCommands, **kw
  File "C:\Python27\lib\distutils\core.py", line 152, in setup
    dist.run_commands()
  File "C:\Python27\lib\distutils\dist.py", line 953, in run_commands
    self.run_command(cmd)
  File "C:\Python27\lib\distutils\dist.py", line 972, in run_command
    cmd_obj.run()
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
211, in run
    self.easy_install(spec, not self.no_deps)
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
446, in easy_install
    return self.install_item(spec, dist.location, tmpdir, deps)
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
476, in install_item
    dists = self.install_eggs(spec, download, tmpdir)
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
655, in install_eggs
    return self.build_and_install(setup_script, setup_base)
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
930, in build_and_install
    self.run_setup(setup_script, setup_base, args)
  File "C:\Python27\lib\site-packages\setuptools\command\easy_install.py", line
919, in run_setup
    run_setup(setup_script, args)
  File "C:\Python27\lib\site-packages\setuptools\sandbox.py", line 62, in run_se
tup
    lambda: execfile(
  File "C:\Python27\lib\site-packages\setuptools\sandbox.py", line 105, in run
    return func()
  File "C:\Python27\lib\site-packages\setuptools\sandbox.py", line 64, in <lambd
a>
    {'__file__':setup_script, '__name__':'__main__'}
  File "setup.py", line 12, in <module>
ImportError: No module named simpleauth

Workaround of sorts is to easy_install pip, and then pip install simpleauth, which works.


pjdelport

Pull request: https://code.google.com/r/pjdelport-gae-simpleauth/

8b2c8e3428f7 should fix this, by using read() instead of import to get the version.


Moved here from https://code.google.com/p/gae-simpleauth/issues/detail?id=8

Simplify example/handlers.py AuthHandler._to_user_models_attrs

Here's how I did it.

def _to_user_model_attrs(self, data, attrs_map):
  """Get the needed information from the provider dataset."""
  user_attrs = {}
  for k, v in attrs_map.iteritems():
    attr = (v, data.get(k)) if isinstance(v, str) else v(data.get(k))
    user_attrs.setdefault(*attr)

  return user_attrs

The behaviour of urlfetch of Google App Engine will be changed from April 2015. Will it have any impact on simpleauth

Here is the content of the GAE announcement

"Dear URL Fetch users,

We’re contacting you because you’re listed as the administrator for your organization’s App Engine application, which uses the URL Fetch service. During the phased rollout of an update to this service, we determined that your application may be affected by the change described below.

Currently, the URL Fetch service preserves your original HTTP method (e.g., GET, POST) when it receives and responds to a 302 Moved Temporarily response. Modern user agents typically issue a GET request in response to a 302. After the update, URL Fetch will only issue a GET request after receiving a 302 response, rather than preserving the original method. This may cause requests to be routed differently and/or return 404s or other errors, and will drop the message body from POST requests.

To avoid being affected by this change, please verify that either:
Your app sends non-GET requests (such as POST) directly to the final URL that will handle the request rather than to one that redirects. Some common services, including App Engine, use 302 to redirect HTTP connections to HTTPS and vice versa, so it’s important to check that your protocol is correct as well. You can use the final_url field of the Response object (or a similar object in other APIs) to determine if your fetches are being redirected.
The destination server sends a 303 or 307 HTTP code, each of which specifies the redirect behavior with respect to HTTP methods, rather than a 302.

We will apply the update to your affected application’s URL Fetch usage on April 25, 2015.

If you have any questions, please contact our support team - even if you do not have a support contract.

Sincerely,
Google Cloud Platform team "

Change Google variable names in settings.py

Hi, thanks for providing this. I made a mistake that took me hours to fix, and I think a small change could make it easier for others. In secrets.py.template you have:

# Google APIs
GOOGLE_APP_ID = 'app id'
GOOGLE_APP_SECRET = 'app secret'

But Google calls these the client ID and client secret. The Google app ID is something else. I was inserting the Google app ID and not the Google client ID and thus it wasn't working. Please change these two lines to:

# Google APIs
GOOGLE_CLIENT_ID = 'client id'
GOOGLE_CLIENT_SECRET = 'client secret'

thanks!

Does not work with twitter

It seems that twitter login need some fix. I tried to figure out why it doesn't work but ....
You can actually verify the demo... :(

DeadlineExceededError: with google authentication

I'm getting:

DeadlineExceededError:Deadline exceeded while waiting for HTTP response from URL: https://accounts.google.com/o/oauth2/token

This stack overflow post explains.

"An invalid_grant is returned when the refresh token can't be used to get a new access token from the current user. This is happening to you because the stored Credentials object has a null refresh token, i.e.

credentials.refresh_token is None
True
As mentioned in the NOTE in How to make 'access_type=offline' / server-only OAuth2 operations on GAE/Python?:

If a user has already authorized your client ID, the subsequent times you perform OAuth for these users they will not see the OAuth dialog and you won't be given a refresh token.

You need to make sure your Credentials are stored with a valid refresh token and the easiest way to do this, as mentioned in your last question as well as in all 3 questions you linked to is to use approval_prompt=force when creating your OAuth2WebServerFlow or OAuth2Decorator object (whichever you are using)."

Loading modules from lib directory

@crhym3 In the installation instructions, is there any reason why the simpleauth could not be moved to the lib directory? I noticed the following line in the main.py but it seems to not bring in the modules from the 'lib' directory:

if 'lib' not in sys.path:
  sys.path[0:0] = ['lib']

Option to use stored tokens

Reported by muijsenbergq


Hi,

I'm using your library and i need to be able to use stored tokens and try to reuse them. As a separate path from the OAuth flow.

At the moment a hacked away a little bit to achieve this functionality but maybe it's an idea to implement this (the right way)?

This i my method to use existing tokens and tap into your library.
I made "get_consumer_info_for()" a class method,made it always return a 3-tuple and for the rest using the implementation from your demo.

def try_oauth(tokens):
    provider = tokens.provider
    client_id, client_secret, scope = AuthHandler.get_consumer_info_for(provider)
    fetcher = getattr(AuthHandler(), '_get_%s_user_info' % provider)
    auth_info = {'oauth_token': tokens.oauth_token, 'oauth_token_secret': tokens.oauth_secret}
    user_data = fetcher(auth_info, key=client_id, secret=client_secret)
    if user_data:
        auth_id = get_auth_id(user_data, provider)
        ....

btw, using this class to store tokens in db

class UserTokens(db.Model):
    created = db.IntegerProperty(required=True)
    provider = db.StringProperty(indexed=False, required=True)
    cookie = db.StringProperty()
    oauth_token = db.StringProperty(indexed=False, required=True)
    oauth_secret = db.StringProperty(indexed=False, required=True)
    user = ....

Thanks!

Moved here from https://code.google.com/p/gae-simpleauth/issues/detail?id=6

Occasionally sessions are empty

Very rarely (1 in 100 requests or so) an invalid session is set to the 'auth' cookie. The valid deserialized cookie looks like this: {u'_user': [5690665774088192, 1, u'0u48LYOY8mdVNf38bluT6n', 1407275076, 1407360509]}. And the invalid deserialized cookie looks like this: {}

This becomes the cookie for auth, and the users session cannot recover.

I have one theory, but its tenuous. By putting a try around the dispatch call in https://github.com/crhym3/simpleauth/blob/master/example/handlers.py that you may in some cases be invalidating the session? For instance an exception is fired before the session can be properly set?

Update setup instructions

Reported by guillermo


For this step
pip install simpleauth

You need to add the google app engine to your PYTHONPATH first, with a mac this would be

export PYTHONPATH=$PYTHONPATH:/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine

pjdelport

See issue 8: The fix in https://code.google.com/r/pjdelport-gae-simpleauth/ should resolve this issue too, and no longer require the SDK to be on the path for the install to work.


Moved here from https://code.google.com/p/gae-simpleauth/issues/detail?id=7

Example app Possible Enhancement

@crhym3 I have been playing with the SimpleAuth for a few days and I noticed that it uses a single User object for an individual user and links the additional social networks to this logged in user. I'm thinking about adding some functionality where I would like the first logged in account to be used when displaying the profile information instead of switching profiles every time user links an account. Thus, do you see this as a good addition to the SimpleAuth module?

Where can I get help

Is there a forum where I might be able to get some help? I have simpleauth working but on some machines, there are problems while on others all is well. Worse, I get no error logs anywhere I can find. I'm new to Python so there might be (probably is) something I just don't know about.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.