Skip to content

Commit

Permalink
Merge pull request #1 from authsignal/rollup-tweaks
Browse files Browse the repository at this point in the history
Rollup tweaks
  • Loading branch information
hwhmeikle committed May 25, 2022
2 parents 305eee0 + 66239bf commit 350b16f
Show file tree
Hide file tree
Showing 14 changed files with 308 additions and 35 deletions.
7 changes: 7 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2021
},
"extends": ["plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"]
}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ dist
package-lock.json
.nyc_output
coverage/
*.tsbuildinfo
*.tsbuildinfo
.vscode
3 changes: 0 additions & 3 deletions .vscode/settings.json

This file was deleted.

1 change: 0 additions & 1 deletion .vscode/spellright.dict

This file was deleted.

37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,38 @@
# authsignal-browser

## API

### challengeWithPopup

You will need to add the following CSS to your application if using this method:

```css
.dialog-container,
.dialog-overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
}

.dialog-container {
z-index: 2;
display: flex;
}

.dialog-container[aria-hidden="true"] {
display: none;
}

.dialog-overlay {
background-color: rgba(43, 46, 56, 0.9);
}

.dialog-content {
margin: auto;
z-index: 2;
position: relative;
background-color: white;
}
```
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"scripts": {
"typecheck": "tsc",
"clean": "rm -rf ./dist",
"lint": "eslint \"{cli,config,src,test}/**/*.ts\"",
"build": "rollup --configPlugin rollup-plugin-ts --config rollup.config.ts"
},
"files": [
Expand All @@ -27,10 +28,13 @@
},
"dependencies": {
"@fingerprintjs/fingerprintjs": "^3.3.3",
"basiclightbox": "^5.0.4",
"a11y-dialog": "^7.4.0",
"uuid": "^8.3.2"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"@types/basiclightbox": "^5.0.1",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.25.0",
"@typescript-eslint/parser": "^5.25.0",
Expand Down
9 changes: 5 additions & 4 deletions rollup.config.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import type {RollupOptions} from "rollup";
import ts from "rollup-plugin-ts";
import {nodeResolve} from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import pkg from "./package.json";

const isWatchMode = process.env.ROLLUP_WATCH === "true";

const input = "src/index.ts";
const plugins = [ts({browserslist: false})];
const external = ["@fingerprintjs/fingerprintjs", "uuid", "basiclightbox"];
const plugins = [nodeResolve(), commonjs(), ts({browserslist: false})];
const watch: RollupOptions["watch"] = {include: ["src/**"], clearScreen: false};
const sourcemap = isWatchMode ? false : true;
const onwarn: RollupOptions["onwarn"] = (warning) => {
throw new Error(warning.message);
};

const cjs: RollupOptions = {
...{input, watch, plugins, external, onwarn},
...{input, watch, plugins, onwarn},
output: {file: pkg.main, format: "cjs", sourcemap},
};

const esm: RollupOptions = {
...{input, watch, plugins, external, onwarn},
...{input, watch, plugins, onwarn},
output: {file: pkg.module, format: "esm", sourcemap},
};

Expand Down
26 changes: 12 additions & 14 deletions src/Authsignal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {default as basicLightbox} from "basiclightbox";
import FingerprintJS, {Agent} from "@fingerprintjs/fingerprintjs";
import * as FingerprintJS from "@fingerprintjs/fingerprintjs";

import {setCookie, generateId, getCookieDomain, getCookie, getHostWithProtocol, reformatDate} from "./helpers";
import {
Expand All @@ -9,14 +8,14 @@ import {
RegisterAnonymousIdRequest,
RegisterIdentityRequest,
UserProps,
} from "./interfaces";
} from "./types";
import {PopupHandler} from "./PopupHandler";

export function authsignalClient(publishableKey: string, options?: AuthsignalOptions): AuthsignalClient {
const client = new AuthsignalClient();
client.init(publishableKey, options);
return client;
}

export class AuthsignalClient {
private anonymousId = "";
private initialized = false;
Expand All @@ -25,7 +24,7 @@ export class AuthsignalClient {
private idCookieName = "";
private trackingHost = "";
// Could do with a fingerprintClient interface
private fingerprintClient?: Agent;
private fingerprintClient?: FingerprintJS.Agent;
private deviceFingerprint?: string;

async init(publishableKey: string, options?: AuthsignalOptions): Promise<void> {
Expand Down Expand Up @@ -78,19 +77,18 @@ export class AuthsignalClient {
return {idCookie: newId, generated: true};
}

handleChallenge(challenge: AuthsignalChallenge): Promise<boolean> {
const lightbox = basicLightbox.create(
`<iframe name="authsignal" src="${challenge.challengeUrl}" width="600" height="100%" frameborder="0"></iframe>`
);
challengeWithPopup({challengeUrl}: AuthsignalChallenge): Promise<boolean> {
const Popup = new PopupHandler();

Popup.show({challengeUrl});

lightbox.show();
return new Promise<boolean>((resolve, reject) => {
const handleChallenge = (event: MessageEvent) => {
if (event.data === "authsignal-challenge-success") {
lightbox.close();
Popup.close();
resolve(true);
} else if (event.data === "authsignal-challenge-failure") {
lightbox.close();
Popup.close();
reject(false);
}
};
Expand Down Expand Up @@ -135,7 +133,7 @@ export class AuthsignalClient {
};
}

private sendJson(path: string, payload: any) {
private sendJson(path: string, payload: unknown) {
const jsonString = JSON.stringify(payload);
const url = `${this.trackingHost}/api/v1/client/${path}?publishableKey=${this.publishableKey}`;

Expand All @@ -147,7 +145,7 @@ export class AuthsignalClient {
private xmlHttpReqTransport(url: string, json: string): Promise<void> {
const req = new XMLHttpRequest();
return new Promise((resolve, reject) => {
req.onerror = (e) => {
req.onerror = () => {
reject(new Error(`Failed to send JSON. See console logs`));
};
req.onload = () => {
Expand Down
80 changes: 80 additions & 0 deletions src/PopupHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import A11yDialog from "a11y-dialog";
import {AuthsignalChallenge} from "./types";

const DIALOG_CONTAINER_ID = "authsignal-popup";
const DIALOG_CONTENT_ID = "authsignal-popup-content";

class PopupHandler {
private popup: A11yDialog | null = null;

constructor() {
if (document.querySelector(`#${DIALOG_CONTAINER_ID}`)) {
throw new Error("Multiple instances of Authsignal popup is not supported.");
}

this.create();
}

create() {
// Dialog container
const container = document.createElement("div");
container.setAttribute("id", DIALOG_CONTAINER_ID);
container.setAttribute("aria-hidden", "true");
container.setAttribute("class", "dialog-container");

// Dialog overlay
const overlay = document.createElement("div");
overlay.setAttribute("class", "dialog-overlay");
overlay.setAttribute("data-a11y-dialog-hide", "true");
container.appendChild(overlay);

// Dialog content
const content = document.createElement("div");
content.setAttribute("class", "dialog-content");
content.setAttribute("id", DIALOG_CONTENT_ID);
container.appendChild(content);

document.body.appendChild(container);

this.popup = new A11yDialog(container);
this.popup.on("hide", this.destroy);
}

destroy() {
const dialogEl = document.querySelector(`#${DIALOG_CONTAINER_ID}`);
if (dialogEl) {
document.body.removeChild(dialogEl);
}
}

show({challengeUrl}: {challengeUrl: AuthsignalChallenge["challengeUrl"]}) {
if (!this.popup) {
throw new Error("Popup is not initialized");
}

const iframe = document.createElement("iframe");
iframe.setAttribute("name", "authsignal");
iframe.setAttribute("title", "Authsignal multi-factor authentication challenge");
iframe.setAttribute("src", challengeUrl);
iframe.setAttribute("width", "600");
iframe.setAttribute("height", "600");
iframe.setAttribute("frameborder", "0");

const dialogContent = document.querySelector(`#${DIALOG_CONTENT_ID}`);
if (dialogContent) {
dialogContent.appendChild(iframe);
}

this.popup.show();
}

close() {
if (!this.popup) {
throw new Error("Popup is not initialized");
}

this.popup.hide();
}
}

export {PopupHandler};
5 changes: 2 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
import { AuthsignalClient, authsignalClient } from "./Authsignal";

export { AuthsignalClient, authsignalClient };
export {AuthsignalClient, authsignalClient} from "./Authsignal";
export * from "./types";
1 change: 0 additions & 1 deletion src/types.d.ts

This file was deleted.

File renamed without changes.
1 change: 0 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"strict": true,
"noEmit": true,
"moduleResolution": "node",
"jsx": "react-jsx",
"esModuleInterop": true,
"resolveJsonModule": true,
"preserveWatchOutput": true
Expand Down
Loading

0 comments on commit 350b16f

Please sign in to comment.