Newer
Older
from flask import abort, Flask, redirect, request, render_template
app.debug = True if "FLASK_ENV" in environ and environ["FLASK_ENV"] == "development" else False
@app.route('/login', methods=['GET', 'POST'])
"""Provides login form and handles login attempt
Args:
login_form: contains login data submitted by a user (POST)
challenge: id that identifies the request from oauth client. passed by hydra
Error page if no challenge id is present
or Login Form if user hasn't authenticated
or redirect to callback url provided by hydra if login was successful
redirect_to = None
# Retrieve the challenge id from the request. Depending on the method it is saved in the
# form (POST) or in a GET variable.
if request.method == 'GET':
challenge = request.args.get("login_challenge")
if not challenge:
elif login_form.validate_on_submit():
challenge = login_form.challenge.data
# Now that we have the challenge id, we can request the challenge object from the hydra
# admin API
except hydra_client.exceptions.NotFound:
app.logger.error("Not Found. Login request not found. challenge={0}".format(challenge))
abort(404)
except hydra_client.exceptions.HTTPError:
app.logger.error("Conflict. Login request has been used already. challenge={0}".format(challenge))
abort(503)
# We need to decide here whether we want to accept or decline the login request.
# if a login form was submitted, we need to confirm that the userdata, the agent
# send us via POST is valid
try:
user = User(login_form.username.data)
except BackendConnectionError as error:
app.logger.error(
"Retrieving user object from GraphQL server failed {0}".format(error))
return redirect(login_request.reject(
"Login denied",
error_description="Login request was denied due to an internal server error"))
redirect_to = login_request.accept(
user.username,
remember=login_form.remember.data,
app.logger.info("{0} logged in successfully".format(user.username))
else:
redirect_to = login_request.reject(
"Login denied",
error_description="Invalid username or password")
app.logger.info("{0} failed to login".format(user.username))
# Skip, if true, let's us know that Hydra has already successfully authenticated
# the user. we don't need to check anything and we can accept the request right away.
elif login_request.skip:
skip = request.args.get("skip")
logout = request.args.get("logout")
if skip:
app.logger.info("{0} is already logged in. Skip authentication".format(login_request.subject))
return redirect(login_request.accept(login_request.subject))
elif logout:
login_form.challenge.data = challenge
HYDRA.invalidate_login_sessions(login_request.subject);
return redirect(login_request.reject(
"Login cancelled",
error_description="Login was cancelled and user session was terminated"))
else:
return render_template('skip.html', challenge=challenge, logo=login_request.client.logo_uri, application_name=login_request.client.client_name, username=login_request.subject)
# If Skip is not true and the user has not submitted any data via a form, we need
# to display a login form for the user to type in their username and password.
# as a reference we save the challenge id in a hidden field of the form.
return render_template('login.html', login_form=login_form, logo=login_request.client.logo_uri, application_name=login_request.client.client_name)