Skip to content

Commit

Permalink
Merge pull request #565 from NBISweden/feature/no-google
Browse files Browse the repository at this point in the history
Goodbye Google
  • Loading branch information
viklund committed May 23, 2019
2 parents fe92811 + 3715849 commit 2ddda89
Show file tree
Hide file tree
Showing 11 changed files with 11 additions and 296 deletions.
1 change: 0 additions & 1 deletion backend/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ def get(self):
'email': user.email,
'affiliation': user.affiliation,
'country': user.country,
'login_type': self.get_secure_cookie('identity_type').decode('utf-8'),
}

self.finish(ret)
Expand Down
179 changes: 0 additions & 179 deletions backend/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ def get(self):
self.set_secure_cookie('user', self.get_argument("user"))
self.set_secure_cookie('email', self.get_argument("email"))
self.set_secure_cookie('identity', self.get_argument("email"))
self.set_secure_cookie('identity_type', 'google')
self.finish()


Expand Down Expand Up @@ -56,27 +55,10 @@ async def get(self):
user_token = await self.get_user_token(self.get_argument('code'))
user = await self.get_user(user_token["access_token"])

extra_login = None
try: # check if the user is already logged in
extra_login = self.get_secure_cookie('identity_type').decode('utf-8')

# Store other login in separate cookies (elixir is main login)
# This is hardcoded for google right now, as that is the only option
if extra_login == 'google':
google_identity = self.get_secure_cookie('identity').decode('utf-8')
self.set_secure_cookie('google_identity', google_identity)

except AttributeError: # if the user isn't logged in
pass

self.set_secure_cookie('access_token', user_token["access_token"])
self.set_secure_cookie('user', user["name"])
self.set_secure_cookie('email', user["email"])
self.set_secure_cookie('identity', user["sub"])
self.set_secure_cookie('identity_type', 'elixir')

if extra_login:
self.set_secure_cookie('identity_type', 'elixir_%s' % extra_login)

redirect = self.get_secure_cookie("login_redirect")
self.clear_cookie("login_redirect")
Expand Down Expand Up @@ -162,164 +144,3 @@ def get(self):
self.redirect(redirect)


class GoogleLoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
"""
See http://www.tornadoweb.org/en/stable/auth.html#google for documentation
on this. Here I have copied the example more or less verbatim.
"""
@tornado.gen.coroutine
def get(self):
if self.get_argument("code", False):
logging.debug("Requesting user token")
user_token = yield self.get_authenticated_user(
redirect_uri=self.application.settings['redirect_uri'],
code=self.get_argument('code'),
callback = lambda *_, **__: None)

logging.debug("Requesting user info")
user = yield self.oauth2_request(
"https://www.googleapis.com/plus/v1/people/me",
access_token=user_token["access_token"],
callback = lambda *_, **__: None)

try:
# Check if there is the user is already in the database.
# This will generate an exception if the user does not exist, preventing login
db.User.select().where(db.User.identity == self._get_google_email(user)).get()

extra_login = None
try: # check if the user is already logged in
extra_login = self.get_secure_cookie('identity_type').decode('utf-8')

# Store this login in separate cookies (elixir is main login)
# This is hardcoded for elixir right now, as that is the only option
if extra_login == 'elixir':
google_identity = self._get_google_email(user)
self.set_secure_cookie('google_identity', google_identity)

self.set_secure_cookie('identity_type', '%s_google' % extra_login)

except AttributeError: # if the user isn't logged in
self.set_secure_cookie('user', user["displayName"])
self.set_secure_cookie('access_token', user_token["access_token"])
self.set_secure_cookie('email', self._get_google_email(user))
self.set_secure_cookie('identity', self._get_google_email(user))
self.set_secure_cookie('identity_type', 'google')

except db.User.DoesNotExist:
msg = "You have no user information logged in our database, so you may directly log in using elixir without updating."
self.set_user_msg(msg, "success")

url = self.get_secure_cookie("login_redirect")
self.clear_cookie("login_redirect")
if url is None:
url = '/'
self.redirect(url)

else:
logging.debug("Redirecting to google for login")
self.set_secure_cookie('login_redirect', self.get_argument("next", '/'), 1)
self.authorize_redirect(
redirect_uri=self.application.settings['redirect_uri'],
client_id=self.application.oauth_key,
scope=['profile', 'email'],
response_type='code',
extra_params={'approval_prompt': 'auto'})

def _get_google_email(self, user): #pylint: disable=no-self-use
email = ''
# There can be several emails registered for a user.
for email in user["emails"]:
if email.get('type', '') == 'account':
return email['value']

return user['emails'][0]['value']


class GoogleLogoutHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
def get(self):
def handle_request(response):
if response.error:
logging.info("Error, failed in logout")
logging.info(response.error)
else:
logging.info("User logged out")

sAccessToken = self.get_secure_cookie("access_token")
sLogoutUrl = "https://accounts.google.com/o/oauth2/revoke?token=" + str(sAccessToken)
http_client = tornado.httpclient.AsyncHTTPClient()
http_client.fetch(sLogoutUrl, handle_request)

self.clear_all_cookies()

redirect = self.get_argument("next", '/')
self.redirect(redirect)


class UpdateUserHandler(handlers.SafeHandler):
def post(self):
"""
If a user is logged in to elixir, and also has google login cookies, the
google users information in the database will be updated with the elixir
users information.
"""
# set redirect
try:
redirect = self.get_argument("next")
except tornado.web.MissingArgumentError:
redirect = self.get_cookie("login_redirect", '/')
self.clear_cookie("login_redirect")

try:
# Double check so that the elixir user isn't already have any credentials
# in the database.

elixir_identity = self.get_secure_cookie('user')

(db.User.select()
.join(db.DatasetAccess)
.where(
db.User.user == db.DatasetAccess.user,
db.User.identity == elixir_identity)
.get())
msg = "This elixir account already has its own credentials. Sadly, you will have to contact us directly to merge your accounts."
self.set_user_msg(msg, "error")
self.finish({'redirect':'/login'})
return
except db.User.DoesNotExist:
# This is what we want
pass

try:
# Check if we have a google login, will throw an AttributeError
# if the cookie isn't available
google_identity = self.get_secure_cookie('google_identity').decode('utf-8')

# Try to update the google user in the database with the elixir information
# This throws a peewee.IntegrityError if the elixir account is already in
# the database
db.User.update( name = self.get_secure_cookie('user').decode('utf-8'),
email = self.get_secure_cookie('email').decode('utf-8'),
identity = self.get_secure_cookie('identity').decode('utf-8'),
identity_type = 'elixir'
).where( db.User.identity == google_identity ).execute()

self.set_secure_cookie('identity_type', 'updated')
except AttributeError:
# This will happen when we don't have a google cookie
msg = "You need to log in to a google account to be able to transfer credentials"
self.set_user_msg(msg, "info")

self.finish({'redirect':'/login'})
return
except peewee.IntegrityError:
# This will happen if the elixir account is already in the database
msg = "This elixir account is already in our database, so it can't be used to update another google account."
self.set_user_msg(msg, "error")
self.finish({'redirect':'/login'})
return

msg = "Your account has been updated! You may now use the site as you used to, using your Elixir account."
self.set_user_msg(msg, "success")

self.finish({'redirect':redirect})
2 changes: 1 addition & 1 deletion backend/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ class Meta:
name = CharField(db_column="username", null=True)
email = CharField(unique=True)
identity = CharField(unique=True)
identity_type = EnumField(null=False, choices=['google', 'elixir'])
identity_type = EnumField(null=False, choices=['google', 'elixir'], default='elixir')
affiliation = CharField(null=True)
country = CharField(null=True)

Expand Down
4 changes: 1 addition & 3 deletions backend/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ def get_current_user(self):
email = self.get_secure_cookie('email')
name = self.get_secure_cookie('user')
identity = self.get_secure_cookie('identity')
identity_type = self.get_secure_cookie('identity_type')

# Fix ridiculous bug with quotation marks showing on the web
if name and (name[0] == '"') and (name[-1] == '"'):
Expand All @@ -49,8 +48,7 @@ def get_current_user(self):
try:
return db.User(email = email.decode('utf-8'),
name = name.decode('utf-8'),
identity = identity.decode('utf-8'),
identity_type = identity_type.decode('utf-8'))
identity = identity.decode('utf-8'))
except peewee.OperationalError as e:
logging.error("Can't create new user: {}".format(e))
else:
Expand Down
11 changes: 0 additions & 11 deletions backend/route.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,11 @@
tornado_settings = {"debug": False,
"cookie_secret": swefreq_settings.cookie_secret,
"login_url": "/login",
"google_oauth": {
"key": swefreq_settings.google_key,
"secret": swefreq_settings.google_secret
},
"elixir_oauth": {
"id": swefreq_settings.elixir["id"],
"secret": swefreq_settings.elixir["secret"],
"redirect_uri": swefreq_settings.elixir["redirectUri"],
},
"redirect_uri": swefreq_settings.redirect_uri,
"xsrf_cookies": True,
"template_path": "templates/",
}
Expand All @@ -49,10 +44,7 @@ def __init__(self, settings):
(r"/logout", auth.ElixirLogoutHandler),
(r"/elixir/login", auth.ElixirLoginHandler),
(r"/elixir/logout", auth.ElixirLogoutHandler),
(r"/google/login", auth.GoogleLoginHandler),
(r"/google/logout", auth.GoogleLogoutHandler),
## API Methods
(r"/api/users/elixir_transfer", auth.UpdateUserHandler),
(r"/api/countries", application.CountryList),
(r"/api/users/me", application.GetUser),
(r"/api/users/datasets", application.UserDatasetAccess),
Expand Down Expand Up @@ -93,9 +85,6 @@ def __init__(self, settings):
self.declared_handlers.insert(-1, ("/developer/login", auth.DeveloperLoginHandler))
self.declared_handlers.insert(-1, ("/developer/quit", application.QuitHandler))

# google oauth key
self.oauth_key = tornado_settings["google_oauth"]["key"]

# Setup the Tornado Application
tornado.web.Application.__init__(self, self.declared_handlers, **settings)

Expand Down
5 changes: 0 additions & 5 deletions backend/settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import os
import sys
import json
Expand All @@ -23,10 +22,6 @@
json_settings = json.load(json_settings_fh)
json_settings_fh.close()

google_key = json_settings["googleKey"]
google_secret = json_settings["googleSecret"]
redirect_uri = json_settings["redirectUri"]

elixir = json_settings["elixir"]

## Generated with base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)
Expand Down
1 change: 0 additions & 1 deletion frontend/src/js/app.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
.config(["$routeProvider", "$locationProvider", "$httpProvider", function($routeProvider, $locationProvider, $httpProvider) {
$routeProvider
.when("/", { templateUrl: "static/templates/ng-templates/home.html" })
.when("/login", { templateUrl: "static/templates/ng-templates/login.html" })
.when("/profile", { templateUrl: "static/templates/ng-templates/profile.html" })
.when("/error", { templateUrl: "static/templates/ng-templates/error.html" })
.when("/security_warning", { templateUrl: "static/templates/ng-templates/security-warning.html" })
Expand Down
19 changes: 1 addition & 18 deletions frontend/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,6 @@
<!-- CSS -->
<link rel="stylesheet" href="/static/css/main.css?v=[[ version ]]" type="text/css" />

[% if develop %]
[% else %]
<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-85976442-1', 'auto');
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->
[% endif %]
</head>
<!-- define angular controller -->
<body ng-controller="mainController as mainCtrl">
Expand All @@ -57,11 +44,7 @@
</ul>
</li>
<li class="dropdown" ng_if="mainCtrl.loggedIn == false">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Login <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/elixir/login?next={{ mainCtrl.url() }}" target="_self">Elixir AAI</a></li>
<li><a href="/login/?next={{ mainCtrl.url() }}" target="_self">Google (legacy)</a></li>
</ul>
<a href="/elixir/login?next={{ mainCtrl.url() }}" target="_self">Login</a>
</li>
</ul>
</div>
Expand Down
65 changes: 0 additions & 65 deletions frontend/templates/ng-templates/login.html

This file was deleted.

Loading

0 comments on commit 2ddda89

Please sign in to comment.