Custom login - UniMOOC/AAClassroom GitHub Wiki
New student registration
One of the things we wanted to change from the 2014 version of the Activate platform was the way the students authenticate on the platform. Specifically we wanted to scrap the default App Engine Google login and use the Google+ Sign-in system.
This feature has both a frontend and a backend component.
Frontend
We have to include the G+ Sign in button somewhere. Once the user is logged in we will set a header with the id_token of the user with every request that we want to authenticate.
config.headers['Id-Token'] = user.idToken;
(This example by itself won't do much. It's a part of the AngularJS app)
Once every requests has it's Id-Token header we are ready to authenticate them in the server.
Backend
To make a URL endpoint authenticated we can use the decorator gpluslogin
located in modules.um_students.utils.py
like so:
class ProgressAPIHandler(UMBaseHandler):
""" Handlers for /api/progress"""
@gpluslogin
def get(self):
""" Retrieves the progress of a student
Returns the progress of the authenticated student
"""
progress = self.student.get_course_progress()
self.write_json(progress)
Every method decorated with gpluslogin
can access the authenticated user with self.student
.
The decorator does the following:
def gpluslogin(fn):
""" Decorator to inject a student by their Google id token
"""
def inner_fn(handler, *args, **kwargs):
try:
# 1
id_token = handler.request.headers.get('Id-Token')
if not id_token:
return handler.return_with_error(
401, 'Id-Token header is required')
# 2
jwt = AuthenticationService.um_verify_id_token(id_token)
if not jwt:
return handler.return_with_error(401, 'Id-Token not valid')
# 3
email = jwt['email']
handler.student = Students.get_by_email(email)
if not handler.student:
return throw_some_error()
except AppIdentityError as ex: # 4
import logging
logging.error(str(ex))
return handler.return_with_error(401, 'API Identity error')
return fn(handler, *args, **kwargs)
return inner_fn
-
Gets the token from the headers
-
Verifies that it's a valid token (more on this later) and if it's not we return with an error
-
Gets the email from the unencrypted token
-
If the unencryption throws an AppIdentityError (which means that the token is not for our application) we throw an error.
The AuthenticationService
gets the Google certs from memcache and tries to unencrypt the token. If for some reason it fails it updates the certs.