diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..04eab79
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,3 @@
+password
+secret
+secret.json
diff --git a/src/auth/__init__.py b/src/auth/__init__.py
deleted file mode 100644
index 4c06cdc..0000000
--- a/src/auth/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from auth import *
diff --git a/src/auth/auth.py b/src/auth/auth.py
deleted file mode 100644
index f85a724..0000000
--- a/src/auth/auth.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/python
-
-from ..utils import authentication_core #as authentication
-from ..utils import authorization_core #as authorization
-
-# Setup flask basics.
-from flask import Flask, render_template, make_response, request
-app = Flask(__name__)
-
-# TODO: Remove in production? DO NOT PRINT TOKEN FOR FUCKS SAKE.
-@app.route('/')
-def test():
- username = request.cookies.get('username')
- token = request.cookies.get('token')
- return render_template( 'test.html', username = username, token = token )
-
-@app.route('/login', methods=['GET', 'POST'])
-def login():
- if request.method == 'POST':
- username = request.form['username']
- password = request.form['password']
- try:
- token = authentication_core.authenticate( username, password )
- resp = make_response( render_template( 'logged_in.html', username = username ) )
- resp.set_cookie( 'username', username )
- resp.set_cookie( 'token', token )
- return resp
- except authentication_core.AuthenticationError:
- return "Authentication Error"
- else:
- return render_template( 'login.html' )
-
-@app.route('/logout', methods=['GET', 'POST'])
-def logout():
- username = request.cookies.get('username')
- token = request.cookies.get('token')
- try:
- authentication_core.invalidate_token( username, token )
- resp = make_response( render_template( 'logged_out.html', username = username ) )
- resp.set_cookie( 'username', '' )
- resp.set_cookie( 'token', '' )
- return resp
- except authentication_core.AuthenticationError:
- return "Authentication Error"
-
-# TODO: Remove in production.
-@app.route('/authtest')
-def authtest():
- username = request.cookies.get('username')
- token = request.cookies.get('token')
-
- @authorization_core.restricted( "simmons-tech" )
- def super_secret():
- return "Welcome, Simmons Tech Member " + username + "!"
-
- try:
- return super_secret( username, token )
- except authorization_core.AuthorizationError:
- return "Nice try " + username + ". No bits for you."
-
-
-if __name__ == "__main__":
- app.debug = True # TODO: Remove in production.
- app.run()
diff --git a/src/auth/templates/logged_in.html b/src/auth/templates/logged_in.html
deleted file mode 100644
index 6d00669..0000000
--- a/src/auth/templates/logged_in.html
+++ /dev/null
@@ -1,3 +0,0 @@
-You've been logged in {{ username }}!
-
-testpage
diff --git a/src/auth/templates/logged_out.html b/src/auth/templates/logged_out.html
deleted file mode 100644
index 599c9b1..0000000
--- a/src/auth/templates/logged_out.html
+++ /dev/null
@@ -1,3 +0,0 @@
-You've been logged out {{ username }}!
-
-testpage
diff --git a/src/auth/templates/test.html b/src/auth/templates/test.html
deleted file mode 100644
index 9d8aa87..0000000
--- a/src/auth/templates/test.html
+++ /dev/null
@@ -1,6 +0,0 @@
-Username: {{ username }}
-
-Token: {{ token }}
-
-login
-logout
diff --git a/src/dispatch.py b/src/dispatch.py
index 220c8d2..bd26380 100644
--- a/src/dispatch.py
+++ b/src/dispatch.py
@@ -1,7 +1,7 @@
from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware
-from auth import app as auth_app
+from login import app as login_app
from buses import app as buses_app
from laundry import app as laundry_app
from packages import app as packages_app
@@ -9,13 +9,14 @@
from profile import app as profile_app
from rooming_assignment import app as rooming_assignment_app
from rooms import app as rooms_app
+from groups import app as groups_app
app = Flask(__name__)
app.wsgi_app = DispatcherMiddleware(
app.wsgi_app,
{
- '/auth': auth_app,
+ '/login': login_app,
'/buses': buses_app,
'/laundry': laundry_app,
'/packages': packages_app,
@@ -23,6 +24,7 @@
'/profile': profile_app, # TODO: rename to profiles?
'/rooming_assignment': rooming_assignment_app, # TODO: rename to rooming_assignments?
'/rooms': rooms_app,
+ '/groups': groups_app,
})
app.run()
diff --git a/src/groups/__init__.py b/src/groups/__init__.py
new file mode 100644
index 0000000..5d2cbc8
--- /dev/null
+++ b/src/groups/__init__.py
@@ -0,0 +1 @@
+from groups import *
diff --git a/src/groups/groups.py b/src/groups/groups.py
new file mode 100644
index 0000000..b9ba5b6
--- /dev/null
+++ b/src/groups/groups.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+# Setup flask basics.
+from flask import Flask, jsonify
+from ..utils import authorization_core as authcore
+
+app = Flask(__name__)
+
+@app.route('/')
+def serve_groups():
+ return jsonify(groupnames = authcore.get_groupnames())
+
+@app.route('//')
+def serve_members( groupname ):
+ return jsonify(
+ groupname = groupname,
+ members = list(authcore.members(groupname)))
+
+if __name__ == "__main__":
+ app.debug = True # TODO: Remove in production.
+ app.run()
diff --git a/src/login/__init__.py b/src/login/__init__.py
new file mode 100644
index 0000000..3a6230b
--- /dev/null
+++ b/src/login/__init__.py
@@ -0,0 +1 @@
+from login import *
diff --git a/src/login/login.py b/src/login/login.py
new file mode 100644
index 0000000..c9d618b
--- /dev/null
+++ b/src/login/login.py
@@ -0,0 +1,95 @@
+#!/usr/bin/python
+
+from ..utils import authentication_core
+from ..utils import authorization_core
+
+import binascii
+import os
+
+# Setup flask basics.
+from flask import Flask, render_template, make_response, request, jsonify, redirect
+app = Flask(__name__)
+
+### SESSION LOOKUP AND STORE ###
+
+# TODO: Do not use an in memory store. Make a LOGIN_SESSION Database.
+
+session_cache = {}
+
+def register_session(redirect, state, domain):
+ session_id = binascii.hexlify(os.urandom(16)) # Hex Encoding for URL Saftey.
+ session_cache[session_id] = (redirect, state, domain)
+ return session_id
+
+# Deletes the session and returns it.
+def recall_session( session_id ):
+ result = session_cache[session_id]
+ del session_cache[session_id]
+ return result
+
+################################
+
+def domain_from_redirect( redirect ):
+ #TODO: Use URL Parse.
+ if 'mit.edu' in redirect:
+ return '.mit.edu'
+ return ''
+
+@app.route('/')
+def login_page():
+ # Required args.
+ redirect = request.args.get('redirect', None)
+ if redirect == None:
+ return "500: Must Provide Redirect (i.e. login/?redirect=simmons.mit.edu/directory)"
+ # Optional args.
+ state = request.args.get('state', '')
+ domain = request.args.get('domain', domain_from_redirect(redirect))
+
+ # TODO: Generate session key? Don't expose redirect, state, domain.
+ session_id = register_session(redirect, state, domain)
+
+ # Lot of work in login.html.
+ return render_template( 'login.html', session_id = session_id )
+
+@app.route('/handler', methods=['POST'])
+def login_handler():
+ # TODO: This is only the local case, reflect that.
+ session_id = request.args.get('session_id')
+ session_id = session_id.strip() # TODO: Check if this is needed. It shouldn't be, but I'm paranoid about trailing newlines or something.
+ username = request.form['username']
+ password = request.form['password'] # TODO: This is horribly insecure... Use a burner key with SRP.
+ redirect_link, state, domain = recall_session( session_id ) # TODO: Handle case where session_id not in cache.
+ try:
+ token = authentication_core.authenticate( username, password )
+ response = make_response(redirect(redirect_link))
+ response.set_cookie( 'username', username )
+ response.set_cookie( 'token', token )
+ return response
+ except authentication_core.AuthenticationError:
+ return "500: Authentication Error"
+
+# TODO: Add redirect to this, default to login page.
+@app.route('/invalidate', methods=['GET','POST'])
+def invalidate_token():
+ username = request.cookies.get('username')
+ token = request.cookies.get('token')
+ redirect_link = request.args.get('redirect', '/login/?redirect=http://simmons.mit.edu')
+ try:
+ authentication_core.invalidate_token( username, token )
+ return make_response(redirect(redirect_link))
+ except authentication_core.AuthenticationError:
+ return "500: Authentication Error"
+
+@app.route('/check')
+def check_token():
+ try:
+ username = request.cookies.get('username')
+ token = request.cookies.get('token')
+ authentication_core.validate_token(username, token)
+ return jsonify(response='200', username=username)
+ except: # TODO: Restrict what this catches.
+ return jsonify(response='401')
+
+if __name__ == "__main__":
+ app.debug = True # TODO: Remove in production.
+ app.run()
diff --git a/src/auth/templates/login.html b/src/login/templates/login.html
similarity index 66%
rename from src/auth/templates/login.html
rename to src/login/templates/login.html
index 692962e..b180927 100644
--- a/src/auth/templates/login.html
+++ b/src/login/templates/login.html
@@ -1,6 +1,5 @@
-
-testpage
diff --git a/src/utils/authentication_core/authentication_core.py b/src/utils/authentication_core/authentication_core.py
index e3814f9..028f5a1 100644
--- a/src/utils/authentication_core/authentication_core.py
+++ b/src/utils/authentication_core/authentication_core.py
@@ -16,7 +16,6 @@
# Util imports
from .. import db
-
# Authcore imports
import HMAC
from authentication_exceptions import *
diff --git a/src/utils/authorization_core/authorization_core.py b/src/utils/authorization_core/authorization_core.py
index d0e00b7..7d7b02f 100644
--- a/src/utils/authorization_core/authorization_core.py
+++ b/src/utils/authorization_core/authorization_core.py
@@ -20,6 +20,12 @@
# Local imports
from authorization_exceptions import *
+def get_groupnames():
+ group_db = db.init('group')
+ groups = [ group.groupname for group in group_db.query(db.Group) ]
+ return groups
+ # TODO: Close db?
+
def is_group( name ):
group_db = db.init('group')
group = group_db.query(db.Group).get( name )
diff --git a/src/utils/db/db/user/user.db b/src/utils/db/db/user/user.db
index 99fe14a..8ba97af 100644
Binary files a/src/utils/db/db/user/user.db and b/src/utils/db/db/user/user.db differ
diff --git a/stubgen/apis.yaml b/stubgen/apis.yaml
index 840e916..6700b0b 100644
--- a/stubgen/apis.yaml
+++ b/stubgen/apis.yaml
@@ -2,6 +2,14 @@
# This method is used to generate stubs for both local and remote use on both clients and providers.
---
+- name: login
+ desc: Aux. methods for supporting the Simmons SSO System.
+ path: "login/"
+ fxns:
+ - name: check
+ desc: Checks if the user is logged in. If so, will provide their username.
+ args: []
+ path: "check"
- name: rooms
desc: Provides data about the physical characteristics of Simmons rooms.
path: "rooms/"
diff --git a/stubgen/stubs/javascript/simmons-api.js b/stubgen/stubs/javascript/simmons-api.js
index b72f53f..3d57417 100644
--- a/stubgen/stubs/javascript/simmons-api.js
+++ b/stubgen/stubs/javascript/simmons-api.js
@@ -11,6 +11,16 @@ this.RPC_call = function( path, callback ) {
}
+// Beginning stubs for login:
+// Aux. methods for supporting the Simmons SSO System.
+this.login = {
+
+ // Checks if the user is logged in. If so, will provide their username.
+ check: function( callback ) {
+ return RPC_call( "login/check", callback );
+ },
+}; // End of stubs for login
+
// Beginning stubs for rooms:
// Provides data about the physical characteristics of Simmons rooms.
this.rooms = {
diff --git a/stubgen/stubs/python/simmons_api/__init__.py b/stubgen/stubs/python/simmons_api/__init__.py
index c79666d..6d11534 100644
--- a/stubgen/stubs/python/simmons_api/__init__.py
+++ b/stubgen/stubs/python/simmons_api/__init__.py
@@ -4,6 +4,7 @@
# This will ensure that changes are reflected in other
# languages stubs.
+import login
import rooms
import rooming_assignment
import people
diff --git a/stubgen/stubs/python/simmons_api/login.py b/stubgen/stubs/python/simmons_api/login.py
new file mode 100644
index 0000000..9b521bb
--- /dev/null
+++ b/stubgen/stubs/python/simmons_api/login.py
@@ -0,0 +1,20 @@
+# SIMMONS API CLIENT STUBS FOR PYTHON
+# This code was auto-generated by stubgen.py
+# DO NOT EDIT IT BY HAND. Edit apis.yaml instead.
+# This will ensure that changes are reflected in other
+# languages stubs.
+
+from __common import *
+
+###
+# Beginning stubs for login:
+# Aux. methods for supporting the Simmons SSO System.
+###
+
+# Checks if the user is logged in. If so, will provide their username.
+def check( ):
+ return RPC_call( "login/check" )
+
+###
+# End of stubs for login
+###
\ No newline at end of file