forked from navdeep-G/flask-googlefed
-
Notifications
You must be signed in to change notification settings - Fork 1
/
flask_googlefed.py
107 lines (79 loc) · 3.11 KB
/
flask_googlefed.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# -*- coding: utf-8 -*-
"""
flask-googlefed
~~~~~~~~~~~~~~~
This module contains the Google Federated Authentication extension for Flask.
"""
import os
from functools import wraps
from flask import (
Blueprint, session, request, _request_ctx_stack, redirect,
url_for, g)
from flask_openid import OpenID
# Just a little context.
current_dir = os.path.dirname(__file__)
class GoogleAuth(object):
"""Google Federated Authentication manager.
If ``install==True`` (default), it is automatically installed into the
given Flask application.
"""
def __init__(self, app, install=True, prefix=None, name='GoogleAuth'):
self.app = app
self.app.config.setdefault('GOOGLE_DOMAIN', None)
self.oid = OpenID(self.app)
self.url_prefix = prefix
self.name = name
self.blueprint = self._get_blueprint(self.name)
self.domain = self.app.config.get('GOOGLE_DOMAIN')
self._login = self.oid.loginhandler(self.__login)
self._create_or_login = self.oid.after_login(self.__create_or_login)
if install:
self.install()
def _check_auth(self):
"""Returns True if authentication is valid."""
return ('openid' in session) if self.domain else True
def __login(self):
return self.oid.try_login('https://www.google.com/accounts/o8/site-xrds?hd=%s' % self.domain)
def _before_request(self):
g.user = None
def __create_or_login(self, resp):
"""This is called when login with OpenID succeeded and it's not
necessary to figure out if this is the users's first login or not.
This function has to redirect otherwise the user will be presented
with a terrible URL which we certainly don't want.
"""
session['openid'] = resp.identity_url
return redirect(self.oid.get_next_url())
def _logout(self):
session.pop('openid', None)
return redirect(self.oid.get_next_url())
def _get_blueprint(self, name):
return Blueprint(
name,
__name__,
static_folder=os.path.join(current_dir, 'static'),
template_folder=os.path.join(current_dir, 'templates'),
)
def _configure_routes(self):
self.blueprint.route('/login/', methods=['GET', 'POST'])(self._login)
self.blueprint.route('/logout/', methods=['GET', 'POST'])(self._logout)
def _register_blueprint(self, **kwargs):
self.app.register_blueprint(
self.blueprint,
url_prefix=self.url_prefix,
**kwargs
)
def install(self):
"""Installs the Blueprint into the app."""
self.app.before_request(self._before_request)
self._configure_routes()
self._register_blueprint()
def required(self, f):
"""Request decorator. Forces authentication."""
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not self._check_auth():
return redirect(url_for('%s.__login' % self.blueprint.name, next=request.url))
return f(*args, **kwargs)
return decorated