Instant Login using an Implicit Grant
Use the OAuth 2.0 implicit grant flow to obtain bearer tokens in client-side Javascript or on a native device without access to client secrets.
In our traditional SSO flow, Clever sends users to a redirect URI on your sever with a code
parameter. After your server receives this, it initiates a request to Clever to exchange that code
for a bearer token representing the user. Your application may have initiated this flow with a Log in with Clever button or Clever may have initiated thee flow using the Clever Portal or an Instant Login Link.
This token exchange flow is simplified further in Clever's implicit grant flow. Instead of receiving a code
vaue that you must then exchange for a bearer token, Clever delivers the bearer token to your redirect URI as part of a URI fragment.
We still recommend implementing Clever's traditional SSO flow if you anticipate users signing in through Clever's launchpad or via other district-driven approaches. Some features districts rely on will not work with the Implicit Grant Flow exclusively. Additionally, district tokens cannot be negotiated with the implicit grant flow.
This feature is not generally available
For security reasons, the OAuth 2.0 implicit grant flow is only available to applications that cannot use the authorization grant flow outlined in Instant Login & the Identity API. If you cannot use the authorization grant flow, please reach out to [email protected]
Who is this for?
- Web applications authored in client-side Javascript or Flash
- Widely distributed open source applications
- Web browser extensions and plugins
- WordPress, Drupal, Moodle, or other platform extensions
- Native mobile applications
- Native desktop applications
Requirements
- You need the client ID of the application you're developing against Clever with. Locate your client ID by signing in to your Clever developer account and navigating to your application configuration. This ID is used to identify your application to Clever.
- You must register a redirect URI as part of your application record that will be used for the implicit grant flow. This may be an additional redirect URI or the same redirect URI you already use. You'll be handling URL fragments specially in this flow and you may want to separate concerns with a unique URL path.
The implicit grant flow, step by step
Let's examine this flow in more detail with a hypothetical example.
We have an application called Flight School. Here are some vitals on how we're configured.
Field | Value |
---|---|
Client ID | anVpY2VqdWljZWp1aWNlCg |
Redirect URIs | https://flightschool.edu/oauth , http://localhost/oauth , https://flightschool.edu/oauth/implicit , http://localhost/oauth/implicit |
Your configuration will look something like this. You'll definitely be using a different Client ID, and your redirect URIs will be your own. Regardless, you can complete this implicit grant flow.
I've decided to take my own advice and use a dedicated URI path which I'll use for the remainder of this example: https://flightschool.edu/oauth/implicit
.
Step 1: Present a "Log in with Clever" button
You may recall Log in with Clever buttons from Instant Login & the Identity API
In this flow, we're going to build our button with the response_type parameter set to token. This will instruct Clever to handle subsequent steps with the implicit grant flow. We'll also provide the redirect URI we decided on, properly URL escaped.
https://clever.com/oauth/authorize?response_type=token&redirect_uri=https%3A%2F%flightschool.edu%2Foauth%2F/implicit&client_id=anVpY2VqdWljZWp1aWNlCg&state=fb37f982-925b
Notice we've included the state
parameter - this is important! By randomly generating a nonce value and providing it here, Clever will send it back to your application in the next step. This allows you to validate that your application initiated this flow. We recommend using "opaque" values for state parameters — a human should not be able to understand what information is described in state. See Keeping Instant Login Secure for more information.
Clever authorizes the user
This step is identical to typical "Log in with Clever" usage. If the user is not yet signed in via Clever, they'll be prompted for their district-specific credentials before the next step. If they're already signed in, Clever will instantly send the user back to your redirect_uri
in the next step.
Clever sends the user to your redirect_uri along with a bearer token
After authorization, the user will be sent to your specified redirect_uri
with the user's bearer token attached to the URI fragment as an access_token
field.
Continuing our example, we might receive the end user at this variant of our redirect URI:
https://flightschool.edu/oauth/implicit#token_type=bearer&state=fb37f982-925b&access_token=ZWdnbWFuIGkgYW0gdGhlCg&scope=read%3Astudents%20read%3Ateachers%20read%3Auser_id
To extract the bearer token from the request and validate the state parameter, we first must evaluate the URI fragment.
What's a URI fragment?
URI fragments appear as the final element of a URI and begin with a hash character (#
). They are sometimes referred to a the hash component of a URL.
Consider the following imaginary URL: https://example.com/some/path?field0=value0#field1=value1&field2=value2
This URL has a few component parts:
- the scheme/protocol (
https://
) - the authority/host (
example.com
) - the path (
/some/path
) - the query string (
?field0=value0
) - the URI fragment (
#field1=value1&field=value2
)
Typically, a web server never receives a URI fragment. When you use a URL like this in a web browser, only https://example.com/some/path?field0=value0
is received by the server. The URI fragment is instead handled by the web browser. Your application programmatically gains access to the URI fragment only when the web browser is executing client-side Javascript. This is why this implicit grant flow is typically used in client-side Javascript applications.
Extracting the token from the URI fragment
The OAuth 2.0 implicit grant flow specifies that Clever present you a series of application/x-www-form-urlencoded
key/value pairs within the URI fragment. Your user agent (typically a web browser in this flow) is unlikely to provide you a direct way to convert that URI fragment string into an accessible data type, such as a Javascript associative array.
You'll need to use Javascript to evaluate the URI fragment string, extract the keys and values, and yield a traversable data structure. We recommend using an open source library to perform these extractions, such as jQuery BBQ. However, the following snippet should be functional for most Clever purposes.
// First, extract the URI fragment from the user agent's location object
function extractParamsFromURIFragment() {
var fragmentParams = {};
var e,
a = /\+/g, // Regex for replacing addition symbol with a space
r = /([^&;=]+)=?([^&;]*)/g,
d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
q = window.location.hash.substring(1);
while (e = r.exec(q)) {
fragmentParams[d(e[1])] = d(e[2]);
}
return fragmentParams;
}
Using a similar function, you could extract the bearer token and state with code similar to:
var params = extractParamsFromURIFragment();
var bearer_token = params['access_token'];
var state = params['state'];
var scope = params['scope'];
Server-side implications
Typically your server will still receive a simple request to your specified redirect_uri
even when you're handling it client-side.
You will not receive the data in the URI fragment and you should essentially treat these requests as a "no-op." One reason to separate concerns with distinct redirect URIs is so you don't have to worry about triggering your typical server-side redirect with these requests.
Identify bearer token authenticity with tokeninfo
Now that you've gotten ahold of your user's bearer token, you'll use it in REST API requests to Clever's data API.
Before using the bearer token, it is important to verify the token's legitimacy. The implicit grant flow pushes bearer tokens in your application's direction but just because you've received a token doesn't mean it necessarily came from Clever or was intended for your specific application.
To protect against the "confused deputy problem" and determine if the token is intended for your application and was produced by Clever, you must verify its authenticity and legitimacy by issuing an additional request to Clever.
Verifying is simple. Issue a HTTP GET request to https://clever.com/oauth/tokeninfo
and assert your bearer token and then validate the response.
If the bearer token received was jsfUI2131da2f
, your HTTP Authorization header and request may look something like this:
GET https://clever.com/oauth/tokeninfo
Authorization: Bearer jsfUI2131da2f
Success
If the token was issued by Clever, you should receive a HTTP 200 response with a JSON body containing a client_id
and the token's associated scopes. After receiving this response, compare the received client_id
to the client_id
associated with your application. If they are the same, proceed with storing the token and logging the user in to your application.
A typical success response will looking something like:
{
"client_id": "9122696a58e9c5ae3ad4",
"scopes": [
"read:user_id",
"read:teachers",
"read:students"
]
}
If the client_id does not match, discard the token and prevent the user from signing in.
Rejection
If the token was not issued by Clever, you should receive a HTTP 401 response. No need to evaluate the response's body — just knowing that it's a HTTP 401 should be enough for you to discard the token and prevent the user from signing in.
Technical failure
If Clever can't evaluate the token for some reason — usually due to some kind of internal error — we'll respond with a HTTP 500, HTTP 502, or HTTP 503 error. These errors don't necessarily imply the token is invalid, and you may want to retry the request or ask the user to attempt the login sequence again. Please use an exponential back off strategy if you intend to retry requests.
Use the bearer token to issue Data API requests
Exactly as you would if you had obtained the token through the authorization grant flow
Error Handling
In most cases, if there's a problem authorizing the end user or if you've constructed your oauth/authorize
URL incorrectly, there's no programmatic error condition to consume. Clever will not redirect the user to your specified redirect URI and you'll simply be left with an initiated login state that is never consummated.
That said, exceptional events do happen. In the event that something unusual happens and the user is authenticated through Clever and redirected to your redirect_uri
in an error state, we'll provide an error
parameter instead of an access_token
on the URI fragment you receive.
In practice, such errors are rarely programmatically recoverable based on their disposition. If you receive one of these errors, display a simple message to your end user and allow them to try again. Consult section 4.2.2.1 of the OAuth 2.0 specification for more information.
Updated less than a minute ago