This tutorial covers the necessary steps to build a basic Express app which interacts with the Socialtables API on behalf of your users. We'll cover the following topics:
If you're not familiar with Express, you may also want to read the Express docs. You can find a completed example project implementing this tutorial's instructions, as well as some examples of interactions with user data, on Github.
In order to interact with Socialtables, your app needs an OAuth client ID and secret. To obtain these credentials, you'll want to create an app through our developer portal.
Once you have created an app, you should see an OAuth client ID and secret on its detail page. Write that down.
When a user authenticates through Socialtables, an app receives an OAuth bearer token which is used to make API calls on their behalf. This section focuses on the necessary steps to obtain a bearer token through an authorization code grant.
To complete an authorization code handshake, you'll need to create a mechanism to direct the user to Socialtables' auth page, add a handler for the ensuing redirect, and finally implement an API call to exchange the authorization code for a bearer token.
Let's start with initiating the handshake. We'll create a route which will direct the
user to https://auth.socialtables.com/oauth/authorize
.
/**
* Route which initiates an OAuth authorization_code grant handshake with Socialtables
*/
app.get("/oauth/login-with-socialtables", function(req, res) {
var oauthAuthorizeURL = "https://auth.socialtables.com/oauth/authorize" +
"?client_id=" + encodeURIComponent( YOUR_CLIENT_ID ) +
"&redirect_uri=" + encodeURIComponent( YOUR_REDIRECT_ENDPOINT_URL ) +
"&grant_type=authorization_code" +
"&response_type=code";
res.redirect(oauthAuthorizeURL);
});
Here's an explanation of the query parameters in this redirect:
Next, we'll create a handler for the user to return to after authentication.
var request = require("request-promise");
/**
* Handles authorization code redirect from social tables
*/
app.get("/oauth/redirect", function(req, res) {
// if the response indicated rejection, report the issue to the user
if (req.query.error || !req.query.code) {
res.render("error", {
error: req.query.error_description || "authorization failed"
});
}
// if we have an authorization_code, request an access_token from the API
else {
var authorization_code = req.query.code;
request({
method: "POST",
uri: "https://api.socialtables.com/oauth/token",
form: {
code: authorization_code,
client_id: YOUR_CLIENT_ID,
client_secret: YOUR_CLIENT_SECRET,
grant_type: "authorization_code",
response_type: "token"
},
resolveWithFullResponse: true,
json: true
})
.then(function(tokenResp) {
// if we got a token back, add it to the active session
// and redirect to the root url; the user is now authenticated
if (tokenResp.statusCode === 200) {
if (tokenResp.body) {
req.session.oauth_access_token = tokenResp.body.access_token;
return res.redirect("/");
}
}
return res.render("error", { error: "failed to get an access token" });
})
.catch(function(err) {
res.render("error", { error: "failed to get an access token" });
});
}
});
Note the use of a local session and error handling.
In addition to setting up the routes within our project, we'll need to tell Socialtables what URL we will be redirecting users to in advance to keep malicious third-parties from having user credentials sent to them. To do this, navigate to your app's edit page and add your redirect URL.
So you've got an OAuth token, but what can you do with it? Well, for starters,
you can use it to get basic information about itself through the /oauth/token
GET
endpoint, and then used the retrieved user ID to get information about your user
using the /users/{userID}
GET endpoint. Here's an example of how you can do
this in middleware:
// apply middleware to set the current user based on their OAuth bearer token
app.use(function(req, res, next) {
req.user = null;
// if the session contains a token, look it up
if (req.session.oauth_access_token) {
var authHeaders = {
Authorization: `Bearer ${req.session.oauth_access_token}`
};
// make a request for user details corresponding to the token
request({
method: "GET",
headers: authHeaders,
uri: "https://api.socialtables.com/4.0/oauth/token",
json: true
})
.then(function(tokenDetails) {
// look up the user object based on the ID we recieved
var userID = tokenDetails.id;
req.userID = tokenDetails.v4_id;
req.legacyUserID = tokenDetails.legacy_id;
return request({
method: "GET",
headers: authHeaders,
uri: `https://api.socialtables.com/4.0/users/${userID}`,
json: true
});
})
.then(function(userDetails) {
// apply the user object to the request
req.user = userDetails;
next();
})
.catch(function(err) {
console.error("Error getting user details", err);
next();
});
}
// no token, no problem
else {
next();
}
});
Because Socialtables uses a split ID system between the V3 and V4 APIs, we add both to the request before using the V4 ID to retrieve user information.
You can find a completed example project implementing this tutorial's instructions, as well as some examples of interactions with user data, on Github.