Example SSO Application
Walking through the Clever SSO flow using an example Python application
In this guide, we'll look at a sample Python app called SquidWord and how it implements Clever SSO. For a general overview of SSO, check out our guide to SSO
SquidWord is hosted on Heroku - you can see the app at https://squidword.herokuapp.com/ - the code for SquidWord can be found here: https://github.com/mlezeng/squidword. This application makes use of the web
, os
and requests
libraries.
The sandbox district contains the same data as the default sandbox, so you can use any of those credentials to log in. For example:
- Student:
310100
/310100
- Teacher:
092643
/092643
- If you're logging with the "Log in with Clever" button on the main page, search 53ee4b8a44abc88c1c00119b in the school picker to reach the district login page.
You can also connect your sandbox account to Squidword by clicking its signup URL: https://clever.com/signup/squidword-dev and log in as users from your sandbox district.
Next, we'll walk through all the steps SquidWord takes to authenticate a user.
Defining the Redirect URI & Key Variables
On line 7 & 13 of bin/app.py, we've defined the redirect URI - this must match at least one of the redirect URIs you've listed in your app's OAuth Settings.
The class that dictates the actions taken on this page (IL
) starts on line 137 of bin/app.py.
You'll also notice SquidWord's Client ID and Client Secret (which can be found in the OAuth Settings page in your Clever Dashboard) - are stored as environment variables and are called using os (lines 11-12)
Acquiring the Code
When a user loads SquidWord's redirect URI, we expect them to have been redirected there by Clever. When they are redirected, the URI in the user's browser should look something like this: https://squidword.herokuapp.com/oauth/clever/?code=5e87ec5070ac5ce87da97daac069a82f6c95818d&scope=read%3Auser_id%20read%3Adistrict_admins%20read%3Aschool_admins%20read%3Asis
SquidWord uses web.input to grab the code and scope params, setting the value to None if these params are not present. If these are not present, it shows the Index page instead (which includes a Log in with Clever button) so the user can initiate a login via Clever.
Exchanging the Code for a Token
getToken(code)
is called from line 155 - this POSTs to https://clever.com/oauth/tokens
with the aquired code
, my redirect_uri
, and the grant_type
, which is authorization code
. The POST uses basic authorization based on SquidWord's client_id
and client_secret
.
As long as the following conditions are met:
code
is validredirect_uri
matches the redirecrt URI where the app received the codeclient_id
andclient_secret
are valid
Clever should respond with a token. getToken
extracts the token from the response and returns it to IL
.
Using the Token
Once the token is acquired,IL
uses that token to GET the https://api.clever.com/me endpoint - this endpoint should return the user's Clever id
, district
ID, and user type
.
Creating a User
IL
then attempts to create a new User with this information. class User
's: __new__
function uses the same IL bearer token against the /type
s/id
endpoint to get the user's name, and returns the User object.
First and last name will always be present, but middle name may not. Because of this, the
__new__
function must first check to see if that field exists in the API response.
IL
will then show the user a home page, which displays the first name and user type pulled from the User object (and a great squid gif).
Updated 3 months ago