diff --git a/helios_auth/auth_systems/__init__.py b/helios_auth/auth_systems/__init__.py
index 84382e84a4f394b8e16c1d326d637f9dedf18c55..181834137a187acd82058c00098166d5786c3710 100644
--- a/helios_auth/auth_systems/__init__.py
+++ b/helios_auth/auth_systems/__init__.py
@@ -1,5 +1,5 @@
 from django.conf import settings
-from . import password, twitter, linkedin, cas, facebook, google, yahoo, clever
+from . import password, twitter, linkedin, cas, facebook, google, yahoo, clever, github
 
 AUTH_SYSTEMS = {}
 
@@ -11,6 +11,7 @@ AUTH_SYSTEMS['facebook'] = facebook
 AUTH_SYSTEMS['google'] = google
 AUTH_SYSTEMS['yahoo'] = yahoo
 AUTH_SYSTEMS['clever'] = clever
+AUTH_SYSTEMS['github'] = github
 
 # not ready
 #import live
diff --git a/helios_auth/auth_systems/github.py b/helios_auth/auth_systems/github.py
new file mode 100644
index 0000000000000000000000000000000000000000..30c0e82024ff974c2d59c0619734ee2a5f6fb166
--- /dev/null
+++ b/helios_auth/auth_systems/github.py
@@ -0,0 +1,90 @@
+"""
+Github Authentication
+
+"""
+
+import httplib2
+from django.conf import settings
+from django.core.mail import send_mail
+from oauth2client.client import OAuth2WebServerFlow
+
+from helios_auth import utils
+
+# some parameters to indicate that status updating is not possible
+STATUS_UPDATES = False
+
+# display tweaks
+LOGIN_MESSAGE = "Log in with GitHub"
+
+def get_flow(redirect_url=None):
+  return OAuth2WebServerFlow(
+    client_id=settings.GH_CLIENT_ID,
+    client_secret=settings.GH_CLIENT_SECRET,
+    scope='read:user user:email',
+    auth_uri="https://github.com/login/oauth/authorize",
+    token_uri="https://github.com/login/oauth/access_token",
+    redirect_uri=redirect_url,
+  )
+
+def get_auth_url(request, redirect_url):
+  flow = get_flow(redirect_url)
+  request.session['gh_redirect_uri'] = redirect_url
+  return flow.step1_get_authorize_url()
+
+def get_user_info_after_auth(request):
+  redirect_uri = request.session['gh_redirect_uri']
+  del request.session['gh_redirect_uri']
+  flow = get_flow(redirect_uri)
+  if 'code' not in request.GET:
+    return None
+  code = request.GET['code']
+  credentials = flow.step2_exchange(code)
+
+  http = httplib2.Http(".cache")
+  http = credentials.authorize(http)
+  (_, content) = http.request("https://api.github.com/user", "GET")
+  response = utils.from_json(content.decode('utf-8'))
+  user_id = response['login']
+  user_name = response['name']
+
+  (_, content) = http.request("https://api.github.com/user/emails", "GET")
+  response = utils.from_json(content.decode('utf-8'))
+  user_email = None
+  for email in response:
+    if email['verified'] and email['primary']:
+      user_email = email['email']
+      break
+  if not user_email:
+    raise Exception("email address with GitHub not verified")
+
+  return {
+    'type': 'github',
+    'user_id': user_id,
+    'name': '%s (%s)' % (user_id, user_name),
+    'info': {'email': user_email},
+    'token': {},
+  }
+
+def do_logout(user):
+  return None
+
+def update_status(token, message):
+  pass
+
+def send_message(user_id, name, user_info, subject, body):
+  send_mail(
+    subject,
+    body,
+    settings.SERVER_EMAIL,
+    ["%s <%s>" % (user_id, user_info['email'])],
+    fail_silently=False,
+  )
+
+def check_constraint(eligibility, user_info):
+  pass
+
+#
+# Election Creation
+#
+def can_create_election(user_id, user_info):
+  return True
diff --git a/helios_auth/media/login-icons/github.png b/helios_auth/media/login-icons/github.png
new file mode 100644
index 0000000000000000000000000000000000000000..182a1a3f734fc1b7d712c68b04c29bad9460d6cd
Binary files /dev/null and b/helios_auth/media/login-icons/github.png differ
diff --git a/settings.py b/settings.py
index f4dddc3bd18e1466f77c5ccb6b1eddaace743d6b..b22c94ffa85951fe42f3c36aa5bbb2a5a2d647c6 100644
--- a/settings.py
+++ b/settings.py
@@ -246,6 +246,10 @@ CAS_ELIGIBILITY_REALM = get_from_env('CAS_ELIGIBILITY_REALM', "")
 CLEVER_CLIENT_ID = get_from_env('CLEVER_CLIENT_ID', "")
 CLEVER_CLIENT_SECRET = get_from_env('CLEVER_CLIENT_SECRET', "")
 
+# GitHub
+GH_CLIENT_ID = get_from_env('GH_CLIENT_ID', '')
+GH_CLIENT_SECRET = get_from_env('GH_CLIENT_SECRET', '')
+
 # email server
 EMAIL_HOST = get_from_env('EMAIL_HOST', 'localhost')
 EMAIL_PORT = int(get_from_env('EMAIL_PORT', "2525"))