# Connecting User Accounts
Kloudless provides an OAuth 2.0 flow to authenticate users and provide your application with an access token to use to perform API requests to that user's Account.
In addition, your application's confidential API Key can be used to access data for any Account connected to your application.
# Using the Authenticator
In this article, we'll use Kloudless' Authenticator JS, an open-source library that prompts a user to grant access to a given cloud service. We will set up a basic web server to render a page that launches the Authenticator, which completes the OAuth flow on the client-side via a pop-up. You can find detailed documentation on the Authenticator on its GitHub page here.
# Web server
In this example, our web server's purpose is to enable a user to save arbitrary text to a text file in their cloud storage account via our app.
# HTML page
The HTML form below contains two hidden input fields that must be populated with the ID of the cloud storage account, and a bearer token to access it, so that our backend server can perform the API request to upload the file.
<form action="/post" method="post">
<input type="hidden" name="access_token" id="access_token" value="">
<input type="hidden" name="account_id" id="account_id" value="">
<div>
<input type="text" name="fileName" placeholder="file-name.txt">
</div>
<div>
<textarea name="file_body" rows="7">File text here.</textarea>
</div>
<div>
<button id="upload" type="submit" disabled>Create and upload file</button>
</div>
</form>
To authenticate the user, include a script tag on the page that sources the Authenticator JS library as documented in the Authenticator's README.
<script type="text/javascript"
src="https://static-cdn.kloudless.com/p/platform/sdk/kloudless.authenticator.js"></script>
This exposes a global Kloudless
object that contains the method
Kloudless.auth.authenticator
, which we'll use to trigger an
authentication pop-up for the end-user.
# JavaScript
In the Kloudless.auth.authenticator
call below:
$element
is the DOM element to click to launch the pop-up, or a jQuery object representing one.config
includes additional query parameters to include in the OAuth flow. At a minimum, this must include the Kloudless application ID as the OAuth Client ID. It can also include ascope
, as documented in the Scopes article, to display a subset of services.callback
is a JS callback method that receives the results of the OAuth flow.
$(document).ready(() => {
const config = {
'client_id': '[INSERT YOUR CLIENT ID HERE]',
'scope': 'storage',
};
// Assumes a button with ID "auth" on the page to launch the pop-up.
var $element = $("#auth");
let auth = Kloudless.auth.authenticator($element, config, callback);
});
The callback
method above should handle errors as well as successful
responses.
let callback = function (result) {
if (result.error) {
console.log('An error occurred:', result.error);
return;
}
$("#account_id").val(result.account.id);
$("#access_token").val(result.access_token);
$("#upload").prop('disabled', false);
};
The JS should now look like below.
let callback = function (result) {
if (result.error) {
console.log('An error occurred:', result.error);
return;
}
$("#account_id").val(result.account.id);
$("#access_token").val(result.access_token);
$("#upload").prop('disabled', false);
};
$(document).ready(() => {
const config = {
'client_id': '[INSERT YOUR CLIENT ID HERE]',
'scope': 'storage',
};
// Assumes a button with ID "auth" on the page to launch the pop-up.
var $element = $("#auth");
let auth = Kloudless.auth.authenticator($element, config, callback);
});
We now have all the data in need to send to our server-side code to make an API request. We could also perform the API request via client-side JS if preferbale.
# Verifying Bearer Tokens
The form in the section above sends the server details of an account to upload a text file to. However, before we do so, it is important to verify that our the account was connected using our app, to prevent a Confused Deputy attack, which is when an attacker obtains access tokens through a compromised client or other mechanism and impersonates an end-user, potentially gaining access to privileged content otherwise only accessible to that user.
Use this endpoint on the server-side to verify the token.
Here is an example in a Node server:
axios.get('https://api.kloudless.com/v1/oauth/token', {
headers: {
'Authorization': 'Bearer ' + access_token
}
})
.then(function(response) {
if (response.data.client_id === KLOUDLESS_APP_ID) {
// handle successful verification
}
else {
// handle incorrect app
}
})
.catch(function(error) {
console.log(error);
})
Comparing the known client ID to the client ID returned from the GET request is the minimum amount of verification to perform.
With the token now verified, you can make an API call to Kloudless to upload the file to the identified location in the service using this API endpoint.
Scopes →