UNPKG

whodis-sdk

Version:

A simple sdk for easy, secure authentication with the whodis platform. Setup secure authentication for your app in seconds.

168 lines (126 loc) 5.75 kB
# whodis-sdk A simple sdk for easy, secure, best practices authentication with the whodis platform. Setup and manage secure authentication for your app in seconds. # install ```sh npm install --save whodis-sdk ``` # examples ### getAuthedClaimsFromHeaders to securely get authenticated claims from headers containing a whodis auth token ```ts import { getAuthedClaimsFromHeaders } from 'whodis-sdk'; const claims = await getAuthedClaimsFromHeaders({ headers: event.headers, config: { issuer: config.whodis.directory.issuer, audience: config.whodis.directory.audience, }, log }); const userUuid = claims?.sub ?? null; // this is the userUuid that you can use to uniquely identify your users ``` _note: assumes that the token was issued by [`whodis`](https://github.com/whodisio/whodis-cli) and managed on the client by either [`whodis-client`](https://github.com/whodisio/whodis-client) or [`whodis-react`](https://github.com/whodisio/whodis-react)._ ### getUser to lookup a user's data by uuid ```ts import { getUser } from 'whodis-sdk'; const user = await getUser( { userUuid: string, }, { credentials: { publicKey: config.whodis.api.publicKey, privateKey: config.whodis.api.privateKey, }, }, ); ``` ### addUserContactMethod to lookup a user's data by uuid ```ts import { addUserContactMethod } from 'whodis-sdk'; const user = await addUserContactMethod( { userUuid: string, contactMethod: { type: 'EMAIL' | 'PHONE', address: string, } }, { credentials: { publicKey: config.whodis.api.publicKey, privateKey: config.whodis.api.privateKey, }, }, ); ``` # docs ### `getAuthedClaimsFromHeaders({ headers, config, log })` `getAuthedClaimsFromHeaders` extracts authenticated claims from the auth token found in the headers, if any exist. Additionally, it monitors authentication errors to proactively help with debugging and detect potential security attacks. Operation: - if there is no auth token in the headers, the function returns `null` - if there is an auth token and it can not be authenticated, the error will be logged, reported, and the function returns `null` - if there is an auth token and it is successfully authenticated, the function will return the token claims ```ts const claims = await getAuthedClaimsFromHeaders({ // the headers hold the auth token well be authing headers, // the config provides the keys required to complete a secure authentication of a JWT config: { issuer: 'https://auth.whodis.io/__yourdirectoryuuid__', // must match up exactly with what is present on the token, to verify that the token was from the intended authority audience: 'https://api.__yourwebsite__.com', // must match up exactly with what is present on the token, to verify the token was intended for you }, // the log methods allow you to monitor authentication errors log: { warn: (message: string, metadata: Record<string, string>) => console.log(message, metadata), // replace this with your favorite log method }, }); ``` # nuances ### cookie based authentication If your users are interacting with your app through the browser, there is no choice but to use cookie based token storage for security (due to all data accessible by JS being vulnerable to XSS). Fortunately for us, browsers make it really challenging to work with cookies. A combination of CORS and Cookie security standards results in a very fine line of how your preflight-request responses have to look like in order for the cookie to be sent and the browser not to throw an error at the request. Specifically: 1. your client has to make the request with the flag `{ credentials: 'include' }` 2. your server's preflight response has to include the header `access-control-allow-credentials: true` 3. your server's preflight response has to include the header `access-control-allow-headers: content-type,authorization` 4. your server's preflight response has to include the header `access-control-allow-origin: __YOUR_WEBSITES_ORIGIN__` 1. where `__YOUR_WEBSITES_ORIGIN__` is the full origin uri listed in the request header by the browser (e.g., `https://www.yourdomain.com`) Typically, this is done by setting up a custom route that responds specifically to the `OPTIONS` method on all paths of the api. (The `OPTIONS` method is called by browsers in the preflight requests that browsers check the above settings with). For example, if you are working with the `serverless` framework you can setup an HTTP api gateway that handles all options requests with the following: ```yml corsPreflightResponse: handler: dist/contract/handlers/corsPreflightResponse.handler events: - httpApi: method: OPTIONS path: /user/{proxy+} ``` with the code of the handler as follows: ```ts import Joi from 'joi'; import { createApiGatewayHandler } from 'simple-lambda-handler'; export const CORS_SETTINGS = { // define each origin website that you want to support here (or set `origins: '*'` if you want to support all origins) origins: ['https://www.yourwebsite.com', 'https://localhost.yourwebsite.com:3443'], // for example, support the main website and a localhost variant // define that this server supports credentials withCredentials: true, // with credentials, since tokens come in cookies from browser }; // return a successful response each time const handle = async (): Promise<{ statusCode: 200; headers?: any; body: undefined }> => { return { statusCode: 200, body: undefined, }; }; // export the handler export const handler = createApiGatewayHandler({ log, schema: Joi.object().unknown(true), // allow any input shape logic: handle, cors: CORS_SETTINGS, }); ```