Skip to content

Create a simple credentials endpoint

The simple credentials endpoint requires no user-identity to be sent to the server. It simply receives a request for new API credentials, uses the key and secret, and then returns the credentials to the client. This type of flow is useful for developers or apps with an existing user-validation flow, or who are able to utilize domain whitelisting and/or are hosting their own app.

Setup

There are a few resources you'll need before you start writing code.

  • An account. This is your developer account on the Hub.
  • A user group key. This is how your users will be able to access your Hub APIs. Consider creating the key in an organization not your personal account so that you can invite collaborators later.
  • A new Typescript project. We recommend using Typescript, as Textile libraries are in a stage rapid of development and type detection is valuable during upgrades.
  • A server framework. The example below uses KoaJS but could just as easily be written for Express or the basic Node server.

Install dependencies

# Textile libraries
npm install --save @textile/hub

# Other utilities use in example
npm install --save dotenv isomorphic-ws

# Libraries specific to our server framework, koajs
npm install --save koa koa-router koa-logger koa-json koa-bodyparser

Environment variables

We'll use a .env file in the root of our project repo where you'll add your Hub API key and secret. The .env file should be added to your .gitignore so that your key and secret are never shared.

Contents of .env.

USER_API_KEY=alk3rlkjvl323r09fqpoweruw34
USER_API_SECRET=balkweop3jflk9f43lkjs9df2jlght94nzlkv93s

Replace the example key and secret values with values you create usint the CLI

Create the server

In our project setup, our main server is defined in src/index.ts.

/** Import our server libraries */
import koa from "koa";
import Router from "koa-router";
import logger from "koa-logger";
import json from "koa-json";
import bodyParser from "koa-bodyparser";

/** For using values in our .env */
import dotenv from "dotenv";

/** Textile libraries */
import { Client, createAPISig, PrivateKey } from "@textile/hub";

/** Read the values of .env into the environment */
dotenv.config();

/** Port our server will run */
const PORT: number = 3000;

/** Init Koa */
const app = new koa();

/** Middlewares */
app.use(json());
app.use(logger());
app.use(bodyParser());

/**
 * Start API Routes
 *
 * All prefixed with `/api/`
 */
const api = new Router({
    prefix: "/api",
});

/**
 * Basic foo-bar endpoint
 *
 * https://localhost:3000/api/foo
 */
api.get("/foo", async (ctx: koa.Context, next: () => Promise<any>) => {
    ctx.body = { foo: "bar" };
    await next();
});

/**
 * Add credentials API here
 */

/** Tell Koa to use the API routes we generate */
app.use(api.routes()).use(api.allowedMethods());

/** Start the server! */
app.listen(PORT, () => console.log("Server started."));

We now have our basic server setup, we can run it and visit http://localhost/api/foo.

ts-node src/index.ts

Info

Follow your Typescript setup guide for specific ways of launching the server.

Add the credentials endpoint

Next, we'll add an endpoint so the client can get new or refreshed credentials. Note the Add credentials API here location in the server code above.

/**
 * Add credentials API here
 */
api.get("/credentials", async (ctx: koa.Context, next: () => Promise<any>) => {
    // Custom validation could be done here...

    /** Get API authorization for the user */
    const expiration = new Date(Date.now() + 60 * seconds);
    const auth = await createAPISig(process.env.USER_API_SECRET, expiration);

    /** Include the API KEY in the auth payload */
    const credentials = {
        ...auth,
        key: process.env.USER_API_KEY,
    };

    /** Return the credentials in a JSON object */
    ctx.body = credentials;

    await next();
});

Now when you refresh your locally running server you should be able to visit the following and receive valid credentials.

http://localhost:3000/api/credentials

Response:

{
    "key": "<your user group api key>",
    "msg": "<your credentials expiration>",
    "sig": "<the api signature>"
}

Create a client

Back in the browser, you can now make requests to your credentials endpoint. From their, each user can use the Hub token endpoint directly and begin making calls to the Hub APIs.

import { Client, UserAuth } from "@textile/hub";

const createCredentials = async (): Promise<UserAuth> => {
    const response = await fetch(`/api/credentials`, {
        method: "GET",
    });
    const userAuth = await response.json();
    return userAuth;
};

/** Use the simple auth REST endpoint to get API access */

console.log("Verified on Textile API");
displayStatus();

/** The simple auth endpoint generates a user's Hub API Token */
const client = Client.withUserAuth(createCredentials);

/** See identity tutorial */
const token = await client.getToken(identity);

/** Now, full auth object includes the token */
auth = {
    ...this.auth,
    token: token,
};

GitHub Example

If you'd like to explore the examples explained above more, we've provided a fully working example on GitHub. The simple credentials endpoint is part of a more complete example, you can see it here.