Identity-TBD
Documentation Page
Identity-TBD is an API service that provides Identity-as-a-service (IDAAS) features for your app development.
Save yourself the hassle and security worries of a old-fashioned name/password login scheme and give your application a modern, professional sign-in experience that leverages the Single-Sign-In services of many favorite providers, such as Google, Facebook, Apple, and more.
Getting Started
Identity-TBD is available from the RapidAPI marketplace.
Pick your plan and make requests as shown on the RapidAPI site. Remember to use your rapidApi api key in the headers of the request as shown.
BYOB (Bring your own browser)
If your app is a web page (SPA or otherwise), you are already in a browser context. If your app is a mobile app, you may first need to create a webview control to host the login experience, and then follow the steps shown here within that context. Once you have your identifier, you no longer need to remain in the webview.
The OAuth2 login process used for each of the providers differs slightly per provider, but all will employ a combination of service requests and browser redirects to conduct the secure login using their infrastructure and user information. This is why a browser context is necessary to conduct the sign-in process.
Identity-TBD normalizes all of the variations for you, so the process is the same regardless which provider your user selects.
The overall flow
In this diagram, the calls to the rest-api for /login and /identity are controlled as they are in the
helper library, identity-tbd-client.js
which will be explored in more detail shortly.
On page load
The login process is driven on entry by the presence or absence of a token, named idtbd
that
determines the next steps. If this code is available, it is used to call the /identity
endpoint with
to retrieve the associated IdentityObject
.
If it is not available, the next step is to call the /login
endpoint which will return HTML that should be
put into the browser page to allow the user to select their login provider and continue the sign-in process.
The Login Process
The result from the login request will be HTML content. This content should be set to your browser (use document.write()
).
This Page will direct the user to select from a list of possible providers and then proceed to execute the sign-in process via that provider.
When the process completes, it will redirect to the page url where the login request was made, and this redirect request
will include a query parameter named idtbd
(e.g. http://localhost:8081/index.html?idtbd=xxxxxxxx
) The value of the idtbd
parameter can be used as a token to retrieve the Identity data from the service, with the /identity
api.
The /login
endpoint accepts a single path parameter, appId
Picking an appId
An appId is an arbitrary string, but it should be unique to avoid possible duplication of identifiers with another app.
The recommendation is to use reverse domain notation - such as com.example.your-app-name
where
the reverse-domain portion represents a domain identifying your organization, if possible.
The Identity Process
After the login process delivers an idtbd
token to the page, this token may be used to retrieve the actual
IdentityObject
and its associated identifying information. The /identity
endpoint is called by passing
this idtbd
value as a path parameter (e.g.) /identity/28ca232d-d09f-461e-9a04-3e5217f92c10
.
This call does not return HTML, but a JSON response (Content-Type 'application/json') that contains the so-called IdentityObject
At this point you can pull the information needed from this object (most notably the userIdentity
value) and use as
appropriate in your own app code.
Using the identity-tbd-client.js library
You could choose to implement Identity-TBD
for your application at the REST-API level,
but you may find it much easier to use the helper script identity-tbd-client.js
, or the minified
version (identity-tbd-client-min-js
), or if
you are creating a React app and need an ES6 module for this, the @tremho/idtbd
module available from NPM.
The following sections walk through the flow explained above, and in particular references the flow chart diagram, but in this description, we look through the lens of using the client library. Afterward, some sample app implementations are presented to help you get started.
1. OnLoad
On page load, the application checks for an idtbd
token value passed into it by
either a query parameter on the URL or as a cookie.
If this value exists, the login selection itself may be skipped and the identity
for the token is retrieved.
2. Login
if no identity token is available, the login selection may begin. This can be designed
to occur directly at this point, or upon a button click from the user.
This login
operation produces html that is delivered to the brower and conducts
the remaining steps of the provider-specific sign-in flow, after which the
page from the caller is refreshed, this time with an idtbd
value made available.
3. Identity
With an idtbd
token in hand, a call to the /identity
operation is made and
a complete IdentityObject
is returned. This object contains information from the
provider about the signed-in user, but more importantly a unique yet consistent userIdentity
value that identifies this user to your application.
At this point, your app can use this identifier to establish a user presence within your application,
establish a session, access your database, etc. as the needs of your app define.
Implementing the javascript identity-tbd-client library
Below is some sample code for a simple HTML page that implements the identity-tbd-client.js library.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Example</title>
<script src="https://www.tremho.com/identity-tbd/script/identity-tbd-client-min.js" type="application/javascript"></script>
<script>
const rapidapikey = '---your-rapid-api-key-here---'
const appId = 'simpleTest'
function start(withLogin) {
window.IDTBD.allowCookie = true
window.IDTBD.onLoad(rapidapikey,appId,onIdentity,onStatus).then(() => {
console.log("return from onLoad", window.IDTBD)
if(withLogin) {
window.IDTBD.login()
}
})
}
function onIdentity(identityObject) {
console.warn('called with ', identityObject)
document.getElementById('identity').innerText=`User Identity returned as ${identityObject.userIdentity}`
}
function onStatus(status) {
console.log(status)
let vis = status ? 'hidden' : 'visible'
if(status === 'Logout') vis = 'visible'
document.getElementById('login').style.visibility = vis
if(status === 'Identified') vis = 'visible'
document.getElementById('logout').style.visibility = vis
}
</script>
</head>
<body onload="start(false)">
<h1>Simple example</h1>
<button id='login' onClick="window.IDTBD.login()">Log in</button>
<button id='logout' onClick="window.IDTBD.logout()">Log Out</button>
<p id='identity'/>
</body>
</html>
Before running the above code, replace the '---your-rapid-api-key-here---' with your actual rapidAPI api key. Otherwise, you will get an error in the javascript console and the page will not execute.
When run, this page will present a "Log in" and a "Log Out" button. Logging in will begin the sign-in process and once complete, the user identifier will be displayed.
Understanding the code
The implementation begins by loading the identity-tbd-client-min.js script, which we
can see with this line within the <head>
section of the html.
there are minimized and non-minimized versions of this script available, each identical in operation
<script src="https://www.tremho.com/identity-tbd/script/identity-tbd-client-min.js" type="application/javascript"></script>
- identity-tbd-client.js
- identity-tbd-client-min.js
IDTBD
.
It will be referred to subsequently via window.IDTBD
in the page script.
Creating the execution script section
Immediately following the script load, there is a <script> section defined.
This is where the page interacts with the library and its layout elements.
In this example, it begins with a start
function. We can see further down that
the <body>
tag invokes this function through its `onload` handler, so that the
execution occurs when the page is ready.
We see the `start` function immediately calling window.IDTBD.onLoad
and passing
the following parameters
- rapidapikey - This is your RapidAPI key that you can find at the RapidAPI site for your subscription.
- appId - This is the identifier for your application. It can be arbitrary, but it should be unique. The recommendation here is to use "reverse-domain" syntax - so that a unique domain identifier identifies your organization. For example com.example.yourApp, or org.johndoe.myApp
-
identityCallback - This is a function you define in your script that will be called from the library when there is an
identity is available. You can see in the example, the function
onIdentity
is created and used here. -
statusCallback - (optional) This is a function you define in your script that will be called with
the names of the processing status as the library steps through its functions.
The status will be an empty string ('') when no processing is in effect.
In this example, this status callback is pointed at the function
onStatus
which is used to adjust the visibility of the login display elements accordingly.
Optional components to the start function
You've no doubt notices that the example code start
function accepts a parameter named withLogin
that is called as 'false' when invoked from the "<body onload=
" trigger.
If this were called as 'true', then login
would be called when the onLoad
promise
returns, eliminating the need for a Log In button. The user would automatically be prompted to select their provider
on page load, unless there was a cookie stored, in which case the identity callback would announce the returning user with no futher interaction.
Also, you will note the line window.IDTBD.allowCookie=true
. This is optional since
the default for this value is 'true', but were it to be set to false, then
the standard behavior of using a cookie to capture the last idtbd
would be skipped, and
the user will need to log in each time. The need to Log Out would also be eliminated.
Implement according to the needs of your app and any user preferences for cookie usage.
Implementing for React
If you are working in React, please look at the following example, written in Typescript and using NPM modules, while keeping in mind what we learned from the simple HTML example above.
MainPage.tsx
import React from 'react'
import { Button } from "@mui/material"
import IDTBD from '@tremho/idtbd'
export default function MainPage() {
const [identity, setIdentity] = React.useState(null)
const [status, setStatus] = React.useState('')
const rapidapikey = '---your-rapid-api-key-here---'
const appId = 'com.example.yourApp'
const withLogin = false
function callback(identity) {
console.warn('callback called with', identity)
setLoggedInUser(identity)
}
function statusCallback(status) {
console.log("status", status)
setStatus(status)
}
React.useEffect( () => {
if(!identity) {
IDTBD.allowCookie = true
IDTBD.onLoad(rapidapikey, appId, callback, statusCallback).then(() => {
console.log("return from onLoad", IDTBD)
if (withLogin) {
IDTBD.login()
}
})
}
})
async function setLoggedInUser(identity:any) {
console.warn("SetLoggedInUser", identity)
setIdentity(identity)
// you can now do what you may need to do for your own app with this identity
}
function UserIdentity() {
if(identity?.userIdentity) {
return (
<>
<p>user identity = {identity?.userIdentity}</p>
</>
)
}
}
// supress page output if status callback informed us we are in process, or we have no identity
if(!status || identity)
return (
<>
<h3>Identity-TBD React sample</h3>
<div>
<Button onClick={IDTBD.login} className="btn btn-primary">Log In</Button>
<Button onClick={IDTBD.logout} className="btn btn-primary">Log Out</Button>
</div>
<UserIdentity />
</>
)
}
Here, we can see features introduced in the previous example, but couched within React-type contexts.
First, we see that the IDTBD
object has been imported as an ES6 module, so we
refer to it by this name alone, rather than window.IDTBD
The module can be found on NPM and is installed with npm install @tremho/idtbd
We see our identityCallback
and statusCallback
functions defined,
and following through we see that these echo these status changes via useState
so that React state management
is properly executed.
We see the "start" function from the html example is effectively reproduced here
within the useEffect
handler that React will update with each state change.
As in the previous example, we pass our rapidapikey, appId, and callbacks to the onLoad function to
set things up.
What to do when you get an identifier
In these examples, we are simply displaying the value of the identifier to the web page, but in an actual app, you will want to initiate some mechanism (perhaps via your backend services) to establish a session or other context that will use this user identifier within your app. The actual use of this will depend upon your application architecture and your database and service implementation.
Provider Data
The IdentityObject
contains a property named providerData
. Within this will be one
or more object properties that have the names of the provider that supplied this information via
their sign-in process. These property names will be 'apple', 'google', 'facebook' (and others as
new providers are added). Each will contain an object that at a minimum will
contain a providerToken
identifier, but may also contain properties that contain some
direct personal information about the user (depending upon the provider and the options the user has set
with that provider). These may include email, name, and/or picture information. The structure of this information
varies by provider and not all fields may exist.
For most of the providers, the providerToken
value may be used to access the provider-specific
apis of that provider to obtain a potentially wider degree of information to discover about the user.
Visit the developer documentation sites for each of the providers to learn more about using their apis.
It is recommended that information you may need to collect for the user be done within your
application, although the provider info may be used to pre-populate the fields of such
an on-boarding form.
Log Out
The "log out" operation merely removes the value of the cookie that is saved (if cookies are enabled).
You can do this by calling IDTBD.logout
, as shown here, or simply with document.cookie='idtbd='
Provider Linking
Not shown in either of these examples is handling the IDTBD.link
operation.
This is used to associate the currently logged in identity with the sign-in result of using
a different provider.
To use link
, you must first have performed the onLoad
operation and established an IdentityObject
from a login
Call link
in the way that you would call login
, except you must pass the sid
property found
in the IdentityObject
as the idtbd
parameter to link
.
This will proceed through a flow very similar to that of login
, but upon the successful conclusion,
the browser window will contain the words 'Identities Linked'
and subsequent logins via either the original provider or through the new linked provider
will result in the same userIdentity
value.
The providerData
information will contain entries for all the linked providers, by name.