@atproto/oauth-provider 0.1.0 → 0.1.2-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/account/account-manager.d.ts +2 -2
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +19 -6
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js +16 -1
- package/dist/account/account-store.js.map +1 -1
- package/dist/assets/app/bundle-manifest.json +3 -3
- package/dist/assets/app/main.css +1 -1
- package/dist/assets/app/main.js +3 -3
- package/dist/assets/app/main.js.map +1 -1
- package/dist/client/client-auth.d.ts.map +1 -1
- package/dist/client/client-auth.js +2 -2
- package/dist/client/client-auth.js.map +1 -1
- package/dist/client/client-manager.d.ts.map +1 -1
- package/dist/client/client-manager.js +3 -1
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +3 -3
- package/dist/client/client.js.map +1 -1
- package/dist/dpop/dpop-manager.d.ts.map +1 -1
- package/dist/dpop/dpop-manager.js +3 -3
- package/dist/dpop/dpop-manager.js.map +1 -1
- package/dist/errors/invalid-token-error.d.ts.map +1 -1
- package/dist/errors/invalid-token-error.js +3 -2
- package/dist/errors/invalid-token-error.js.map +1 -1
- package/dist/errors/second-authentication-factor-required-error.d.ts +13 -0
- package/dist/errors/second-authentication-factor-required-error.d.ts.map +1 -0
- package/dist/errors/second-authentication-factor-required-error.js +23 -0
- package/dist/errors/second-authentication-factor-required-error.js.map +1 -0
- package/dist/lib/util/authorization-header.js +1 -1
- package/dist/lib/util/authorization-header.js.map +1 -1
- package/dist/metadata/build-metadata.d.ts.map +1 -1
- package/dist/metadata/build-metadata.js +2 -0
- package/dist/metadata/build-metadata.js.map +1 -1
- package/dist/oauth-errors.d.ts +1 -0
- package/dist/oauth-errors.d.ts.map +1 -1
- package/dist/oauth-errors.js +3 -1
- package/dist/oauth-errors.js.map +1 -1
- package/dist/oauth-provider.d.ts +101 -4
- package/dist/oauth-provider.d.ts.map +1 -1
- package/dist/oauth-provider.js +98 -110
- package/dist/oauth-provider.js.map +1 -1
- package/dist/output/build-authorize-data.d.ts +40 -0
- package/dist/output/build-authorize-data.d.ts.map +1 -0
- package/dist/output/build-authorize-data.js +22 -0
- package/dist/output/build-authorize-data.js.map +1 -0
- package/dist/output/build-error-payload.d.ts.map +1 -1
- package/dist/output/build-error-payload.js +4 -3
- package/dist/output/build-error-payload.js.map +1 -1
- package/dist/output/customization.d.ts +2 -12
- package/dist/output/customization.d.ts.map +1 -1
- package/dist/output/customization.js +59 -32
- package/dist/output/customization.js.map +1 -1
- package/dist/output/output-manager.d.ts +16 -0
- package/dist/output/output-manager.d.ts.map +1 -0
- package/dist/output/output-manager.js +69 -0
- package/dist/output/output-manager.js.map +1 -0
- package/dist/output/send-web-page.d.ts +1 -1
- package/dist/output/send-web-page.d.ts.map +1 -1
- package/dist/output/send-web-page.js +3 -2
- package/dist/output/send-web-page.js.map +1 -1
- package/package.json +7 -7
- package/src/account/account-manager.ts +2 -2
- package/src/account/account-store.ts +12 -6
- package/src/assets/app/components/accept-form.tsx +86 -83
- package/src/assets/app/components/account-picker.tsx +98 -79
- package/src/assets/app/components/button.tsx +34 -0
- package/src/assets/app/components/client-identifier.tsx +12 -13
- package/src/assets/app/components/fieldset.tsx +26 -0
- package/src/assets/app/components/form-card.tsx +47 -0
- package/src/assets/app/components/help-card.tsx +1 -1
- package/src/assets/app/components/icons/alert-icon.tsx +5 -0
- package/src/assets/app/components/icons/at-symbol-icon.tsx +5 -0
- package/src/assets/app/components/icons/caret-right-icon.tsx +5 -0
- package/src/assets/app/components/icons/lock-icon.tsx +5 -0
- package/src/assets/app/components/icons/token-icon.tsx +5 -0
- package/src/assets/app/components/icons/util.tsx +17 -0
- package/src/assets/app/components/info-card.tsx +45 -0
- package/src/assets/app/components/input-checkbox.tsx +47 -0
- package/src/assets/app/components/input-container.tsx +37 -0
- package/src/assets/app/components/input-layout.tsx +47 -0
- package/src/assets/app/components/input-text.tsx +69 -0
- package/src/assets/app/components/layout-title-page.tsx +33 -16
- package/src/assets/app/components/layout-welcome.tsx +30 -14
- package/src/assets/app/components/sign-in-form.tsx +214 -196
- package/src/assets/app/components/sign-up-account-form.tsx +101 -117
- package/src/assets/app/components/sign-up-disclaimer.tsx +1 -1
- package/src/assets/app/hooks/use-api.ts +2 -0
- package/src/assets/app/lib/api.ts +49 -14
- package/src/assets/app/lib/clsx.ts +6 -1
- package/src/assets/app/lib/util.ts +3 -0
- package/src/assets/app/main.css +2 -1
- package/src/assets/app/views/accept-view.tsx +4 -3
- package/src/assets/app/views/authorize-view.tsx +8 -4
- package/src/assets/app/views/error-view.tsx +24 -15
- package/src/assets/app/views/sign-in-view.tsx +5 -15
- package/src/assets/app/views/sign-up-view.tsx +3 -10
- package/src/assets/app/views/welcome-view.tsx +11 -18
- package/src/client/client-auth.ts +3 -2
- package/src/client/client-manager.ts +2 -1
- package/src/client/client.ts +3 -1
- package/src/dpop/dpop-manager.ts +3 -2
- package/src/errors/invalid-token-error.ts +3 -1
- package/src/errors/second-authentication-factor-required-error.ts +25 -0
- package/src/lib/util/authorization-header.ts +1 -1
- package/src/metadata/build-metadata.ts +3 -0
- package/src/oauth-errors.ts +1 -0
- package/src/oauth-provider.ts +110 -99
- package/src/output/{send-authorize-page.ts → build-authorize-data.ts} +3 -43
- package/src/output/build-error-payload.ts +3 -1
- package/src/output/customization.ts +67 -45
- package/src/output/output-manager.ts +87 -0
- package/src/output/send-web-page.ts +4 -3
- package/tailwind.config.js +14 -1
- package/src/assets/app/components/error-card.tsx +0 -41
- package/src/output/send-error-page.ts +0 -41
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
declare const colorNames: readonly ["
|
|
1
|
+
declare const colorNames: readonly ["brand", "error", "warning"];
|
|
2
2
|
type ColorName = (typeof colorNames)[number];
|
|
3
|
-
export type FieldDefinition = {
|
|
4
|
-
label?: string;
|
|
5
|
-
placeholder?: string;
|
|
6
|
-
pattern?: string;
|
|
7
|
-
title?: string;
|
|
8
|
-
};
|
|
9
|
-
export type ExtraFieldDefinition = FieldDefinition & {
|
|
10
|
-
type: 'text' | 'password' | 'date' | 'captcha';
|
|
11
|
-
required?: boolean;
|
|
12
|
-
[_: string]: unknown;
|
|
13
|
-
};
|
|
14
3
|
export type Customization = {
|
|
15
4
|
name?: string;
|
|
16
5
|
logo?: string;
|
|
@@ -33,5 +22,6 @@ export declare function buildCustomizationData({ name, logo, links, }?: Customiz
|
|
|
33
22
|
}[] | undefined;
|
|
34
23
|
};
|
|
35
24
|
export declare function buildCustomizationCss(customization?: Customization): string;
|
|
25
|
+
export declare function buildCustomizationVars(customization?: Customization): Generator<string, void, unknown>;
|
|
36
26
|
export {};
|
|
37
27
|
//# sourceMappingURL=customization.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customization.d.ts","sourceRoot":"","sources":["../../src/output/customization.ts"],"names":[],"mappings":"AACA,QAAA,MAAM,UAAU
|
|
1
|
+
{"version":3,"file":"customization.d.ts","sourceRoot":"","sources":["../../src/output/customization.ts"],"names":[],"mappings":"AACA,QAAA,MAAM,UAAU,wCAAyC,CAAA;AACzD,KAAK,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AAI5C,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE;SAAG,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,MAAM;KAAE,CAAA;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,GAAG,CAAC,EAAE,MAAM,CAAA;KACb,CAAC,CAAA;CACH,CAAA;AAED,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,IAAI,EACJ,KAAK,GACN,GAAE,aAAkB;;;;;;;;EAMpB;AAED,wBAAgB,qBAAqB,CAAC,aAAa,CAAC,EAAE,aAAa,UAKlE;AAED,wBAAiB,sBAAsB,CAAC,aAAa,CAAC,EAAE,aAAa,oCAkBpE"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildCustomizationCss = exports.buildCustomizationData = void 0;
|
|
3
|
+
exports.buildCustomizationVars = exports.buildCustomizationCss = exports.buildCustomizationData = void 0;
|
|
4
4
|
// Matches colors defined in tailwind.config.js
|
|
5
|
-
const colorNames = ['
|
|
5
|
+
const colorNames = ['brand', 'error', 'warning'];
|
|
6
6
|
const isColorName = (name) => colorNames.includes(name);
|
|
7
7
|
function buildCustomizationData({ name, logo, links, } = {}) {
|
|
8
8
|
return {
|
|
@@ -13,50 +13,77 @@ function buildCustomizationData({ name, logo, links, } = {}) {
|
|
|
13
13
|
}
|
|
14
14
|
exports.buildCustomizationData = buildCustomizationData;
|
|
15
15
|
function buildCustomizationCss(customization) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.map(([name, value]) => [name, parseColor(value)])
|
|
21
|
-
.filter((e) => e[1] != null)
|
|
22
|
-
// alpha not supported by tailwind (it does not work that way)
|
|
23
|
-
.map(([name, { r, g, b }]) => `--color-${name}: ${r} ${g} ${b};`);
|
|
24
|
-
return `:root { ${vars.join(' ')} }`;
|
|
16
|
+
const vars = Array.from(buildCustomizationVars(customization));
|
|
17
|
+
if (vars.length)
|
|
18
|
+
return `:root { ${vars.join(' ')} }`;
|
|
19
|
+
return '';
|
|
25
20
|
}
|
|
26
21
|
exports.buildCustomizationCss = buildCustomizationCss;
|
|
22
|
+
function* buildCustomizationVars(customization) {
|
|
23
|
+
if (customization?.colors) {
|
|
24
|
+
for (const [name, value] of Object.entries(customization.colors)) {
|
|
25
|
+
if (!isColorName(name)) {
|
|
26
|
+
throw new TypeError(`Invalid color name: ${name}`);
|
|
27
|
+
}
|
|
28
|
+
// Skip undefined values
|
|
29
|
+
if (value === undefined)
|
|
30
|
+
continue;
|
|
31
|
+
const { r, g, b, a } = parseColor(value);
|
|
32
|
+
// Tailwind does not apply alpha values to base colors
|
|
33
|
+
if (a !== undefined)
|
|
34
|
+
throw new TypeError('Alpha not supported');
|
|
35
|
+
yield `--color-${name}: ${r} ${g} ${b};`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.buildCustomizationVars = buildCustomizationVars;
|
|
27
40
|
function parseColor(color) {
|
|
41
|
+
if (typeof color !== 'string') {
|
|
42
|
+
throw new TypeError(`Invalid color value: ${typeof color}`);
|
|
43
|
+
}
|
|
28
44
|
if (color.startsWith('#')) {
|
|
29
45
|
if (color.length === 4 || color.length === 5) {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
const r = parseUi8Hex(color.slice(1, 2));
|
|
47
|
+
const g = parseUi8Hex(color.slice(2, 3));
|
|
48
|
+
const b = parseUi8Hex(color.slice(3, 4));
|
|
49
|
+
const a = color.length > 4 ? parseUi8Hex(color.slice(4, 5)) : undefined;
|
|
34
50
|
return { r, g, b, a };
|
|
35
51
|
}
|
|
36
52
|
if (color.length === 7 || color.length === 9) {
|
|
37
|
-
const r =
|
|
38
|
-
const g =
|
|
39
|
-
const b =
|
|
40
|
-
const a = color.length > 8 ?
|
|
53
|
+
const r = parseUi8Hex(color.slice(1, 3));
|
|
54
|
+
const g = parseUi8Hex(color.slice(3, 5));
|
|
55
|
+
const b = parseUi8Hex(color.slice(5, 7));
|
|
56
|
+
const a = color.length > 8 ? parseUi8Hex(color.slice(7, 9)) : undefined;
|
|
41
57
|
return { r, g, b, a };
|
|
42
58
|
}
|
|
43
|
-
|
|
59
|
+
throw new TypeError(`Invalid hex color: ${color}`);
|
|
44
60
|
}
|
|
45
|
-
const rgbMatch = color.match(
|
|
61
|
+
const rgbMatch = color.match(/^\s*rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/);
|
|
46
62
|
if (rgbMatch) {
|
|
47
|
-
const
|
|
48
|
-
|
|
63
|
+
const r = parseUi8Dec(rgbMatch[1]);
|
|
64
|
+
const g = parseUi8Dec(rgbMatch[2]);
|
|
65
|
+
const b = parseUi8Dec(rgbMatch[3]);
|
|
66
|
+
return { r, g, b };
|
|
49
67
|
}
|
|
50
|
-
const rgbaMatch = color.match(
|
|
68
|
+
const rgbaMatch = color.match(/^\s*rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/);
|
|
51
69
|
if (rgbaMatch) {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
a: parseInt(a, 10),
|
|
58
|
-
};
|
|
70
|
+
const r = parseUi8Dec(rgbaMatch[1]);
|
|
71
|
+
const g = parseUi8Dec(rgbaMatch[2]);
|
|
72
|
+
const b = parseUi8Dec(rgbaMatch[3]);
|
|
73
|
+
const a = parseUi8Dec(rgbaMatch[4]);
|
|
74
|
+
return { r, g, b, a };
|
|
59
75
|
}
|
|
60
|
-
|
|
76
|
+
throw new TypeError(`Unsupported color format: ${color}`);
|
|
77
|
+
}
|
|
78
|
+
function parseUi8Hex(v) {
|
|
79
|
+
return asUi8(parseInt(v, 16));
|
|
80
|
+
}
|
|
81
|
+
function parseUi8Dec(v) {
|
|
82
|
+
return asUi8(parseInt(v, 10));
|
|
83
|
+
}
|
|
84
|
+
function asUi8(v) {
|
|
85
|
+
if (v >= 0 && v <= 255 && v === (v | 0))
|
|
86
|
+
return v;
|
|
87
|
+
throw new TypeError(`Invalid color component: ${v}`);
|
|
61
88
|
}
|
|
62
89
|
//# sourceMappingURL=customization.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customization.js","sourceRoot":"","sources":["../../src/output/customization.ts"],"names":[],"mappings":";;;AAAA,+CAA+C;AAC/C,MAAM,UAAU,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"customization.js","sourceRoot":"","sources":["../../src/output/customization.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ServerResponse } from 'node:http';
|
|
3
|
+
import { Asset } from '../assets/asset.js';
|
|
4
|
+
import { Html } from '../lib/html/index.js';
|
|
5
|
+
import { AuthorizationResultAuthorize } from './build-authorize-data.js';
|
|
6
|
+
import { Customization } from './customization.js';
|
|
7
|
+
export declare class OutputManager {
|
|
8
|
+
readonly customizationScript: Html;
|
|
9
|
+
readonly customizationStyle: Html;
|
|
10
|
+
readonly customizationLinks?: Customization['links'];
|
|
11
|
+
readonly assetsPromise: Promise<[js: Asset, css: Asset]>;
|
|
12
|
+
constructor(customization?: Customization);
|
|
13
|
+
sendAuthorizePage(res: ServerResponse, data: AuthorizationResultAuthorize): Promise<void>;
|
|
14
|
+
sendErrorPage(res: ServerResponse, err: unknown): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=output-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-manager.d.ts","sourceRoot":"","sources":["../../src/output/output-manager.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE1C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C,OAAO,EAAW,IAAI,EAAQ,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EACL,4BAA4B,EAE7B,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAGL,aAAa,EACd,MAAM,oBAAoB,CAAA;AAG3B,qBAAa,aAAa;IACxB,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAA;IAClC,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAA;IACjC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAA;IAMpD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAG7C;gBAEC,aAAa,CAAC,EAAE,aAAa;IAYnC,iBAAiB,CACrB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,4BAA4B,GACjC,OAAO,CAAC,IAAI,CAAC;IAoBV,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAoBtE"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OutputManager = void 0;
|
|
4
|
+
const index_js_1 = require("../assets/index.js");
|
|
5
|
+
const index_js_2 = require("../lib/html/index.js");
|
|
6
|
+
const build_authorize_data_js_1 = require("./build-authorize-data.js");
|
|
7
|
+
const build_error_payload_js_1 = require("./build-error-payload.js");
|
|
8
|
+
const customization_js_1 = require("./customization.js");
|
|
9
|
+
const send_web_page_js_1 = require("./send-web-page.js");
|
|
10
|
+
class OutputManager {
|
|
11
|
+
customizationScript;
|
|
12
|
+
customizationStyle;
|
|
13
|
+
customizationLinks;
|
|
14
|
+
// Could technically cause an "UnhandledPromiseRejection", which might cause
|
|
15
|
+
// the process to exit. This is intentional, as it's a critical error. It
|
|
16
|
+
// should never happen in practice, as the built assets are bundled with the
|
|
17
|
+
// package.
|
|
18
|
+
assetsPromise = Promise.all([
|
|
19
|
+
(0, index_js_1.getAsset)('main.js'),
|
|
20
|
+
(0, index_js_1.getAsset)('main.css'),
|
|
21
|
+
]);
|
|
22
|
+
constructor(customization) {
|
|
23
|
+
// Note: building this here for two reasons:
|
|
24
|
+
// 1. To avoid re-building it on every request
|
|
25
|
+
// 2. To throw during init if the customization is invalid
|
|
26
|
+
this.customizationScript = (0, send_web_page_js_1.declareBackendData)('__customizationData', (0, customization_js_1.buildCustomizationData)(customization));
|
|
27
|
+
this.customizationStyle = (0, index_js_2.cssCode)((0, customization_js_1.buildCustomizationCss)(customization));
|
|
28
|
+
this.customizationLinks = customization?.links;
|
|
29
|
+
}
|
|
30
|
+
async sendAuthorizePage(res, data) {
|
|
31
|
+
const [jsAsset, cssAsset] = await this.assetsPromise;
|
|
32
|
+
return (0, send_web_page_js_1.sendWebPage)(res, {
|
|
33
|
+
scripts: [
|
|
34
|
+
(0, send_web_page_js_1.declareBackendData)('__authorizeData', (0, build_authorize_data_js_1.buildAuthorizeData)(data)),
|
|
35
|
+
this.customizationScript,
|
|
36
|
+
jsAsset, // Last (to be able to read the "backend data" variables)
|
|
37
|
+
],
|
|
38
|
+
styles: [
|
|
39
|
+
cssAsset, // First (to be overridden by customization)
|
|
40
|
+
this.customizationStyle,
|
|
41
|
+
],
|
|
42
|
+
links: this.customizationLinks,
|
|
43
|
+
htmlAttrs: { lang: 'en' },
|
|
44
|
+
title: 'Authorize',
|
|
45
|
+
body: (0, index_js_2.html) `<div id="root"></div>`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async sendErrorPage(res, err) {
|
|
49
|
+
const [jsAsset, cssAsset] = await this.assetsPromise;
|
|
50
|
+
return (0, send_web_page_js_1.sendWebPage)(res, {
|
|
51
|
+
status: (0, build_error_payload_js_1.buildErrorStatus)(err),
|
|
52
|
+
scripts: [
|
|
53
|
+
(0, send_web_page_js_1.declareBackendData)('__errorData', (0, build_error_payload_js_1.buildErrorPayload)(err)),
|
|
54
|
+
this.customizationScript,
|
|
55
|
+
jsAsset, // Last (to be able to read the "backend data" variables)
|
|
56
|
+
],
|
|
57
|
+
styles: [
|
|
58
|
+
cssAsset, // First (to be overridden by customization)
|
|
59
|
+
this.customizationStyle,
|
|
60
|
+
],
|
|
61
|
+
links: this.customizationLinks,
|
|
62
|
+
htmlAttrs: { lang: 'en' },
|
|
63
|
+
title: 'Error',
|
|
64
|
+
body: (0, index_js_2.html) `<div id="root"></div>`,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.OutputManager = OutputManager;
|
|
69
|
+
//# sourceMappingURL=output-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-manager.js","sourceRoot":"","sources":["../../src/output/output-manager.ts"],"names":[],"mappings":";;;AAGA,iDAA6C;AAC7C,mDAA0D;AAC1D,uEAGkC;AAClC,qEAA8E;AAC9E,yDAI2B;AAC3B,yDAAoE;AAEpE,MAAa,aAAa;IACf,mBAAmB,CAAM;IACzB,kBAAkB,CAAM;IACxB,kBAAkB,CAAyB;IAEpD,4EAA4E;IAC5E,yEAAyE;IACzE,4EAA4E;IAC5E,WAAW;IACF,aAAa,GAAqC,OAAO,CAAC,GAAG,CAAC;QACrE,IAAA,mBAAQ,EAAC,SAAS,CAAC;QACnB,IAAA,mBAAQ,EAAC,UAAU,CAAC;KACZ,CAAC,CAAA;IAEX,YAAY,aAA6B;QACvC,4CAA4C;QAC5C,8CAA8C;QAC9C,0DAA0D;QAC1D,IAAI,CAAC,mBAAmB,GAAG,IAAA,qCAAkB,EAC3C,qBAAqB,EACrB,IAAA,yCAAsB,EAAC,aAAa,CAAC,CACtC,CAAA;QACD,IAAI,CAAC,kBAAkB,GAAG,IAAA,kBAAO,EAAC,IAAA,wCAAqB,EAAC,aAAa,CAAC,CAAC,CAAA;QACvE,IAAI,CAAC,kBAAkB,GAAG,aAAa,EAAE,KAAK,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,GAAmB,EACnB,IAAkC;QAElC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,aAAa,CAAA;QAEpD,OAAO,IAAA,8BAAW,EAAC,GAAG,EAAE;YACtB,OAAO,EAAE;gBACP,IAAA,qCAAkB,EAAC,iBAAiB,EAAE,IAAA,4CAAkB,EAAC,IAAI,CAAC,CAAC;gBAC/D,IAAI,CAAC,mBAAmB;gBACxB,OAAO,EAAE,yDAAyD;aACnE;YACD,MAAM,EAAE;gBACN,QAAQ,EAAE,4CAA4C;gBACtD,IAAI,CAAC,kBAAkB;aACxB;YACD,KAAK,EAAE,IAAI,CAAC,kBAAkB;YAC9B,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACzB,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,IAAA,eAAI,EAAA,uBAAuB;SAClC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAmB,EAAE,GAAY;QACnD,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,MAAM,IAAI,CAAC,aAAa,CAAA;QAEpD,OAAO,IAAA,8BAAW,EAAC,GAAG,EAAE;YACtB,MAAM,EAAE,IAAA,yCAAgB,EAAC,GAAG,CAAC;YAC7B,OAAO,EAAE;gBACP,IAAA,qCAAkB,EAAC,aAAa,EAAE,IAAA,0CAAiB,EAAC,GAAG,CAAC,CAAC;gBACzD,IAAI,CAAC,mBAAmB;gBACxB,OAAO,EAAE,yDAAyD;aACnE;YACD,MAAM,EAAE;gBACN,QAAQ,EAAE,4CAA4C;gBACtD,IAAI,CAAC,kBAAkB;aACxB;YACD,KAAK,EAAE,IAAI,CAAC,kBAAkB;YAC9B,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACzB,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,IAAA,eAAI,EAAA,uBAAuB;SAClC,CAAC,CAAA;IACJ,CAAC;CACF;AArED,sCAqEC"}
|
|
@@ -4,5 +4,5 @@ import { BuildDocumentOptions, Html } from '../lib/html/index.js';
|
|
|
4
4
|
export declare function declareBackendData(name: string, data: unknown): Html;
|
|
5
5
|
export declare function sendWebPage(res: ServerResponse, { status, ...options }: BuildDocumentOptions & {
|
|
6
6
|
status?: number;
|
|
7
|
-
}): void
|
|
7
|
+
}): Promise<void>;
|
|
8
8
|
//# sourceMappingURL=send-web-page.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send-web-page.d.ts","sourceRoot":"","sources":["../../src/output/send-web-page.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE1C,OAAO,EAGL,oBAAoB,EACpB,IAAI,EAEL,MAAM,sBAAsB,CAAA;AAG7B,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,QAM7D;AAED,
|
|
1
|
+
{"version":3,"file":"send-web-page.d.ts","sourceRoot":"","sources":["../../src/output/send-web-page.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE1C,OAAO,EAGL,oBAAoB,EACpB,IAAI,EAEL,MAAM,sBAAsB,CAAA;AAG7B,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,QAM7D;AAED,wBAAsB,WAAW,CAC/B,GAAG,EAAE,cAAc,EACnB,EAAE,MAAY,EAAE,GAAG,OAAO,EAAE,EAAE,oBAAoB,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE,OAAO,CAAC,IAAI,CAAC,CAiCf"}
|
|
@@ -12,8 +12,9 @@ function declareBackendData(name, data) {
|
|
|
12
12
|
return (0, index_js_1.js) `window[${name}]=${data};document.currentScript.remove();`;
|
|
13
13
|
}
|
|
14
14
|
exports.declareBackendData = declareBackendData;
|
|
15
|
-
function sendWebPage(res, { status = 200, ...options }) {
|
|
15
|
+
async function sendWebPage(res, { status = 200, ...options }) {
|
|
16
16
|
// @TODO: make these headers configurable (?)
|
|
17
|
+
res.setHeader('Permissions-Policy', 'otp-credentials=*, document-domain=()');
|
|
17
18
|
res.setHeader('Cross-Origin-Embedder-Policy', 'credentialless');
|
|
18
19
|
res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');
|
|
19
20
|
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
|
|
@@ -34,7 +35,7 @@ function sendWebPage(res, { status = 200, ...options }) {
|
|
|
34
35
|
`upgrade-insecure-requests`,
|
|
35
36
|
].join('; '));
|
|
36
37
|
const html = (0, index_js_1.buildDocument)(options);
|
|
37
|
-
(0, response_js_1.writeHtml)(res, html.toString(), status);
|
|
38
|
+
return (0, response_js_1.writeHtml)(res, html.toString(), status);
|
|
38
39
|
}
|
|
39
40
|
exports.sendWebPage = sendWebPage;
|
|
40
41
|
function assetToHash(asset) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send-web-page.js","sourceRoot":"","sources":["../../src/output/send-web-page.ts"],"names":[],"mappings":";;;AAAA,6CAAwC;AAGxC,mDAM6B;AAC7B,yDAAmD;AAEnD,SAAgB,kBAAkB,CAAC,IAAY,EAAE,IAAa;IAC5D,8EAA8E;IAC9E,8EAA8E;IAC9E,8DAA8D;IAC9D,yDAAyD;IACzD,OAAO,IAAA,aAAE,EAAA,UAAU,IAAI,KAAK,IAAI,mCAAmC,CAAA;AACrE,CAAC;AAND,gDAMC;
|
|
1
|
+
{"version":3,"file":"send-web-page.js","sourceRoot":"","sources":["../../src/output/send-web-page.ts"],"names":[],"mappings":";;;AAAA,6CAAwC;AAGxC,mDAM6B;AAC7B,yDAAmD;AAEnD,SAAgB,kBAAkB,CAAC,IAAY,EAAE,IAAa;IAC5D,8EAA8E;IAC9E,8EAA8E;IAC9E,8DAA8D;IAC9D,yDAAyD;IACzD,OAAO,IAAA,aAAE,EAAA,UAAU,IAAI,KAAK,IAAI,mCAAmC,CAAA;AACrE,CAAC;AAND,gDAMC;AAEM,KAAK,UAAU,WAAW,CAC/B,GAAmB,EACnB,EAAE,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,EAA8C;IAExE,6CAA6C;IAC7C,GAAG,CAAC,SAAS,CAAC,oBAAoB,EAAE,uCAAuC,CAAC,CAAA;IAC5E,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,gBAAgB,CAAC,CAAA;IAC/D,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,aAAa,CAAC,CAAA;IAC5D,GAAG,CAAC,SAAS,CAAC,4BAA4B,EAAE,aAAa,CAAC,CAAA;IAC1D,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAA;IAC/C,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAA;IACxC,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAA;IAClD,GAAG,CAAC,SAAS,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAA;IACtC,GAAG,CAAC,SAAS,CAAC,2BAA2B,EAAE,kBAAkB,CAAC,CAAA;IAC9D,GAAG,CAAC,SAAS,CACX,yBAAyB,EACzB;QACE,oBAAoB;QACpB,wBAAwB;QACxB,oBAAoB;QACpB,YAAY,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,QAAQ,EAAE;QAC9C,qBACE,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EACpE,EAAE;QACF,oBACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EACnE,EAAE;QACF,6BAA6B;QAC7B,oBAAoB;QACpB,2BAA2B;KAC5B,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAA;IAED,MAAM,IAAI,GAAG,IAAA,wBAAa,EAAC,OAAO,CAAC,CAAA;IAEnC,OAAO,IAAA,uBAAS,EAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAA;AAChD,CAAC;AApCD,kCAoCC;AAED,SAAS,WAAW,CAAC,KAAsB;IACzC,OAAO,KAAK,YAAY,eAAI;QAC1B,CAAC,CAAC,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;QAChE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAA;AAClB,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,WAAW,IAAI,GAAG,CAAA;AAC3B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/oauth-provider",
|
|
3
|
-
"version": "0.1.0",
|
|
3
|
+
"version": "0.1.2-rc.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Generic OAuth2 and OpenID Connect provider for Node.js. Currently only supports features needed for Atproto.",
|
|
6
6
|
"keywords": [
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
"psl": "^1.9.0",
|
|
40
40
|
"zod": "^3.23.8",
|
|
41
41
|
"@atproto-labs/fetch": "0.1.0",
|
|
42
|
-
"@atproto-labs/
|
|
42
|
+
"@atproto-labs/simple-store": "0.1.1",
|
|
43
|
+
"@atproto-labs/simple-store-memory": "0.1.1",
|
|
44
|
+
"@atproto/jwk": "0.1.1",
|
|
45
|
+
"@atproto/jwk-jose": "0.1.2-rc.0",
|
|
46
|
+
"@atproto/oauth-types": "0.1.1",
|
|
43
47
|
"@atproto-labs/pipe": "0.1.0",
|
|
44
|
-
"@atproto-labs/
|
|
45
|
-
"@atproto-labs/simple-store-memory": "0.1.0",
|
|
46
|
-
"@atproto/jwk": "0.1.0",
|
|
47
|
-
"@atproto/jwk-jose": "0.1.0",
|
|
48
|
-
"@atproto/oauth-types": "0.1.0"
|
|
48
|
+
"@atproto-labs/fetch-node": "0.1.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@rollup/plugin-commonjs": "^25.0.7",
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
Account,
|
|
10
10
|
AccountInfo,
|
|
11
11
|
AccountStore,
|
|
12
|
-
|
|
12
|
+
SignInCredentials,
|
|
13
13
|
} from './account-store.js'
|
|
14
14
|
|
|
15
15
|
const TIMING_ATTACK_MITIGATION_DELAY = 400
|
|
@@ -18,7 +18,7 @@ export class AccountManager {
|
|
|
18
18
|
constructor(protected readonly store: AccountStore) {}
|
|
19
19
|
|
|
20
20
|
public async signIn(
|
|
21
|
-
credentials:
|
|
21
|
+
credentials: SignInCredentials,
|
|
22
22
|
deviceId: DeviceId,
|
|
23
23
|
): Promise<AccountInfo> {
|
|
24
24
|
return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
+
import z from 'zod'
|
|
2
|
+
|
|
1
3
|
import { ClientId } from '../client/client-id.js'
|
|
2
4
|
import { DeviceId } from '../device/device-id.js'
|
|
3
5
|
import { Awaitable } from '../lib/util/type.js'
|
|
4
6
|
import { Sub } from '../oidc/sub.js'
|
|
5
7
|
import { Account } from './account.js'
|
|
6
8
|
|
|
7
|
-
export
|
|
8
|
-
username: string
|
|
9
|
-
password: string
|
|
9
|
+
export const signInCredentialsSchema = z.object({
|
|
10
|
+
username: z.string(),
|
|
11
|
+
password: z.string(),
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* If false, the account must not be returned from
|
|
13
15
|
* {@link AccountStore.listDeviceAccounts}. Note that this only makes sense when
|
|
14
16
|
* used with a device ID.
|
|
15
17
|
*/
|
|
16
|
-
remember
|
|
17
|
-
|
|
18
|
+
remember: z.boolean().optional().default(false),
|
|
19
|
+
|
|
20
|
+
emailOtp: z.string().optional(),
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export type SignInCredentials = z.TypeOf<typeof signInCredentialsSchema>
|
|
18
24
|
|
|
19
25
|
export type DeviceAccountInfo = {
|
|
20
26
|
remembered: boolean
|
|
@@ -32,7 +38,7 @@ export type AccountInfo = {
|
|
|
32
38
|
|
|
33
39
|
export interface AccountStore {
|
|
34
40
|
authenticateAccount(
|
|
35
|
-
credentials:
|
|
41
|
+
credentials: SignInCredentials,
|
|
36
42
|
deviceId: DeviceId,
|
|
37
43
|
): Awaitable<AccountInfo | null>
|
|
38
44
|
|
|
@@ -1,26 +1,32 @@
|
|
|
1
1
|
import { OAuthClientMetadata } from '@atproto/oauth-types'
|
|
2
|
-
import {
|
|
2
|
+
import { FormEvent } from 'react'
|
|
3
3
|
|
|
4
4
|
import { Account } from '../backend-data'
|
|
5
|
-
import {
|
|
5
|
+
import { Override } from '../lib/util'
|
|
6
6
|
import { AccountIdentifier } from './account-identifier'
|
|
7
|
+
import { Button } from './button'
|
|
7
8
|
import { ClientIdentifier } from './client-identifier'
|
|
8
9
|
import { ClientName } from './client-name'
|
|
10
|
+
import { FormCard, FormCardProps } from './form-card'
|
|
11
|
+
import { Fieldset } from './fieldset'
|
|
9
12
|
|
|
10
|
-
export type AcceptFormProps =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
export type AcceptFormProps = Override<
|
|
14
|
+
FormCardProps,
|
|
15
|
+
{
|
|
16
|
+
account: Account
|
|
17
|
+
clientId: string
|
|
18
|
+
clientMetadata: OAuthClientMetadata
|
|
19
|
+
clientTrusted: boolean
|
|
20
|
+
onAccept: () => void
|
|
21
|
+
acceptLabel?: string
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
onReject: () => void
|
|
24
|
+
rejectLabel?: string
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
26
|
+
onBack?: () => void
|
|
27
|
+
backLabel?: string
|
|
28
|
+
}
|
|
29
|
+
>
|
|
24
30
|
|
|
25
31
|
export function AcceptForm({
|
|
26
32
|
account,
|
|
@@ -34,79 +40,76 @@ export function AcceptForm({
|
|
|
34
40
|
onBack,
|
|
35
41
|
backLabel = 'Back',
|
|
36
42
|
|
|
37
|
-
...
|
|
38
|
-
}: AcceptFormProps
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<img
|
|
44
|
-
crossOrigin="anonymous"
|
|
45
|
-
src={clientMetadata.logo_uri}
|
|
46
|
-
alt={clientMetadata.client_name}
|
|
47
|
-
className="w-16 h-16 rounded-full"
|
|
48
|
-
/>
|
|
49
|
-
</div>
|
|
50
|
-
)}
|
|
51
|
-
|
|
52
|
-
<ClientName
|
|
53
|
-
clientId={clientId}
|
|
54
|
-
clientMetadata={clientMetadata}
|
|
55
|
-
as="h1"
|
|
56
|
-
className="text-2xl font-semibold text-center text-primary"
|
|
57
|
-
/>
|
|
58
|
-
|
|
59
|
-
<p className="mt-4">
|
|
60
|
-
<ClientIdentifier clientId={clientId} clientMetadata={clientMetadata} />{' '}
|
|
61
|
-
is asking for permission to access your{' '}
|
|
62
|
-
<AccountIdentifier account={account} /> account.
|
|
63
|
-
</p>
|
|
64
|
-
|
|
65
|
-
<p className="mt-4">
|
|
66
|
-
By clicking <b>{acceptLabel}</b>, you allow this application to access
|
|
67
|
-
your information in accordance to its{' '}
|
|
68
|
-
<a
|
|
69
|
-
href={clientMetadata.tos_uri}
|
|
70
|
-
rel="nofollow noopener"
|
|
71
|
-
target="_blank"
|
|
72
|
-
className="text-primary underline"
|
|
73
|
-
>
|
|
74
|
-
terms of service
|
|
75
|
-
</a>
|
|
76
|
-
.
|
|
77
|
-
</p>
|
|
43
|
+
...props
|
|
44
|
+
}: AcceptFormProps) {
|
|
45
|
+
const doSubmit = (e: FormEvent) => {
|
|
46
|
+
e.preventDefault()
|
|
47
|
+
onAccept()
|
|
48
|
+
}
|
|
78
49
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
</button>
|
|
50
|
+
return (
|
|
51
|
+
<FormCard
|
|
52
|
+
onSubmit={doSubmit}
|
|
53
|
+
cancel={onBack && <Button onClick={onBack}>{backLabel}</Button>}
|
|
54
|
+
actions={
|
|
55
|
+
<>
|
|
56
|
+
<Button type="submit" color="brand">
|
|
57
|
+
{acceptLabel}
|
|
58
|
+
</Button>
|
|
89
59
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
60
|
+
<Button onClick={onReject}>{rejectLabel}</Button>
|
|
61
|
+
</>
|
|
62
|
+
}
|
|
63
|
+
{...props}
|
|
64
|
+
>
|
|
65
|
+
<Fieldset
|
|
66
|
+
title={
|
|
67
|
+
<ClientName clientId={clientId} clientMetadata={clientMetadata} />
|
|
68
|
+
}
|
|
69
|
+
>
|
|
70
|
+
{clientTrusted && clientMetadata.logo_uri && (
|
|
71
|
+
<div key="logo" className="flex items-center justify-center">
|
|
72
|
+
<img
|
|
73
|
+
crossOrigin="anonymous"
|
|
74
|
+
src={clientMetadata.logo_uri}
|
|
75
|
+
alt={clientMetadata.client_name}
|
|
76
|
+
className="w-16 h-16 rounded-full"
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
98
79
|
)}
|
|
99
80
|
|
|
100
|
-
<
|
|
81
|
+
<p>
|
|
82
|
+
<ClientIdentifier
|
|
83
|
+
clientId={clientId}
|
|
84
|
+
clientMetadata={clientMetadata}
|
|
85
|
+
/>{' '}
|
|
86
|
+
is asking for permission to access your{' '}
|
|
87
|
+
<AccountIdentifier account={account} /> account.
|
|
88
|
+
</p>
|
|
101
89
|
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
90
|
+
<p>
|
|
91
|
+
By clicking <b>{acceptLabel}</b>, you allow this application to access
|
|
92
|
+
your information in accordance to their{' '}
|
|
93
|
+
<a
|
|
94
|
+
href={clientMetadata.tos_uri}
|
|
95
|
+
rel="nofollow noopener"
|
|
96
|
+
target="_blank"
|
|
97
|
+
className="text-brand underline"
|
|
98
|
+
>
|
|
99
|
+
terms of service
|
|
100
|
+
</a>
|
|
101
|
+
{' and '}
|
|
102
|
+
<a
|
|
103
|
+
href={clientMetadata.policy_uri}
|
|
104
|
+
rel="nofollow noopener"
|
|
105
|
+
target="_blank"
|
|
106
|
+
className="text-brand underline"
|
|
107
|
+
>
|
|
108
|
+
privacy policy
|
|
109
|
+
</a>
|
|
110
|
+
.
|
|
111
|
+
</p>
|
|
112
|
+
</Fieldset>
|
|
113
|
+
</FormCard>
|
|
111
114
|
)
|
|
112
115
|
}
|