The nature of this tutorial ...
This tutorial is designed to walk you through DaniWeb's implicit (clientside) OAuth flow. This is not designed to be an introductory tutorial to OAuth, and we will expect that you are already familiar with the nature of OAuth and/or have read our tutorial on Getting started with OAuth 2.0 Explicit Flow.
The implicit flow allows you to acquire an access token and access the API entirely from within a browser-based javascript application. While this tutorial is specific to DaniWeb's API, we do adhere to OAuth standards, and so the flow should not be very different when working with other services.
Acquiring an access token with the implicit (clientside) flow
As with the explicit flow, the first step to using OAuth is to register your application with the service in order to generate a client_id
and client_secret
unique to your application. Because the entire application is browser-based and client-facing, we do not use the client_secret
because the end-user would have access to it by viewing the javascript source code from their web browser. Instead, the application authenticates itself by ensuring that it resides on the same domain name as you used when you registered your application.
Our implementation uses jQuery for convenience. You will need to include the jQuery library if you plan on using our example within your own application.
Step 1
The first step is to load the service's authorization dialog in a popup window, along with a way to get back.
// Load a popup window pointing to the OAuth dialog
var url = 'https://www.daniweb.com/api/oauth?response_type=token&client_id='
+ client_id + '&redirect_uri=' + window.location;
// We set the location for the popup after we create it to workaround
// popup blockers that have a same-origin policy
// Most popup blockers will allow popups that are user-initiated but
// not ones that open automatically at page load; You will most likely
// want to modify this so that the dialog opens upon clicking a link
// or button or in some user-initiated way (which it doesn't)
var dialog = window.open('', 'oauth', 'height=460,width=1180');
dialog.location = url;
In the above code, we opened up a dialog window pointing to https://www.daniweb.com/api/oauth with the following query-string parameters:
- response_type (Required): Defines what we want to be returned to us, so we set this to
token
. - redirect_uri (Required): Set to your redirect URI, which is the way that the service returns the end-user to your web-based application. It MUST reside on the same domain as was used to register the application.
- client_id (Required): Set to your application's ID #.
You will notice that here we are requesting a response of a token
as opposed to code
as we do with a serverside implementation. When working with a serverside implementation, the authorization process returns us a code which we can then use to exchange for an access token. When working with a clientside implementation, however, we are immediately granted an access token as a result of the authorization process.
Step 2
Upon authorizing that your application can access their account, the popup will be redirected to your Redirect URI and an access token will be passed along in the hash of the URI.
Once the popup redirects back to our URI, the popup window has served its purpose and we will want to close it. However, before we can do so, we need to extract the hash from it that includes the access token. We can copy the hash from the popup window and move it into the hash of the main browser window.
// Check to see if this page is loaded in the popup we created
if (window.opener != null && !window.opener.closed)
{
// Copy the hash (which includes the access token) received from the
// OAuth process to the main window for parsing and close the popup
opener.location.hash = window.location.hash;
window.close();
}
Step 3
In the below code snippet, we use a jQuery event listener to listen for a hash change in the URI of the main browser window.
// Event listener for a hash change in the URI
$(window).on('hashchange', function() {
// If the URI hash changed and it's not empty ...
if (window.location.hash != '')
{
// TODO: ...
}
});
Step 4
Once we have detected a hash change, we can parse the hash to gain access to the access token. The actual format of the hash will look like the following: http://www.example.com#access_token=12345abcdef&expires_in=86400
Note that the expires_in
parameter indicates that the access token will expire in 86,400 seconds, or 24 hours.
The following code snippet fetches the hash of the currently opened web page and put it into a variable called string
. However, once we have a string that looks like access_token=12345abcdef&expires_in=86400
we will need to do some manipulation to make sense out of it.
First, we split the string into an array using the ampersand character as the delimiter. Therefore, we end up with an array that fits the following schema:
array
{
[0] => 'access_token=12345'
[1] => 'expires_in=86400'
}
Then, we iterate over each item in the array (in this case, there are only 2 items), splitting each string using the equals sign character as the delimiter. Within our loop, we check the value of the first parameter of the newly-created array. If it is equal to the string 'access_token'
then we know that the second parameter of the array is the value of the access token.
var string = window.location.hash.substr(1);
var query = string.split('&');
var param;
// Parse the URI hash to fetch the access token
for (var i = 0; i < query.length; i++)
{
param = query[i].split('=');
if (param[0] == 'access_token')
{
access_token = param[1];
break;
}
}
Step 5
Now that we have an access token, we can pass it into our API requests. When making API calls from within javascript-based applications, we always want to pass in a callback parameter. The callback parameter allows us to receive a response in JSONP format, as opposed to a typical JSON string. JSONP, or padded JSON, wraps the result in a callback function. (We can optionally specify the name of the callback function as the parameter's value.) Doing so is actually a technique that is used as an effective workaround for the same-origin policy which typically prevents web browsers from sending AJAX requests to a different domain and receiving a response. Please visit the jQuery AJAX documentation related to JSONP for more information, but the details are out of the scope of this tutorial.
$.getJSON('https://www.daniweb.com/api/me?access_token=' + access_token + '&callback=?', function(response) {
alert('Hi, ' + response.data.username + '!');
});
Here we put everything together and we end up with the following workable demo. In this example, we used a jQuery event handler to load the popup window upon clicking on a link.
<a href="#" id="click-here">Connect to DaniWeb</a>
<script type="text/javascript">
<!--
var client_id = '';
var access_token;
/***********************************************************************************/
/* THE END-USER NEEDS TO AUTHORIZE OUR APPLICATION SO WE CAN FETCH AN ACCESS TOKEN */
/***********************************************************************************/
/*******************************/
/* LOAD THE POPUP OAUTH DIALOG */
/*******************************/
$('#click-here').on('click',function() {
// Load a popup window pointing to the OAuth dialog
var url = 'https://www.daniweb.com/api/oauth?response_type=token&client_id=' + client_id + '&redirect_uri=' + window.location;
var dialog = window.open('', 'oauth', 'height=560,width=1080');
dialog.location = url;
});
/***************************/
/* DO STUFF WITH THE POPUP */
/***************************/
$(function() {
// Check to see if this page is loaded in the popup we created
if (window.opener != null && !window.opener.closed) {
// Copy the hash (which includes the access token) received from the
// OAuth process to the main window for parsing and close the popup
opener.location.hash = window.location.hash;
window.close();
}
else {
// Event listener for a hash change in the URI
$(window).on('hashchange', function() {
// If the URI hash changed and it's not empty ...
if (window.location.hash != '') {
var string = window.location.hash.substr(1);
var query = string.split('&');
var param;
// Parse the URI hash to fetch the access token
for (var i = 0; i < query.length; i++) {
param = query[i].split('=');
if (param[0] == 'access_token') {
access_token = param[1];
break;
}
}
// We now have the access token
if (access_token !== undefined) {
connectToDaniWeb();
}
}
});
}
});
function connectToDaniWeb() {
/***********************************************************************************/
/* SUCCESS! WE HAVE AN ACCESS TOKEN! NOW WE CAN PASS IT INTO REQUESTS AND DO STUFF */
/***********************************************************************************/
// Fetch ME!
$.getJSON('https://www.daniweb.com/api/me?access_token=' + access_token + '&callback=?', function(response) {
alert('Hi, ' + response.data.username + '!');
});
}
//-->
</script>
Here is a live demo of the implicit OAuth flow with the DaniWeb API.