Defining the Endpoints
00:00
This is where the rubber hits the road. It’s time to define the endpoints for the demo app. There are four of them. First is a homepage. It will be mapped to the URL /
. Second is the login endpoint, mapped to the URL /login
.
00:16
Third is the logout endpoint, mapped to the URL /logout
. And the final endpoint is the callback, which Google will redirect the user to after they’ve been authenticated. Recall the URL of /login/callback
was given to Google during the registration process.
00:34
Start off with the homepage. The route
decorator on the Flask app
object accepts the URL that will be mapped to a handler function.
00:43
The function itself just returns some HTML. It will look at the current_user
object from Flask-Login
. The current_user
is an instance of the User
class.
00:54
The .is_authenticated
property of the User
class will be True
when a user is logged in. So if there’s a user logged in, display the profile information for the user.
01:04
Otherwise, display a link to the login page. Speaking of the /login
route, it does the heavy lifting of kicking off the OAuth 2 flow. But first, create a helper function that will get the provider configuration from the .well-known/
discovery endpoint. Here, you can see the power of the requests
module. To make a basic GET
request, call the get()
function and pass it a URL.
01:28
The response will be in JSON format. The login()
handler will be mapped to the /login
route. Get the authorization endpoint from the provider configuration.
01:40 Use the OAuth client class to construct a URL which will start the Google login. Notice that it includes the authorization endpoint from the provider configuration, the redirect URI you registered with Google, and a list of scopes, which are the types of data your app is requesting access to. The scopes are displayed to the user on the consent screen. Redirect the user to the URL, which will request them to log in with their Google account.
02:07
You’ll see this in a minute when you run the app, but after logging in, the user will be taken to the consent screen. Assuming they authorize your app, Google will then redirect to the callback URL /login/callback
. Define that route in the handler next.
02:23
Remember that Google will send an authorization code back to your app. It will be in the query string as the key "code"
. Your app needs to send that code back to Google and exchange it for tokens.
02:35 First, retrieve the token endpoint from the provider configuration.
02:40 Use the OAuth2 client again to construct a URL to call and get the token.
02:47
Now, call the token URL to generate and receive the actual token. Notice that this is a POST
request. Also, this is where you provide the client ID and secret to verify the identity of your app.
03:02 The token itself will be in JSON format. The OAuth client can then parse the tokens out of the JSON data. Armed with a token, you can use it to get the profile information to show for authenticated users on the homepage.
03:16 The URL to get the profile is also in the provider configuration. Construct a URL that uses the token and call it to get a response with the profile data. Congratulations!
03:30 If you get this far, the hard work is done. All that is left is to pull the profile data out of the response. The profile data is available after a user has verified their email address, so check for that first. If so, get the JSON from the user response and pull the individual profile values out.
03:50
If the email address is not verified, return an error and a status code of 400
for a Bad Request
.
03:58
Use the profile values to create a new User
and insert it into the database, if it does not exist.
04:07
Finally, you can log the user into your app… and redirect the user to the homepage. The url_for()
function accepts the name of a request handler function.
04:19 It will generate a URL for that function based on the route that decorates it. You’re almost done. What comes up must eventually come down, and what is logged in must eventually get logged out. Create a logout route and handler function.
04:34
The logout_user()
function will log out the current user. After logout, redirect the user back to the homepage. The logout()
handler should only be valid for logged in users.
04:47
Add the @login_required
decorator to the handler function. If a user tries to access the URL without logging in, they will be redirected to the login page. To run the application, add an entry point and then call the .run()
method on the Flask app.
05:03
This will start the server on the localhost
address and listen on port 5000
. But Google requires the callback endpoint to use SSL. Add the ssl_context
keyword argument to the .run()
method to enable SSL.
Become a Member to join the conversation.
ynotmarygrace on Feb. 8, 2021
Why is it that
create
is not available forUser
object?