-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/login api #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
441fa7e
20ab0c2
436756f
f2c065b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| password | ||
| secret | ||
| secret.json |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,28 +1,30 @@ | ||
| 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 | ||
| from people import app as people_app | ||
| 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, | ||
| '/people': people_app, | ||
| '/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() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from groups import * | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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('/<groupname>/') | ||
| 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() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from login import * |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| #!/usr/bin/python | ||
|
|
||
| from ..utils import authentication_core | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. combine into one line |
||
| 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() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,5 @@ | ||
| <form name="login" action="" method="POST"> | ||
| <form name="login" action="handler?session_id={{session_id}}" method="POST"> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is the session_id revealed in the link by design? it can be posted as well through a hidden input element |
||
| Username: <input type="text" name="username"><br> | ||
| Password: <input type="password" name="password"><br> | ||
| <input type="submit" value="Submit"> | ||
| </form><br> | ||
| <a href="..">testpage</a> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # SIMMONS API CLIENT STUBS FOR PYTHON | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this was autogenerated, we might want to put it in .gitignore? I guess it doesn't change thaaaat much between commits |
||
| # 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 | ||
| ### | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the point of this line? I thought this could be an empty file