def test_verify_response(self): request_sig = duo_web.sign_request(IKEY, SKEY, AKEY, USER) duo_sig, valid_app_sig = request_sig.split(':') request_sig = duo_web.sign_request(IKEY, SKEY, 'invalid' * 6, USER) duo_sig, invalid_app_sig = request_sig.split(':') invalid_user = duo_web.verify_response( IKEY, SKEY, AKEY, INVALID_RESPONSE + ':' + valid_app_sig) self.assertEqual(invalid_user, None) expired_user = duo_web.verify_response( IKEY, SKEY, AKEY, EXPIRED_RESPONSE + ':' + valid_app_sig) self.assertEqual(expired_user, None) future_user = duo_web.verify_response( IKEY, SKEY, AKEY, FUTURE_RESPONSE + ':' + invalid_app_sig) self.assertEqual(future_user, None) future_user = duo_web.verify_response( IKEY, SKEY, AKEY, FUTURE_RESPONSE + ':' + valid_app_sig) self.assertEqual(future_user, USER) future_user = duo_web.verify_response( IKEY, SKEY, AKEY, WRONG_PARAMS_RESPONSE + ':' + valid_app_sig) self.assertEqual(future_user, None) future_user = duo_web.verify_response( IKEY, SKEY, AKEY, FUTURE_RESPONSE + ':' + WRONG_PARAMS_APP) self.assertEqual(future_user, None) future_user = duo_web.verify_response( WRONG_IKEY, SKEY, AKEY, FUTURE_RESPONSE + ':' + valid_app_sig) self.assertEqual(future_user, None)
def test_verify_response(self): request_sig = duo_web.sign_request(IKEY, SKEY, AKEY, USER) duo_sig, valid_app_sig = request_sig.split(':') request_sig = duo_web.sign_request(IKEY, SKEY, 'invalid' * 6, USER) duo_sig, invalid_app_sig = request_sig.split(':') invalid_user = duo_web.verify_response(IKEY, SKEY, AKEY, INVALID_RESPONSE + ':' + valid_app_sig) self.assertEqual(invalid_user, None) expired_user = duo_web.verify_response(IKEY, SKEY, AKEY, EXPIRED_RESPONSE + ':' + valid_app_sig) self.assertEqual(expired_user, None) future_user = duo_web.verify_response(IKEY, SKEY, AKEY, FUTURE_RESPONSE + ':' + invalid_app_sig) self.assertEqual(future_user, None) future_user = duo_web.verify_response(IKEY, SKEY, AKEY, FUTURE_RESPONSE + ':' + valid_app_sig) self.assertEqual(future_user, USER) future_user = duo_web.verify_response(IKEY, SKEY, AKEY, WRONG_PARAMS_RESPONSE + ':' + valid_app_sig) self.assertEqual(future_user, None) future_user = duo_web.verify_response(IKEY, SKEY, AKEY, FUTURE_RESPONSE + ':' + WRONG_PARAMS_APP) self.assertEqual(future_user, None) future_user = duo_web.verify_response(WRONG_IKEY, SKEY, AKEY, FUTURE_RESPONSE + ':' + valid_app_sig) self.assertEqual(future_user, None)
def test_sign_request(self): request_sig = duo_web.sign_request(IKEY, SKEY, AKEY, USER) self.assertNotEqual(request_sig, None) request_sig = duo_web.sign_request(IKEY, SKEY, AKEY, '') self.assertEqual(request_sig, duo_web.ERR_USER) request_sig = duo_web.sign_request('invalid', SKEY, AKEY, USER) self.assertEqual(request_sig, duo_web.ERR_IKEY) request_sig = duo_web.sign_request(IKEY, 'invalid', AKEY, USER) self.assertEqual(request_sig, duo_web.ERR_SKEY) request_sig = duo_web.sign_request(IKEY, SKEY, 'invalid', USER) self.assertEqual(request_sig, duo_web.ERR_AKEY)
def duo_auth(request): if is_duo_authenticated(request): return redirect("index") sig_request = None duo_settings = CONFIG.get("DUO_SETTINGS", {}) if request.POST: sig_response = request.POST.get("sig_response", None) if sig_response: authenticated_username = duo_web.verify_response( duo_settings.get("IKEY"), duo_settings.get("SKEY"), duo_settings.get("AKEY"), sig_response, ) if authenticated_username: duo_authenticate(request) return redirect("admin:index") sig_request = duo_web.sign_request( duo_settings.get("IKEY"), duo_settings.get("SKEY"), duo_settings.get("AKEY"), request.user.username, ) context = { "sig_request": sig_request, "host": duo_settings.get("HOST"), "post_action": reverse("duo_auth"), } return render(request, "registration/duo.html", context)
async def post(self): """Override the default POST handler. If the Duo signed response isn't present, do primary auth and POST back to the same URL with the request. If the response is present, call the stock LoginHandler post method, which will call DuoAuthenticator.authenticate() to perform verification of the response. """ # parse the arguments dict data = {} for arg in self.request.arguments: data[arg] = self.get_argument(arg, strip=False) sig_response = self.get_argument("sig_response", default=None) if sig_response: # Duo signed response present, do secondary auth await LoginHandler.post(self) else: # no sig_response, do primary auth and generate the request username = await self.authenticator.do_primary_auth(self,data) if username: sig_request = duo_web.sign_request(self.authenticator.ikey, self.authenticator.skey, self.authenticator.akey, username) html = await self.render_template('duo.html', host=self.authenticator.apihost, sig_request=sig_request, custom_html=self.authenticator.duo_custom_html) self.finish(html) else: # self._render is defined by LoginHandler html = await self._render( login_error='Invalid username or password', username=username, ) self.finish(html)
def do_GET(self): try: self.serve_file() except IOError: pass else: return # we served a file from the FS # Get the username from the 'user' query argument. In real life, # this will usually be done with framework-appropriate authentication. # The local username will be used as the Duo username as well. try: username = self.require_query('user') except ValueError: self.error('user query parameter is required') return self.send_response(200) # Set a cookie to compare with the Duo return self.set_secure_cookie('user', username) self.end_headers() sig_request = duo_web.sign_request(skey, ikey, username) self.wfile.write( "<script src='/Duo-Web-v1.bundled.min.js'></script>" "<script>" "Duo.init({'host':'%(host)s', 'sig_request':'%(sig_request)s'});" "</script>" "<iframe height='100%%' width='100%%' id='duo_iframe' />" % { 'host': host, 'sig_request': sig_request }) return
def prepareForStep(self, configurationAttributes, requestParameters, step): identity = CdiUtil.bean(Identity) authenticationService = CdiUtil.bean(AuthenticationService) duo_host = configurationAttributes.get("duo_host").getValue2() if (step == 1): print "Duo. Prepare for step 1" return True elif (step == 2): print "Duo. Prepare for step 2" user = authenticationService.getAuthenticatedUser() if (user == None): print "Duo. Prepare for step 2. Failed to determine user name" return False user_name = user.getUserId() duo_sig_request = duo_web.sign_request(self.ikey, self.skey, self.akey, user_name) print "Duo. Prepare for step 2. duo_sig_request: " + duo_sig_request identity.setWorkingParameter("duo_host", duo_host) identity.setWorkingParameter("duo_sig_request", duo_sig_request) return True else: return False
def do_GET(self): try: self.serve_file() except IOError: pass else: return # we served a file from the FS # Get the username from the 'user' query argument. In real life, # this will usually be done with framework-appropriate authentication. # The local username will be used as the Duo username as well. try: username = self.require_query("user") except ValueError: self.error("user query parameter is required") return self.send_response(200) # Set a cookie to compare with the Duo return self.set_secure_cookie("user", username) self.end_headers() sig_request = duo_web.sign_request(skey, ikey, username) self.wfile.write( "<script src='/Duo-Web-v1.bundled.min.js'></script>" "<script>" "Duo.init({'host':'%(host)s', 'sig_request':'%(sig_request)s'});" "</script>" "<iframe height='100%%' width='100%%' id='duo_iframe' />" % {"host": host, "sig_request": sig_request} ) return
def get(self): if self.both_logged_in(): self.redirect('/') return user = users.get_current_user() if not user: self.redirect('/') return (username, _) = self.user_email_parts(user) sig_request = duo_web.sign_request(ikey, skey, akey, username) self.response.out.write( "<html>" " <head>" " <title>Duo Authentication</title>" " <meta name='viewport' content='width=device-width, initial-scale=1'>" " <meta http-equiv='X-UA-Compatible' content='IE=edge'>" " <link rel='stylesheet' type='text/css' href='/static/Duo-Frame.css'>" " </head>" " <body>" " <h1>Duo Authentication</h1>" " <script src='/static/Duo-Web-v2.js'></script>" " <iframe id='duo_iframe'" " title='Two-Factor Authentication'" " frameborder='0'" " data-host='%(host)s'" " data-sig-request='%(sig_request)s'" " data-post-action='%(post_action)s'" " >" " </iframe>" " </body>" "</html>" % {'host': host, 'sig_request': sig_request, 'post_action': self.request.uri})
def prepareForStep(self, configurationAttributes, requestParameters, step): context = Contexts.getEventContext() duo_host = configurationAttributes.get("duo_host").getValue2() credentials = Identity.instance().getCredentials() user_name = credentials.getUsername() if (step == 1): print "Duo prepare for step 1" return True elif (step == 2): print "Duo prepare for step 2" passed_step1 = self.isPassedStep1 if (not passed_step1): return False duo_sig_request = duo_web.sign_request(self.ikey, self.skey, self.akey, user_name) print "Duo prepare for step 2. duo_sig_request: " + duo_sig_request context.set("duo_host", duo_host) context.set("duo_sig_request", duo_sig_request) return True else: return False
def duo_auth(request): if is_duo_authenticated(request): return redirect("index") sig_request = None duo_settings = CONFIG.get("DUO_SETTINGS", {}) if request.POST: sig_response = request.POST.get("sig_response", None) if sig_response: authenticated_username = duo_web.verify_response( duo_settings.get("IKEY"), duo_settings.get("SKEY"), duo_settings.get("AKEY"), sig_response, ) if authenticated_username: duo_authenticate(request) return redirect(request.GET.get("next", "admin:index")) sig_request = duo_web.sign_request( duo_settings.get("IKEY"), duo_settings.get("SKEY"), duo_settings.get("AKEY"), request.user.username, ) context = { "sig_request": sig_request, "host": duo_settings.get("HOST"), "post_action": f"{reverse('duo_auth')}?next={request.GET.get('next')}", } return render(request, "registration/duo.html", context)
def do_admin_login(): if request.form['sig_response'] == 'none' : session['logged_in'] = False POST_USERNAME = str(request.form['username']) POST_PASSWORD = str(request.form['password']) Session = sessionmaker(bind=engine) s = Session() query = s.query(User).filter(User.username.in_([POST_USERNAME]), User.password.in_([POST_PASSWORD]) ) result = query.first() if result: session['logged_in'] = True session['user'] = POST_USERNAME sig_request = duo_web.sign_request(ikey, skey, akey,session['user']) return render_template('duo_mfa.html',host=host,sig_request=sig_request) else: session['logged_in'] = False flash('wrong password!') else: sig_response=request.form['sig_response'] authenticated_username = duo_web.verify_response(ikey, skey, akey, sig_response) if authenticated_username: session['logged_in'] = True session['user']=authenticated_username return home() return home()
def prepareForStep(self, configurationAttributes, requestParameters, step): context = Contexts.getEventContext() duo_host = configurationAttributes.get("duo_host").getValue2() credentials = Identity.instance().getCredentials() user_name = credentials.getUsername() if (step == 1): print "Duo. Prepare for step 1" return True elif (step == 2): print "Duo. Prepare for step 2" duo_sig_request = duo_web.sign_request(self.ikey, self.skey, self.akey, user_name) print "Duo. Prepare for step 2. duo_sig_request: " + duo_sig_request context.set("duo_host", duo_host) context.set("duo_sig_request", duo_sig_request) return True else: return False
def get(self): if self.both_logged_in(): self.redirect('/') return user = users.get_current_user() if not user: self.redirect('/') return (username, _) = self.user_email_parts(user) sig_request = duo_web.sign_request(ikey, skey, akey, username) self.response.out.write( "<html>" " <head>" " <title>Duo Authentication</title>" " <meta name='viewport' content='width=device-width, initial-scale=1'>" " <meta http-equiv='X-UA-Compatible' content='IE=edge'>" " <link rel='stylesheet' type='text/css' href='/static/Duo-Frame.css'>" " </head>" " <body>" " <h1>Duo Authentication</h1>" " <script src='/static/Duo-Web-v2.js'></script>" " <iframe id='duo_iframe'" " frameborder='0'" " data-host='%(host)s'" " data-sig-request='%(sig_request)s'" " data-post-action='%(post_action)s'" " >" " </iframe>" " </body>" "</html>" % { 'host': host, 'sig_request': sig_request, 'post_action': self.request.uri })
def duo(): username = request.form["username"] ikey = config.DUO_IKEY skey = config.DUO_SKEY akey = config.SECRET host = config.DUO_HOST sig_request = duo_web.sign_request(ikey, skey, akey, username) return render("duo.html", host=host, sig_request=sig_request)
def mfa(): result = grab_keys() sec = duo.sign_request(result['ikey'], result['skey'], result['akey'], "admin") if request.method == 'GET': return render_template('duoframe.html', duohost=result['host'], sig_request=sec) if request.method == 'POST': user = duo.verify_response(result['ikey'], result['skey'], result['akey'], request.args.get('sig_response')) if user: return render_template(url_for('mfa'), user=user)
def login(request): """ View to authenticate the user locally and with Duo, redirecting to the next argument if given. For a GET, show the Duo form, which posts back with the Duo token. For a POST with successful authorization, redirect to the next argument, or show some default content. Without successful authorization, redirect back here to try again. """ if request.method == 'GET': message = request.GET.get( 'message', 'Secondary authorization required.') next_page = request.GET.get('next') sig_request = duo_web.sign_request( settings.DUO_IKEY, settings.DUO_SKEY, settings.DUO_AKEY, duo_username(request.user)) print duo_username(request.user) context = { 'message': message, 'next': next_page, 'duo_css_src': '/'.join([settings.STATIC_URL, 'Duo-Frame.css']), 'duo_js_src': '/'.join([settings.STATIC_URL, 'Duo-Web-v2.js']), 'duo_host': settings.DUO_HOST, 'post_action': request.path, 'sig_request': sig_request } return render(request, 'duo_login.html', context) elif request.method == 'POST': return HttpResponse('failed') sig_response = request.POST.get('sig_response', '') duo_user = duo_web.verify_response( settings.DUO_IKEY, settings.DUO_SKEY, settings.DUO_AKEY, sig_response) next_page = request.POST.get('next') if duo_user is None: # Redirect user to try again, keeping the next argument. # Note that we don't keep any other arguments. arg_map = {'message': 'Duo access denied.'} if next_page: arg_map['next'] = next_page redirect_url = '%s?%s' % ( request.path, urlencode(arg_map)) return HttpResponseRedirect(redirect_url) else: duo_authenticate(request) if not next_page: next_page = settings.LOGIN_REDIRECT_URL return HttpResponse('ok') return HttpResponseRedirect(next_page)
def mfa(): result = grab_keys() sec = duo.sign_request(result['ikey'], result['skey'], result['akey'], session['user']) if request.method == 'GET': return render_template('duoframe.html', duohost=result['host'], sig_request=sec) if request.method == 'POST': user = duo.verify_response(result['ikey'], result['skey'], result['akey'], request.args.get('sig_response')) if user == session['user']: return render_template(url_for('mfa'), user=user)
def test_sign_request_bytestring_username(self): """ Tests that duo_web will produce an encoding error for bytestring usernames in Python 3 (you cannot encode a bytes object in PY3) and will reject bytestring usernames in PY2 if they contain non-ASCII characters. """ if sys.version_info[0] == 2: username = bytes("testüser") else: username = bytes("testüser", "utf-8") bytestring_request_sig = duo_web.sign_request( IKEY, SKEY, AKEY, username) self.assertEqual(duo_web.ERR_USER_ENCODING, bytestring_request_sig)
def test_sign_request_bytestring_username(self): """ Tests that duo_web will produce an encoding error for bytestring usernames in Python 3 (you cannot encode a bytes object in PY3) and will reject bytestring usernames in PY2 if they contain non-ASCII characters. """ if sys.version_info[0] == 2: username = bytes("testüser") else: username = bytes("testüser", "utf-8") bytestring_request_sig = duo_web.sign_request(IKEY, SKEY, AKEY, username) self.assertEqual(duo_web.ERR_USER_ENCODING, bytestring_request_sig)
def login(request): """ View to authenticate the user locally and with Duo, redirecting to the next argument if given. For a GET, show the Duo form, which posts back with the Duo token. For a POST with successful authorization, redirect to the next argument, or show some default content. Without successful authorization, redirect back here to try again. """ if request.method == 'GET': message = request.GET.get( 'message', 'Secondary authorization required.') next_page = request.GET.get('next') sig_request = duo_web.sign_request( settings.DUO_IKEY, settings.DUO_SKEY, settings.DUO_AKEY, duo_username(request.user)) template = loader.get_template('duo_login.html') context = RequestContext( request, {'message': message, 'next': next_page, 'duo_css_src': '/'.join([settings.STATIC_URL, 'Duo-Frame.css']), 'duo_js_src': '/'.join([settings.STATIC_URL, 'Duo-Web-v2.js']), 'duo_host': settings.DUO_HOST, 'post_action': request.path, 'sig_request': sig_request}) return HttpResponse(template.render(context)) elif request.method == 'POST': sig_response = request.POST.get('sig_response', '') duo_user = duo_web.verify_response( settings.DUO_IKEY, settings.DUO_SKEY, settings.DUO_AKEY, sig_response) next_page = request.POST.get('next') if duo_user is None: # Redirect user to try again, keeping the next argument. # Note that we don't keep any other arguments. arg_map = {'message': 'Duo access denied.'} if next_page: arg_map['next'] = next_page redirect_url = '%s?%s' % ( request.path, urllib.urlencode(arg_map)) return HttpResponseRedirect(redirect_url) else: duo_authenticate(request) if not next_page: next_page = settings.LOGIN_REDIRECT_URL return HttpResponseRedirect(next_page)
def post(self): """Override the default POST handler. If the Duo signed response isn't present, do primary auth and POST back to the same URL with the request. If the response is present, call the stock LoginHandler post method, which will call DuoAuthenticator.authenticate() to perform verification of the response. """ # parse the arguments dict data = {} for arg in self.request.arguments: data[arg] = self.get_argument(arg, strip=False) sig_response = self.get_argument("sig_response", default=None) if sig_response: # Duo signed response present, do secondary auth yield LoginHandler.post(self) else: # no sig_response, do primary auth and generate the request auth = yield self.authenticator.do_primary_auth(self, data) if auth: if isinstance(auth, str): auth = dict(name=auth) sig_request = duo_web.sign_request(self.authenticator.ikey, self.authenticator.skey, self.authenticator.akey, auth.get('name')) html = self.render_template( 'duo.html', host=self.authenticator.apihost, sig_request=sig_request, auth_cache=base64.binascii.b2a_base64( json.dumps(auth).encode('ascii')).decode('ascii'), custom_html=self.authenticator.duo_custom_html) self.finish(html) else: html = self._render( login_error='Invalid username or password', username=data.get('username'), ) self.finish(html)
def get(self): if self.both_logged_in(): self.redirect('/') return user = users.get_current_user() if not user: self.redirect('/') return (username, _) = self.user_email_parts(user) sig_request = duo_web.sign_request(ikey, skey, akey, username) self.response.out.write( "<script src='/static/Duo-Web-v1.bundled.min.js'></script>" "<script>" "Duo.init({'host':'%(host)s', 'post_action':'%(post_action)s', " "'sig_request':'%(sig_request)s'});" "</script>" "<iframe height='100%%' width='100%%' id='duo_iframe' />" % {'host':host, 'post_action':self.request.uri, 'sig_request':sig_request})
def login(): result = get_duo() print('DUO: {}'.format(result)) print(session['user']) sig_request = duo_web.sign_request(result['ikey'], result['skey'], result['akey'], session['user']) print('sig_request: {}'.format(sig_request)) if request.method == 'GET': return render_template('duoframe.html', duohost=result['host'], sig_request=sig_request) elif request.method == 'POST': user = duo_web.verify_response(result['ikey'], result['skey'], result['akey'], request.args.get('sig_response')) print('AUTH: {}'.format(user)) if user == session['user']: return render_template(url_for('duo_auth.login'), user=user)
def get(self): if self.both_logged_in(): self.redirect("/") return user = users.get_current_user() if not user: self.redirect("/") return (username, _) = self.user_email_parts(user) sig_request = duo_web.sign_request(ikey, skey, akey, username) self.response.out.write( "<script src='/static/Duo-Web-v1.bundled.min.js'></script>" "<script>" "Duo.init({'host':'%(host)s', 'post_action':'%(post_action)s', " "'sig_request':'%(sig_request)s'});" "</script>" "<iframe height='100%%' width='100%%' id='duo_iframe' />" % {"host": host, "post_action": self.request.uri, "sig_request": sig_request} )
def login(): if request.method == "POST": email = request.form.get("email") password = request.form.get("password") user_values = user_db.query_user(email) if user_values: current_user = User(user_values['email'], user_values['password'], user_values['first_name'], user_values['last_name'], user_values['role']) if check_password_hash(user_values['password'], password): signal_request = duo_web.sign_request(config('DUO_I_KEY'), config('DUO_S_KEY'), config('DUO_A_KEY'), email) return redirect( url_for("auth.duo_login", sig_request=signal_request)) else: flash("Incorrect password") else: flash("No user exists with that username") return render_template("login.html")
def get(self, request): next_url = request.GET.get('next', settings.LOGIN_REDIRECT_URL) # Figure out which Duo App applies to the user's backend app_name, app = None, None auth_backend = request.session[BACKEND_SESSION_KEY] logger.debug( 'Checking for Duo app to follow after backend: {0}'.format( auth_backend)) for k, v in settings.DUO_CONFIG.items(): if auth_backend in v.get('FIRST_STAGE_BACKENDS', []): app_name, app = k, v break else: # If none, skip Duo request.session['DUO_STATUS'] = 'SKIPPED' return redirect(next_url) username = self.get_username(app, request) sig_request = duo_web.sign_request(app["IKEY"], app["SKEY"], app["AKEY"], username) logger.info('User {0} started Duo using app {1}'.format( username, app_name)) return render( request, 'duo_auth_form.html', { 'duo_css_src': os.path.join(settings.STATIC_URL, 'css', 'Duo-Frame.css'), 'duo_js_src': os.path.join(settings.STATIC_URL, 'javascript', 'Duo-Web-v2.js'), 'app_name': app_name, 'next': next_url, 'duo_host': app["HOST"], 'post_action': request.path, 'sig_request': sig_request })
def login_route(): if request.method == "GET": return render_template("login.html") if request.method == "POST": username = request.form["username"] password = request.form["password"] if not username or not password: flash("Please Enter Both Fields") return render_template("login.html") print username print password c.execute("SELECT * from users") print c.fetchall() c.execute("SELECT username, password FROM users where username=? and password=?", (username, password)) user = c.fetchone() print user if user: sig_request = sign_request(ikey, skey, akey, username) return render_template("duo_login.html", sig_request=sig_request, post_action=request.path) else: flash("Inavlid Password") return render_template("login.html")
def register_route(): if request.method == "GET": return render_template("register.html") elif request.method == "POST": username = request.form["username"] password = request.form["password"] if not username or not password: flash("Please enter both fields") return render_template("register.html") else: # check if username is in db user = c.execute("SELECT * FROM users WHERE username=?", (username,)).fetchall() print user if user: flash("The username already exists") return render_template("register.html") sig_request = sign_request( "DIFRGMA77D2LMZYAESSU", "3PaauXz74LrY9l7aEVxdrbeP8IryyNhToMBemr3I", akey, username ) c.execute("INSERT INTO users (username, password) values (?,?)", (username, password)) conn.commit() return render_template("duo_login.html", sig_request=sig_request, post_action=request.path)
def prepareForStep(self, configurationAttributes, requestParameters, step): duo_host = configurationAttributes.get("duo_host").getValue2() identity = CdiUtil.bean(Identity) credentials = identity.getCredentials() user_name = credentials.getUsername() if (step == 1): print "Duo. Prepare for step 1" return True elif (step == 2): print "Duo. Prepare for step 2" duo_sig_request = duo_web.sign_request(self.ikey, self.skey, self.akey, user_name) print "Duo. Prepare for step 2. duo_sig_request: " + duo_sig_request identity.setWorkingParameter("duo_host", duo_host) identity.setWorkingParameter("duo_sig_request", duo_sig_request) return True else: return False
def test_sign_request(self): request_sig = duo_web.sign_request(SKEY, IKEY, USER) self.assertNotEqual(request_sig, None)
class Login(Handler): """ Handles OpenID requests: associate, checkid_setup, checkid_immediate, check_authentication. """ def post(self): try: oidrequest = oidserver.decodeRequest(self.arg_map(self.request)) if oidrequest is None: self.report_error('no OpenID request') return self.verify_request(oidrequest, self.request) except OpenIDServer.ProtocolError, exc: self.render_response(exc) return logging.debug('Login: mode %s' % oidrequest.mode) if oidrequest.mode in ['associate', 'check_authentication']: logging.debug('Login: responding to %s' % oidrequest.mode) self.respond(oidserver.handleRequest(oidrequest)) return elif oidrequest.mode in ['checkid_immediate', 'checkid_setup']: user = users.get_current_user() logging.debug('Login: user %s' % user) if user is None: logging.debug('Login: no user') if oidrequest.mode == 'checkid_immediate': self.respond(oidrequest.answer(False)) return else: # This will run into problems if the URL is too long, # we're trying to stuff a POST into a GET. A popup is # probably the only safe way. self.redirect( users.create_login_url( '%s?%s' % (self.request.uri, urllib.urlencode(self.arg_map(self.request))))) return check_id = self.check_user(user, self.request) if check_id is None: logging.debug('Login: no identity') self.respond(oidrequest.answer(False)) return elif not check_id: logging.debug('Login: wrong identity for user %s' % user) if oidrequest.mode == 'checkid_immediate': self.respond(oidrequest.answer(False)) return else: # Would be nicer to allow the user to login as the correct # user and keep the auth flow self.render_template('index', { 'user': user, 'logins': self.logins(user) }) return identity_url = self.get_identity_url(user, self.request) if self.has_cookie(self.request, oidrequest.trust_root, identity_url): logging.debug('Login: has cookie, accepting') self.store_login(oidrequest, 'remembered') # provider SHOULD verify return_to #oidrequest.returnToVerified() self.respond(oidrequest.answer(True, identity=identity_url), user) return else: if oidrequest.mode == 'checkid_immediate': logging.debug('Login: declining') self.respond(oidrequest.answer(False)) return else: logging.debug('Login: prompting') # Collect arguments for the template/JS to pass to # our prompt. Note that these could be modified by the # user. post_args = oidrequest.message.toPostArgs() # these may have been identifier_select post_args['openid.claimed_id'] = identity_url post_args['openid.identity'] = identity_url post_args['trust_root'] = oidrequest.trust_root self.render_template( 'secondary_auth', { 'postargs': post_args, 'post_action': '/prompt', 'sig_request': duo_web.sign_request(skey, ikey, self.duo_username(user)), 'host': host })