-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from iProov/examples-revamp
SDK examples revamp
- Loading branch information
Showing
47 changed files
with
7,695 additions
and
476 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
.idea/ | ||
node_modules | ||
.env | ||
**/vendor/prod/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
EXAMPLE_SERVER_PORT=8080 | ||
BASE_URL=https://eu.rp.secure.iproov.me | ||
API_KEY= | ||
API_SECRET= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"bracketSpacing": true, | ||
"printWidth": 120, | ||
"quoteProps": "consistent", | ||
"semi": false, | ||
"singleQuote": false, | ||
"trailingComma": "es5", | ||
"tabWidth": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
FROM node:lts-alpine | ||
|
||
WORKDIR /app | ||
ADD src/yarn.lock . | ||
ADD src/package.json . | ||
RUN yarn | ||
ADD src/static/yarn.lock ./static/ | ||
ADD src/static/package.json ./static/ | ||
RUN cd /app/static && yarn && cd /app | ||
ADD src/ . | ||
|
||
EXPOSE 80 | ||
|
||
ENTRYPOINT ["node", "server.js"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# iProov Web SDK Example | ||
|
||
This demo is a self-contained NodeJS server and minimal frontend which covers: | ||
|
||
* Running a server with a `BASE_URL`, `API_KEY` and `API_SECRET` that you can obtain from https://portal.iproov.com; | ||
* Creating tokens for Genuine Presence and Liveness transactions; | ||
* Enrolling and verifying; | ||
* Customising iProov Web with web component slots and CustomEvents. | ||
|
||
### Running the example: | ||
|
||
For a basic example, all you need to run it is Docker and some minimal configuration: | ||
|
||
1. Obtain your environment variables and create a `.env` file - see `.env.example` for a template. | ||
2. From this `demo` directory, bring up the container with: `bash run.sh` | ||
3. Navigate to http://localhost:8080 in any desktop or mobile web browser. | ||
|
||
For a deeper dive, you can of course run the server locally using [NodeJS 14+](https://nodejs.org/en/download/): | ||
|
||
``` | ||
export $(cat .env | xargs) && node src/server.js | ||
``` | ||
|
||
### Features | ||
|
||
* **Frontend customisation**: | ||
* You can customise `createSDK` inside `static/js/vendor/iproov-integration.js` | ||
* [Available events](https://github.com/iProov/web#-events) | ||
* [Slot customisation](https://github.com/iProov/web#-slots) | ||
* [Language customisation](https://github.com/iProov/web#-localization) | ||
* **Backend customisation**: | ||
* You can customise `PlatformAPI` inside `src/platform.js` | ||
* The server side is written in JavaScript and uses Hapi.js | ||
* [iProov Platform API v2 docs](https://eu.rp.secure.iproov.me/docs.html) | ||
* **Validate endpoint**: you can extend the example to implement the validate call | ||
* Note that in production, it's important that this is implemented on the server side otherwise your API credentials will be exposed! | ||
|
||
### Support and SSL Certificates | ||
To access the device camera and other browser APIs, a "secure context" is required. | ||
|
||
In practice this means running the server under TLS, or simply using localhost. | ||
|
||
For this demo, we keep things simple with localhost. But to test on another device on your network like a mobile, TLS is required. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#!/bin/bash | ||
|
||
ENV_FILE=$(pwd)/.env | ||
|
||
source "$ENV_FILE" | ||
|
||
EXAMPLE_SERVER_PORT=${EXAMPLE_SERVER_PORT:=8080} | ||
|
||
if [ ! -r "$ENV_FILE" ] | ||
then | ||
echo "Missing environment file: $ENV_FILE" | ||
echo "Use the template in .env.example and populate with keys from https://portal.iproov.com." | ||
exit 1 | ||
fi | ||
|
||
docker build . -t iproov-web-example | ||
docker run --env-file "$ENV_FILE" -e EXAMPLE_SERVER_PORT="$EXAMPLE_SERVER_PORT" -e IS_DOCKER=1 -p "0.0.0.0:$EXAMPLE_SERVER_PORT":80 --rm iproov-web-example |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* Load and validate configuration | ||
* @todo Use Joi or some better configuration checker | ||
* @param env an object that contains the configuration, like process.env | ||
* @return {{API_KEY: *, API_SECRET: *, BASE_URL: *, EXAMPLE_SERVER_PORT: *}} | ||
*/ | ||
export function configure(env) { | ||
const { BASE_URL, API_KEY, API_SECRET } = env | ||
let { EXAMPLE_SERVER_PORT } = env | ||
const errors = [] | ||
if (!BASE_URL) { | ||
errors.push("BASE_URL is undefined. Example: https://eu.rp.secure.iproov.me.") | ||
} | ||
if (!API_KEY) { | ||
errors.push("API_KEY is undefined. You can obtain one from https://portal.iproov.com.") | ||
} else if (API_KEY.length < 40) { | ||
errors.push("API_KEY seems incorrect, it should be a 40 character alphanumeric string.") | ||
} | ||
if (!API_SECRET) { | ||
errors.push( | ||
"API_SECRET is undefined. It must correspond to your API_KEY. If lost, reset it at https://portal.iproov.com." | ||
) | ||
} else if (API_SECRET.length < 40) { | ||
errors.push("API_SECRET seems incorrect, it should be a 40 character alphanumeric string.") | ||
} | ||
if (!EXAMPLE_SERVER_PORT) { | ||
console.warn("EXAMPLE_SERVER_PORT not specified, using port 80.") | ||
EXAMPLE_SERVER_PORT = 80 | ||
} | ||
if (errors.length) { | ||
console.error("Configuration problems detected:") | ||
errors.forEach((e) => console.error(e)) | ||
console.error("Contact [email protected] for assistance.") | ||
process.exit(1) | ||
return | ||
} | ||
const config = { | ||
BASE_URL, | ||
API_KEY, | ||
API_SECRET, | ||
EXAMPLE_SERVER_PORT, | ||
} | ||
return config | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "@iproov/web-example", | ||
"version": "1.0.0", | ||
"description": "An example of iProov's Web SDK integration", | ||
"main": "server.js", | ||
"author": "iProov Team", | ||
"license": "GPL", | ||
"private": true, | ||
"type": "module", | ||
"dependencies": { | ||
"@hapi/hapi": "^20.0.3", | ||
"@hapi/inert": "^6.0.3", | ||
"prettier": "^2.2.1", | ||
"superagent": "^6.1.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import superagent from "superagent" | ||
|
||
/** | ||
* Lightweight Platform v2 wrapper | ||
* @see https://eu.rp.secure.iproov.me/docs.html | ||
*/ | ||
export class PlatformAPI { | ||
constructor(logger, baseUrl, apiKey, apiSecret) { | ||
this.logger = logger | ||
this.baseUrl = baseUrl | ||
this.apiKey = apiKey | ||
this.apiSecret = apiSecret | ||
} | ||
|
||
apiUrl(endpoint) { | ||
return `${this.baseUrl}/api/v2/${endpoint}` | ||
} | ||
|
||
withJsonAuth(payload) { | ||
return { | ||
api_key: this.apiKey, | ||
secret: this.apiSecret, | ||
...payload, | ||
} | ||
} | ||
|
||
withHeaders() { | ||
return { | ||
"accept": "json", | ||
"user-agent": "superagent", | ||
} | ||
} | ||
|
||
/** | ||
* @todo Add response envelope for consumption by Hapi | ||
* @param request | ||
* @return {Promise<*>} | ||
*/ | ||
async unpack(request) { | ||
try { | ||
const response = await request | ||
return { ...response.body, base_url: this.baseUrl } | ||
} catch (e) { | ||
// @todo: indicate this is an error - currently we just pass through | ||
if (e.status === 400) { | ||
const { error, error_description } = e.response.body | ||
this.logger.error("Error %s: %s", error, error_description) | ||
} | ||
return e.response.body | ||
} | ||
} | ||
|
||
async token(mode, options = {}) { | ||
const { userId, assuranceType } = options | ||
if (!userId) { | ||
this.logger.warn(`Couldn't create a token because user_id is empty`) | ||
return { | ||
error: "Missing User ID", | ||
error_description: "You must provide a user_id to create a token.", | ||
} | ||
} | ||
this.logger.info(`Creating ${assuranceType} ${mode} token for ${userId}`) | ||
return this.unpack( | ||
superagent | ||
.post(this.apiUrl(`claim/${mode}/token`)) | ||
.set(this.withHeaders()) | ||
.send( | ||
this.withJsonAuth({ | ||
user_id: userId, | ||
assurance_type: assuranceType, | ||
resource: "Web SDK Example", | ||
}) | ||
) | ||
) | ||
} | ||
|
||
async validate(mode, options = { userId, token }) { | ||
const { userId, token } = options | ||
this.logger.info(`Validating ${mode} for ${userId} - token: ${token}`) | ||
return this.unpack( | ||
superagent | ||
.post(this.apiUrl(`claim/${mode}/validate`)) | ||
.set(this.withHeaders()) | ||
.send( | ||
this.withJsonAuth({ | ||
token, | ||
ip: "127.0.0.1", // @todo: change when IPv6 is fully supported | ||
client: "superagent", | ||
}) | ||
) | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Map Hapi request payloads to PlatformAPI method arguments | ||
*/ | ||
export const requestToAPIMapper = Object.freeze({ | ||
token(request) { | ||
return { | ||
userId: request.payload.user_id, | ||
assuranceType: request.payload.assurance_type || "genuine_presence", | ||
} | ||
}, | ||
validate(request) { | ||
return { | ||
token: request.payload.token, | ||
userId: request.payload.user_id, | ||
} | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import Hapi from "@hapi/hapi" | ||
import Inert from "@hapi/inert" | ||
import { fileURLToPath } from "url" | ||
import { dirname, resolve } from "path" | ||
import { PlatformAPI, requestToAPIMapper } from "./platform.js" | ||
|
||
import { configure } from "./config.js" | ||
|
||
const __dirname = fileURLToPath(dirname(import.meta.url)) | ||
|
||
async function init() { | ||
const { BASE_URL, API_KEY, API_SECRET, EXAMPLE_SERVER_PORT } = configure(process.env) | ||
|
||
const ALL_INTERFACES = "0.0.0.0" // listen on all interfaces so Docker can bind | ||
const server = Hapi.server({ | ||
port: 80, | ||
host: ALL_INTERFACES, | ||
}) | ||
|
||
await server.register(Inert) | ||
|
||
let platform | ||
|
||
server.route({ | ||
method: "GET", | ||
path: "/{param*}", | ||
handler: { | ||
directory: { | ||
path: resolve(__dirname, "static"), | ||
index: "index.html", | ||
} | ||
} | ||
}) | ||
|
||
server.route({ | ||
method: "POST", | ||
path: "/api/claim/{claimMode}/{claimAction}", | ||
options: { cors: { origin: ["*"] } }, | ||
handler: async (request, h) => { | ||
const { claimMode, claimAction } = request.params | ||
try { | ||
return await platform[claimAction](claimMode, requestToAPIMapper[claimAction](request)) | ||
} catch (e) { | ||
console.error("Unhandled: %s", e.message) | ||
throw e | ||
} | ||
}, | ||
}) | ||
|
||
platform = new PlatformAPI(console, BASE_URL, API_KEY, API_SECRET) | ||
|
||
console.debug("Starting internal server: %s", server.info.uri) | ||
|
||
await server.start() | ||
|
||
console.log("iProov tokens will be created on %s with API_KEY %s", BASE_URL, API_KEY) | ||
console.log("Web SDK example available at %s", "http://localhost:" + EXAMPLE_SERVER_PORT) | ||
|
||
} | ||
|
||
process.on("unhandledRejection", (err) => { | ||
console.log(err) | ||
process.exit(1) | ||
}) | ||
|
||
process.on("SIGINT", () => { | ||
console.log("Caught SIGINT - shutting down.") | ||
process.exit(0) | ||
}) | ||
|
||
init() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# editorconfig.org | ||
|
||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
indent_size = 2 | ||
indent_style = space | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true |
Oops, something went wrong.