@owlmeans/client-auth 0.1.18-rc.3 → 0.1.18-rc.31
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/README.md +280 -37
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/client-auth/SKILL.md +135 -21
- package/build/components/dispatcher/component.js +1 -1
- package/build/components/dispatcher/component.js.map +1 -1
- package/build/entrypoints.d.ts +7 -0
- package/build/entrypoints.d.ts.map +1 -0
- package/build/entrypoints.js +7 -0
- package/build/entrypoints.js.map +1 -0
- package/build/helper.d.ts +2 -1
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +24 -3
- package/build/helper.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/login/adopt.d.ts +24 -0
- package/build/login/adopt.d.ts.map +1 -0
- package/build/login/adopt.js +28 -0
- package/build/login/adopt.js.map +1 -0
- package/build/login/consts.d.ts +49 -0
- package/build/login/consts.d.ts.map +1 -0
- package/build/login/consts.js +49 -0
- package/build/login/consts.js.map +1 -0
- package/build/login/credit.d.ts +24 -0
- package/build/login/credit.d.ts.map +1 -0
- package/build/login/credit.js +58 -0
- package/build/login/credit.js.map +1 -0
- package/build/login/env.d.ts +32 -0
- package/build/login/env.d.ts.map +1 -0
- package/build/login/env.js +84 -0
- package/build/login/env.js.map +1 -0
- package/build/login/flow.d.ts +20 -0
- package/build/login/flow.d.ts.map +1 -0
- package/build/login/flow.js +39 -0
- package/build/login/flow.js.map +1 -0
- package/build/login/hook.d.ts +37 -0
- package/build/login/hook.d.ts.map +1 -0
- package/build/login/hook.js +72 -0
- package/build/login/hook.js.map +1 -0
- package/build/login/i18n/be.json +37 -0
- package/build/login/i18n/de.json +37 -0
- package/build/login/i18n/en.json +37 -0
- package/build/login/i18n/es.json +37 -0
- package/build/login/i18n/pl.json +37 -0
- package/build/login/i18n/ru.json +37 -0
- package/build/login/i18n/uk.json +37 -0
- package/build/login/i18n.d.ts +2 -0
- package/build/login/i18n.d.ts.map +1 -0
- package/build/login/i18n.js +25 -0
- package/build/login/i18n.js.map +1 -0
- package/build/login/index.d.ts +15 -0
- package/build/login/index.d.ts.map +1 -0
- package/build/login/index.js +15 -0
- package/build/login/index.js.map +1 -0
- package/build/login/methods.d.ts +25 -0
- package/build/login/methods.d.ts.map +1 -0
- package/build/login/methods.js +97 -0
- package/build/login/methods.js.map +1 -0
- package/build/login/resume.d.ts +30 -0
- package/build/login/resume.d.ts.map +1 -0
- package/build/login/resume.js +57 -0
- package/build/login/resume.js.map +1 -0
- package/build/login/screen.d.ts +17 -0
- package/build/login/screen.d.ts.map +1 -0
- package/build/login/screen.js +76 -0
- package/build/login/screen.js.map +1 -0
- package/build/login/service.d.ts +31 -0
- package/build/login/service.d.ts.map +1 -0
- package/build/login/service.js +148 -0
- package/build/login/service.js.map +1 -0
- package/build/login/surrogate.d.ts +20 -0
- package/build/login/surrogate.d.ts.map +1 -0
- package/build/login/surrogate.js +33 -0
- package/build/login/surrogate.js.map +1 -0
- package/build/login/terms.d.ts +20 -0
- package/build/login/terms.d.ts.map +1 -0
- package/build/login/terms.js +0 -0
- package/build/login/terms.js.map +1 -0
- package/build/login/types.d.ts +256 -0
- package/build/login/types.d.ts.map +1 -0
- package/build/login/types.js +31 -0
- package/build/login/types.js.map +1 -0
- package/build/manager/components/authentication/control.js +3 -3
- package/build/manager/components/authentication/control.js.map +1 -1
- package/build/manager/components/authentication/types.d.ts +2 -2
- package/build/manager/components/authentication/types.d.ts.map +1 -1
- package/build/manager/components/tunnel-consumer.js +2 -2
- package/build/manager/components/tunnel-consumer.js.map +1 -1
- package/build/manager/entrypoints.d.ts +11 -0
- package/build/manager/entrypoints.d.ts.map +1 -0
- package/build/manager/entrypoints.js +17 -0
- package/build/manager/entrypoints.js.map +1 -0
- package/build/manager/plugins/basic-ed25519.d.ts.map +1 -1
- package/build/manager/plugins/basic-ed25519.js +5 -0
- package/build/manager/plugins/basic-ed25519.js.map +1 -1
- package/build/manager/plugins/exports.d.ts +2 -0
- package/build/manager/plugins/exports.d.ts.map +1 -1
- package/build/manager/plugins/exports.js +2 -0
- package/build/manager/plugins/exports.js.map +1 -1
- package/build/manager/plugins/index.d.ts +1 -5
- package/build/manager/plugins/index.d.ts.map +1 -1
- package/build/manager/plugins/index.js +9 -1
- package/build/manager/plugins/index.js.map +1 -1
- package/build/manager/plugins/methods.d.ts +6 -0
- package/build/manager/plugins/methods.d.ts.map +1 -0
- package/build/manager/plugins/methods.js +65 -0
- package/build/manager/plugins/methods.js.map +1 -0
- package/build/manager/plugins/re-captcha.d.ts.map +1 -1
- package/build/manager/plugins/re-captcha.js +5 -0
- package/build/manager/plugins/re-captcha.js.map +1 -1
- package/build/manager/plugins/registry.d.ts +20 -0
- package/build/manager/plugins/registry.d.ts.map +1 -0
- package/build/manager/plugins/registry.js +19 -0
- package/build/manager/plugins/registry.js.map +1 -0
- package/build/manager/plugins/tunnel-consumer.d.ts.map +1 -1
- package/build/manager/plugins/tunnel-consumer.js +8 -1
- package/build/manager/plugins/tunnel-consumer.js.map +1 -1
- package/build/manager/plugins/types.d.ts +53 -0
- package/build/manager/plugins/types.d.ts.map +1 -1
- package/build/service.js +1 -1
- package/build/service.js.map +1 -1
- package/package.json +36 -27
- package/src/components/dispatcher/component.tsx +1 -1
- package/src/entrypoints.ts +10 -0
- package/src/helper.ts +26 -3
- package/src/index.ts +1 -1
- package/src/login/adopt.ts +31 -0
- package/src/login/consts.ts +64 -0
- package/src/login/credit.ts +75 -0
- package/src/login/env.ts +86 -0
- package/src/login/flow.ts +44 -0
- package/src/login/hook.ts +80 -0
- package/src/login/i18n/be.json +37 -0
- package/src/login/i18n/de.json +37 -0
- package/src/login/i18n/en.json +37 -0
- package/src/login/i18n/es.json +37 -0
- package/src/login/i18n/pl.json +37 -0
- package/src/login/i18n/ru.json +37 -0
- package/src/login/i18n/uk.json +37 -0
- package/src/login/i18n.ts +26 -0
- package/src/login/index.ts +15 -0
- package/src/login/methods.ts +113 -0
- package/src/login/resume.ts +58 -0
- package/src/login/screen.tsx +136 -0
- package/src/login/service.ts +195 -0
- package/src/login/surrogate.ts +45 -0
- package/src/login/terms.ts +0 -0
- package/src/login/types.ts +279 -0
- package/src/manager/README.md +37 -80
- package/src/manager/components/authentication/control.ts +3 -3
- package/src/manager/components/authentication/types.ts +2 -2
- package/src/manager/components/tunnel-consumer.tsx +2 -2
- package/src/manager/entrypoints.ts +18 -0
- package/src/manager/plugins/basic-ed25519.tsx +7 -0
- package/src/manager/plugins/exports.ts +2 -0
- package/src/manager/plugins/index.ts +10 -4
- package/src/manager/plugins/methods.ts +74 -0
- package/src/manager/plugins/re-captcha.tsx +7 -0
- package/src/manager/plugins/registry.ts +26 -0
- package/src/manager/plugins/tunnel-consumer.tsx +10 -1
- package/src/manager/plugins/types.ts +54 -0
- package/src/service.ts +1 -1
- package/tests/context.ts +1 -2
- package/tests/login.spec.ts +332 -0
- package/build/.gitkeep +0 -0
- package/build/manager/modules.d.ts +0 -2
- package/build/manager/modules.d.ts.map +0 -1
- package/build/manager/modules.js +0 -16
- package/build/manager/modules.js.map +0 -1
- package/build/modules.d.ts +0 -4
- package/build/modules.d.ts.map +0 -1
- package/build/modules.js +0 -9
- package/build/modules.js.map +0 -1
- package/src/manager/modules.ts +0 -18
- package/src/modules.ts +0 -13
package/build/helper.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAGnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAS3D,eAAO,MAAM,KAAK,WACR,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAGnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAS3D,eAAO,MAAM,KAAK,WACR,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,YAAY,SAAS,iDAiDtG,CAAA;AAED,eAAO,MAAM,WAAW,WAAW,OAAO,YAoBzC,CAAA"}
|
package/build/helper.js
CHANGED
|
@@ -6,12 +6,15 @@ import { AUTH_QUERY, DISPATCHER } from '@owlmeans/auth';
|
|
|
6
6
|
// import { useFlow } from '@owlmeans/web-flow'
|
|
7
7
|
// import { DEFAULT_ENTITY } from './consts.js'
|
|
8
8
|
// import { OidcAuthStep } from '@owlmeans/flow'
|
|
9
|
-
export const useWs = (module, _request) => {
|
|
9
|
+
export const useWs = (module, _request, options) => {
|
|
10
10
|
const ctx = useContext();
|
|
11
11
|
const mod = useMemo(() => typeof module === 'string' ? ctx.entrypoint(module) : module, [module]);
|
|
12
|
+
// Captured before the token is filled in below, so a caller who supplied their own token
|
|
13
|
+
// keeps full control of it across a reconnect too — `beforeConnect` only refreshes ours.
|
|
14
|
+
const callerSuppliedToken = _request?.query?.[AUTH_QUERY] != null;
|
|
12
15
|
const request = useMemo(() => {
|
|
13
16
|
if (_request == null) {
|
|
14
|
-
_request = provideRequest(mod.
|
|
17
|
+
_request = provideRequest(mod.alias, mod.path());
|
|
15
18
|
}
|
|
16
19
|
try {
|
|
17
20
|
if (_request?.query?.[AUTH_QUERY] == null) {
|
|
@@ -26,7 +29,25 @@ export const useWs = (module, _request) => {
|
|
|
26
29
|
}
|
|
27
30
|
return _request;
|
|
28
31
|
}, [_request]);
|
|
29
|
-
|
|
32
|
+
const wsOptions = useMemo(() => ({
|
|
33
|
+
...options,
|
|
34
|
+
beforeConnect: async (req) => {
|
|
35
|
+
// A reconnect can land minutes after the socket first opened — refresh the bearer token
|
|
36
|
+
// on every attempt rather than trust the one `request` was built with, or a token rotated
|
|
37
|
+
// in between reopens the socket with a stale one the guard then rejects.
|
|
38
|
+
if (!callerSuppliedToken) {
|
|
39
|
+
try {
|
|
40
|
+
req.query ??= {};
|
|
41
|
+
req.query[AUTH_QUERY] = ctx.auth().token;
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
console.error(e);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
await options?.beforeConnect?.(req);
|
|
48
|
+
}
|
|
49
|
+
}), [options, callerSuppliedToken]);
|
|
50
|
+
return useWebSocket(module, request, wsOptions);
|
|
30
51
|
};
|
|
31
52
|
export const useSelfAuth = (force = true /*, entity: string = DEFAULT_ENTITY*/) => {
|
|
32
53
|
const context = useContext();
|
package/build/helper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ export * from './components/index.js';
|
|
|
2
2
|
export type * from './types.js';
|
|
3
3
|
export * from './service.js';
|
|
4
4
|
export * from './consts.js';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './entrypoints.js';
|
|
6
6
|
export * from './helper.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAA;AACrC,mBAAmB,YAAY,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAA;AACrC,mBAAmB,YAAY,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA"}
|
package/build/index.js
CHANGED
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAA;AAErC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAA;AAErC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LoginContext } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The one path an issued bearer token becomes this context's authentication.
|
|
4
|
+
*
|
|
5
|
+
* Resolved by alias rather than through `ctx.auth()` so the login host does not require
|
|
6
|
+
* `AuthServiceAppend` on the context it is given — a plugin can adopt a token on any context that
|
|
7
|
+
* carries the auth service, including one it did not build.
|
|
8
|
+
*
|
|
9
|
+
* Going through `AuthService.update` matters: it stores the record, decodes the envelope and sets
|
|
10
|
+
* both `auth` and `token` in one place. Writing those three by hand — which is what the popup and
|
|
11
|
+
* the MUI relying party each used to do — leaves the same state on a good day and diverges the
|
|
12
|
+
* moment any of it changes.
|
|
13
|
+
*/
|
|
14
|
+
export declare const adoptToken: (ctx: LoginContext, token: string) => Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* The one path this context's authentication is dropped, and the exact mirror of {@link adoptToken}.
|
|
17
|
+
*
|
|
18
|
+
* `undefined`, not `null`: `undefined` is the declared clearing value, and on the web the auth
|
|
19
|
+
* service reacts to it by navigating to the dispatcher. Everything that signs a user out goes
|
|
20
|
+
* through here — the hook, both browser plugins and the surrogate screen — so there is one place
|
|
21
|
+
* where "signed out" is defined rather than four that agree until one of them changes.
|
|
22
|
+
*/
|
|
23
|
+
export declare const revokeToken: (ctx: LoginContext) => Promise<void>;
|
|
24
|
+
//# sourceMappingURL=adopt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt.d.ts","sourceRoot":"","sources":["../../src/login/adopt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,UAAU,QAAe,YAAY,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CAE/E,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,QAAe,YAAY,KAAG,OAAO,CAAC,IAAI,CAEjE,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DEFAULT_ALIAS as AUTH_ALIAS } from '../consts.js';
|
|
2
|
+
/**
|
|
3
|
+
* The one path an issued bearer token becomes this context's authentication.
|
|
4
|
+
*
|
|
5
|
+
* Resolved by alias rather than through `ctx.auth()` so the login host does not require
|
|
6
|
+
* `AuthServiceAppend` on the context it is given — a plugin can adopt a token on any context that
|
|
7
|
+
* carries the auth service, including one it did not build.
|
|
8
|
+
*
|
|
9
|
+
* Going through `AuthService.update` matters: it stores the record, decodes the envelope and sets
|
|
10
|
+
* both `auth` and `token` in one place. Writing those three by hand — which is what the popup and
|
|
11
|
+
* the MUI relying party each used to do — leaves the same state on a good day and diverges the
|
|
12
|
+
* moment any of it changes.
|
|
13
|
+
*/
|
|
14
|
+
export const adoptToken = async (ctx, token) => {
|
|
15
|
+
await ctx.service(AUTH_ALIAS).update(token);
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The one path this context's authentication is dropped, and the exact mirror of {@link adoptToken}.
|
|
19
|
+
*
|
|
20
|
+
* `undefined`, not `null`: `undefined` is the declared clearing value, and on the web the auth
|
|
21
|
+
* service reacts to it by navigating to the dispatcher. Everything that signs a user out goes
|
|
22
|
+
* through here — the hook, both browser plugins and the surrogate screen — so there is one place
|
|
23
|
+
* where "signed out" is defined rather than four that agree until one of them changes.
|
|
24
|
+
*/
|
|
25
|
+
export const revokeToken = async (ctx) => {
|
|
26
|
+
await ctx.service(AUTH_ALIAS).update(undefined);
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=adopt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/login/adopt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,IAAI,UAAU,EAAE,MAAM,cAAc,CAAA;AAG1D;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,GAAiB,EAAE,KAAa,EAAiB,EAAE;IAClF,MAAM,GAAG,CAAC,OAAO,CAAc,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC1D,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,GAAiB,EAAiB,EAAE;IACpE,MAAM,GAAG,CAAC,OAAO,CAAc,UAAU,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;AAC9D,CAAC,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export declare const DEFAULT_ALIAS = "login-service";
|
|
2
|
+
export declare const LOGIN_SERVICE = "login-service";
|
|
3
|
+
/** Priority of a plugin that makes no claim about the environment. */
|
|
4
|
+
export declare const DEFAULT_LOGIN_PRIORITY = 0;
|
|
5
|
+
/** Order given to a method that declares none. */
|
|
6
|
+
export declare const DEFAULT_METHOD_ORDER = 100;
|
|
7
|
+
/**
|
|
8
|
+
* Name given to the surrogate login window, the marker it records about itself, and the values the
|
|
9
|
+
* two documents exchange.
|
|
10
|
+
*
|
|
11
|
+
* These are a wire protocol between two documents that may be running different builds — an opener
|
|
12
|
+
* holding an older bundle and a surrogate freshly loaded, or the reverse. They are therefore fixed,
|
|
13
|
+
* and must never be "tidied" to match a newer vocabulary. That applies to the query names and the
|
|
14
|
+
* message types added later just as much as to the original three.
|
|
15
|
+
*/
|
|
16
|
+
export declare const LOGIN_SURROGATE_NAME = "owlmeans-oidc-login";
|
|
17
|
+
export declare const LOGIN_TOKEN_MESSAGE = "owlmeans:oidc:popup-token";
|
|
18
|
+
export declare const LOGIN_LOGOUT_MESSAGE = "owlmeans:oidc:popup-logout";
|
|
19
|
+
export declare const LOGIN_SURROGATE_MARKER = "_owlmeans-oidc-popup";
|
|
20
|
+
export declare const LOGIN_SURROGATE_WIDTH = 520;
|
|
21
|
+
export declare const LOGIN_SURROGATE_HEIGHT = 760;
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Never centered the window — it carried no `left`/`top`, so the surrogate always
|
|
24
|
+
* opened wherever the browser's own default popup placement put it. Superseded by
|
|
25
|
+
* `@owlmeans/web-client`'s `centeredPopupFeatures(LOGIN_SURROGATE_WIDTH, LOGIN_SURROGATE_HEIGHT)`,
|
|
26
|
+
* computed fresh per call since centering depends on where the browser window currently sits.
|
|
27
|
+
* Kept, unchanged, for the same reason as the rest of this block: an already-generated app may
|
|
28
|
+
* carry a copy of code that still imports it.
|
|
29
|
+
*/
|
|
30
|
+
export declare const LOGIN_SURROGATE_FEATURES = "popup=yes,width=520,height=760";
|
|
31
|
+
/** How often a surrogate window is checked for having been closed by the user. */
|
|
32
|
+
export declare const LOGIN_WATCH_INTERVAL = 500;
|
|
33
|
+
/** Carries WHY the surrogate window was opened across the window boundary. */
|
|
34
|
+
export declare const LOGIN_INTENT_QUERY = "intent";
|
|
35
|
+
/**
|
|
36
|
+
* Carries the address the surrogate should run, so the flow parameters the opener's URL held are
|
|
37
|
+
* forwarded rather than discarded.
|
|
38
|
+
*/
|
|
39
|
+
export declare const LOGIN_NEXT_QUERY = "next";
|
|
40
|
+
/**
|
|
41
|
+
* Carries the method the user already chose, one window up.
|
|
42
|
+
*
|
|
43
|
+
* A surrogate acting on it is not an auto-redirect in the "never choose for the user" sense: the
|
|
44
|
+
* choice was made, by a person, in the document that opened this one.
|
|
45
|
+
*/
|
|
46
|
+
export declare const LOGIN_METHOD_QUERY = "method";
|
|
47
|
+
/** Where a browser records that it agreed to one exact set of legal documents. */
|
|
48
|
+
export declare const LOGIN_TERMS_STORAGE = "_owlmeans-login-terms";
|
|
49
|
+
//# sourceMappingURL=consts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../src/login/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAE5C,eAAO,MAAM,aAAa,kBAAgB,CAAA;AAE1C,sEAAsE;AACtE,eAAO,MAAM,sBAAsB,IAAI,CAAA;AAEvC,kDAAkD;AAClD,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,wBAAwB,CAAA;AAEzD,eAAO,MAAM,mBAAmB,8BAA8B,CAAA;AAE9D,eAAO,MAAM,oBAAoB,+BAA+B,CAAA;AAEhE,eAAO,MAAM,sBAAsB,yBAAyB,CAAA;AAE5D,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAExC,eAAO,MAAM,sBAAsB,MAAM,CAAA;AAEzC;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,mCACwC,CAAA;AAE7E,kFAAkF;AAClF,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,WAAW,CAAA;AAE1C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,SAAS,CAAA;AAEtC;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,WAAW,CAAA;AAE1C,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,0BAA0B,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export const DEFAULT_ALIAS = 'login-service';
|
|
2
|
+
export const LOGIN_SERVICE = DEFAULT_ALIAS;
|
|
3
|
+
/** Priority of a plugin that makes no claim about the environment. */
|
|
4
|
+
export const DEFAULT_LOGIN_PRIORITY = 0;
|
|
5
|
+
/** Order given to a method that declares none. */
|
|
6
|
+
export const DEFAULT_METHOD_ORDER = 100;
|
|
7
|
+
/**
|
|
8
|
+
* Name given to the surrogate login window, the marker it records about itself, and the values the
|
|
9
|
+
* two documents exchange.
|
|
10
|
+
*
|
|
11
|
+
* These are a wire protocol between two documents that may be running different builds — an opener
|
|
12
|
+
* holding an older bundle and a surrogate freshly loaded, or the reverse. They are therefore fixed,
|
|
13
|
+
* and must never be "tidied" to match a newer vocabulary. That applies to the query names and the
|
|
14
|
+
* message types added later just as much as to the original three.
|
|
15
|
+
*/
|
|
16
|
+
export const LOGIN_SURROGATE_NAME = 'owlmeans-oidc-login';
|
|
17
|
+
export const LOGIN_TOKEN_MESSAGE = 'owlmeans:oidc:popup-token';
|
|
18
|
+
export const LOGIN_LOGOUT_MESSAGE = 'owlmeans:oidc:popup-logout';
|
|
19
|
+
export const LOGIN_SURROGATE_MARKER = '_owlmeans-oidc-popup';
|
|
20
|
+
export const LOGIN_SURROGATE_WIDTH = 520;
|
|
21
|
+
export const LOGIN_SURROGATE_HEIGHT = 760;
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Never centered the window — it carried no `left`/`top`, so the surrogate always
|
|
24
|
+
* opened wherever the browser's own default popup placement put it. Superseded by
|
|
25
|
+
* `@owlmeans/web-client`'s `centeredPopupFeatures(LOGIN_SURROGATE_WIDTH, LOGIN_SURROGATE_HEIGHT)`,
|
|
26
|
+
* computed fresh per call since centering depends on where the browser window currently sits.
|
|
27
|
+
* Kept, unchanged, for the same reason as the rest of this block: an already-generated app may
|
|
28
|
+
* carry a copy of code that still imports it.
|
|
29
|
+
*/
|
|
30
|
+
export const LOGIN_SURROGATE_FEATURES = `popup=yes,width=${LOGIN_SURROGATE_WIDTH},height=${LOGIN_SURROGATE_HEIGHT}`;
|
|
31
|
+
/** How often a surrogate window is checked for having been closed by the user. */
|
|
32
|
+
export const LOGIN_WATCH_INTERVAL = 500;
|
|
33
|
+
/** Carries WHY the surrogate window was opened across the window boundary. */
|
|
34
|
+
export const LOGIN_INTENT_QUERY = 'intent';
|
|
35
|
+
/**
|
|
36
|
+
* Carries the address the surrogate should run, so the flow parameters the opener's URL held are
|
|
37
|
+
* forwarded rather than discarded.
|
|
38
|
+
*/
|
|
39
|
+
export const LOGIN_NEXT_QUERY = 'next';
|
|
40
|
+
/**
|
|
41
|
+
* Carries the method the user already chose, one window up.
|
|
42
|
+
*
|
|
43
|
+
* A surrogate acting on it is not an auto-redirect in the "never choose for the user" sense: the
|
|
44
|
+
* choice was made, by a person, in the document that opened this one.
|
|
45
|
+
*/
|
|
46
|
+
export const LOGIN_METHOD_QUERY = 'method';
|
|
47
|
+
/** Where a browser records that it agreed to one exact set of legal documents. */
|
|
48
|
+
export const LOGIN_TERMS_STORAGE = '_owlmeans-login-terms';
|
|
49
|
+
//# sourceMappingURL=consts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../../src/login/consts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAA;AAE5C,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAA;AAE1C,sEAAsE;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAA;AAEvC,kDAAkD;AAClD,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAA;AAEvC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,qBAAqB,CAAA;AAEzD,MAAM,CAAC,MAAM,mBAAmB,GAAG,2BAA2B,CAAA;AAE9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,4BAA4B,CAAA;AAEhE,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAA;AAE5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAA;AAExC,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAA;AAEzC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACnC,mBAAmB,qBAAqB,WAAW,sBAAsB,EAAE,CAAA;AAE7E,kFAAkF;AAClF,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAA;AAEvC,8EAA8E;AAC9E,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAA;AAE1C;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAA;AAE1C,kFAAkF;AAClF,MAAM,CAAC,MAAM,mBAAmB,GAAG,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { BrandSettings, LoginCreditConfig } from '@owlmeans/config';
|
|
2
|
+
export interface ResolvedCredit {
|
|
3
|
+
/** Whether "Powered by OwlMeans" is rendered. */
|
|
4
|
+
poweredBy: boolean;
|
|
5
|
+
/** The product and organization line, already composed. Null when there is nothing to say. */
|
|
6
|
+
line: string | null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* What the bottom of the sign-in screen says.
|
|
10
|
+
*
|
|
11
|
+
* It is a copyright notice, so it is composed as one: `© <year> <holder>`. That is the whole
|
|
12
|
+
* reason `copyright` defaults to on — the name on its own reads as a caption, and an application
|
|
13
|
+
* that means to assert a copyright would have had to write the mark and the year into a literal
|
|
14
|
+
* `line` to get one.
|
|
15
|
+
*
|
|
16
|
+
* The organization falls back to its slug because an organization record carries no readable name
|
|
17
|
+
* — so "no name" is the ordinary case, not an error, and a screen that rendered an empty line for
|
|
18
|
+
* it would be worse than one that renders the slug.
|
|
19
|
+
*
|
|
20
|
+
* `line` replaces everything when an app supplies it: a product with its own legal wording should
|
|
21
|
+
* not have to defeat a composition rule to use it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const resolveCredit: (cfg?: LoginCreditConfig, brand?: BrandSettings, service?: string) => ResolvedCredit;
|
|
24
|
+
//# sourceMappingURL=credit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credit.d.ts","sourceRoot":"","sources":["../../src/login/credit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAExE,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAA;IAClB,8FAA8F;IAC9F,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAuBD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,SAClB,iBAAiB,UAAU,aAAa,YAAY,MAAM,KAC/D,cA2BF,CAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The years one notice covers.
|
|
3
|
+
*
|
|
4
|
+
* A range only while the first year is genuinely in the past — an app configured with the current
|
|
5
|
+
* year, or with a year a skewed clock puts in the future, still gets a well-formed notice rather
|
|
6
|
+
* than `© 2026–2026` or a range that runs backwards.
|
|
7
|
+
*/
|
|
8
|
+
const years = (since, now) => since != null && since > 0 && since < now ? `${since}–${now}` : `${now}`;
|
|
9
|
+
/**
|
|
10
|
+
* A configured value that was actually SET.
|
|
11
|
+
*
|
|
12
|
+
* Empty is how a build-time default spells "unset", and this config is filled from environment
|
|
13
|
+
* variables a platform delivers — `BRANDING_ORGANIZATION: meta.brandingOrganization ?? ''` is the
|
|
14
|
+
* shape of every one of them. `??` does not fall through an empty string, so an undelivered
|
|
15
|
+
* organization used to win the fallback chain and compose a line ending in a bare dash.
|
|
16
|
+
*/
|
|
17
|
+
const set = (value) => value != null && value.trim() !== '' ? value : null;
|
|
18
|
+
/**
|
|
19
|
+
* What the bottom of the sign-in screen says.
|
|
20
|
+
*
|
|
21
|
+
* It is a copyright notice, so it is composed as one: `© <year> <holder>`. That is the whole
|
|
22
|
+
* reason `copyright` defaults to on — the name on its own reads as a caption, and an application
|
|
23
|
+
* that means to assert a copyright would have had to write the mark and the year into a literal
|
|
24
|
+
* `line` to get one.
|
|
25
|
+
*
|
|
26
|
+
* The organization falls back to its slug because an organization record carries no readable name
|
|
27
|
+
* — so "no name" is the ordinary case, not an error, and a screen that rendered an empty line for
|
|
28
|
+
* it would be worse than one that renders the slug.
|
|
29
|
+
*
|
|
30
|
+
* `line` replaces everything when an app supplies it: a product with its own legal wording should
|
|
31
|
+
* not have to defeat a composition rule to use it.
|
|
32
|
+
*/
|
|
33
|
+
export const resolveCredit = (cfg, brand, service) => {
|
|
34
|
+
const poweredBy = cfg?.poweredBy ?? true;
|
|
35
|
+
const literal = set(cfg?.line);
|
|
36
|
+
if (literal != null) {
|
|
37
|
+
return { poweredBy, line: literal };
|
|
38
|
+
}
|
|
39
|
+
const product = set(cfg?.product) ?? set(brand?.name) ?? set(service);
|
|
40
|
+
const organization = set(cfg?.organization) ?? set(brand?.organization)
|
|
41
|
+
?? set(cfg?.entity) ?? set(brand?.entity);
|
|
42
|
+
// Whoever the notice names. A product with no organization behind it holds its own copyright,
|
|
43
|
+
// which is why this falls through to the product rather than dropping the notice.
|
|
44
|
+
const holder = set(cfg?.holder) ?? organization ?? product;
|
|
45
|
+
const wording = typeof cfg?.copyright === 'string' ? set(cfg.copyright) : null;
|
|
46
|
+
const notice = cfg?.copyright === false || holder == null
|
|
47
|
+
? organization
|
|
48
|
+
: wording ?? `© ${years(cfg?.since, new Date().getFullYear())} ${holder}`;
|
|
49
|
+
// The product is named beside the notice only when it is not already the thing being claimed —
|
|
50
|
+
// "OwlMeans — © 2026 OwlMeans" says the name twice and neither time usefully.
|
|
51
|
+
return {
|
|
52
|
+
poweredBy,
|
|
53
|
+
line: product != null && notice != null && product !== holder
|
|
54
|
+
? `${product} — ${notice}`
|
|
55
|
+
: notice ?? product,
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=credit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credit.js","sourceRoot":"","sources":["../../src/login/credit.ts"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,MAAM,KAAK,GAAG,CAAC,KAAyB,EAAE,GAAW,EAAU,EAAE,CAC/D,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAA;AAE1E;;;;;;;GAOG;AACH,MAAM,GAAG,GAAG,CAAC,KAAqB,EAAiB,EAAE,CACnD,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA;AAErD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,GAAuB,EAAE,KAAqB,EAAE,OAAgB,EAChD,EAAE;IAClB,MAAM,SAAS,GAAG,GAAG,EAAE,SAAS,IAAI,IAAI,CAAA;IACxC,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAC9B,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACpB,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;IACrC,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAA;IACrE,MAAM,YAAY,GAAG,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,YAAY,CAAC;WAClE,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAE3C,8FAA8F;IAC9F,kFAAkF;IAClF,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,YAAY,IAAI,OAAO,CAAA;IAC1D,MAAM,OAAO,GAAG,OAAO,GAAG,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9E,MAAM,MAAM,GAAG,GAAG,EAAE,SAAS,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI;QACvD,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,OAAO,IAAI,KAAK,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,IAAI,MAAM,EAAE,CAAA;IAE3E,+FAA+F;IAC/F,8EAA8E;IAC9E,OAAO;QACL,SAAS;QACT,IAAI,EAAE,OAAO,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,MAAM;YAC3D,CAAC,CAAC,GAAG,OAAO,MAAM,MAAM,EAAE;YAC1B,CAAC,CAAC,MAAM,IAAI,OAAO;KACtB,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { LoginEnv } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether this document is embedded in a frame.
|
|
4
|
+
*
|
|
5
|
+
* Reading `window.top` across origins throws, and that throw is itself the answer: a `top` that
|
|
6
|
+
* differs and a `top` that cannot be reached both mean "framed".
|
|
7
|
+
*/
|
|
8
|
+
export declare const isEmbedded: () => boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Record that this window is the surrogate login window, while that is still knowable.
|
|
11
|
+
*
|
|
12
|
+
* Must run on the surrogate's **first** load, before the flow navigates to the provider:
|
|
13
|
+
* `window.name` is the only evidence at that point, and browsers clear it as soon as a top-level
|
|
14
|
+
* context goes cross-origin — so by the time the provider redirects back, the name is gone and
|
|
15
|
+
* this window would look like an ordinary tab.
|
|
16
|
+
*
|
|
17
|
+
* Idempotent, and a no-op in every window that is not the surrogate.
|
|
18
|
+
*/
|
|
19
|
+
export declare const markSurrogate: () => void;
|
|
20
|
+
/** Whether this document is the surrogate login window. */
|
|
21
|
+
export declare const isSurrogate: () => boolean;
|
|
22
|
+
/** Forget the surrogate marker — called once its token has been handed back. */
|
|
23
|
+
export declare const clearSurrogate: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Default login environment.
|
|
26
|
+
*
|
|
27
|
+
* The single source of environment truth for cascade selection — a plugin's `match` reads this
|
|
28
|
+
* and never probes `window` itself, so a non-DOM host can drive the same plugins by supplying its
|
|
29
|
+
* own descriptor.
|
|
30
|
+
*/
|
|
31
|
+
export declare const defaultLoginEnv: () => LoginEnv;
|
|
32
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/login/env.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,UAAU,QAAO,OAM7B,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,QAAO,IAUhC,CAAA;AAED,2DAA2D;AAC3D,eAAO,MAAM,WAAW,QAAO,OAY9B,CAAA;AAED,gFAAgF;AAChF,eAAO,MAAM,cAAc,QAAO,IAOjC,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,QAAO,QAclC,CAAA"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { LOGIN_SURROGATE_MARKER, LOGIN_SURROGATE_NAME } from './consts.js';
|
|
2
|
+
/**
|
|
3
|
+
* Whether this document is embedded in a frame.
|
|
4
|
+
*
|
|
5
|
+
* Reading `window.top` across origins throws, and that throw is itself the answer: a `top` that
|
|
6
|
+
* differs and a `top` that cannot be reached both mean "framed".
|
|
7
|
+
*/
|
|
8
|
+
export const isEmbedded = () => {
|
|
9
|
+
try {
|
|
10
|
+
return window.self !== window.top;
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Record that this window is the surrogate login window, while that is still knowable.
|
|
18
|
+
*
|
|
19
|
+
* Must run on the surrogate's **first** load, before the flow navigates to the provider:
|
|
20
|
+
* `window.name` is the only evidence at that point, and browsers clear it as soon as a top-level
|
|
21
|
+
* context goes cross-origin — so by the time the provider redirects back, the name is gone and
|
|
22
|
+
* this window would look like an ordinary tab.
|
|
23
|
+
*
|
|
24
|
+
* Idempotent, and a no-op in every window that is not the surrogate.
|
|
25
|
+
*/
|
|
26
|
+
export const markSurrogate = () => {
|
|
27
|
+
if (typeof window === 'undefined' || window.name !== LOGIN_SURROGATE_NAME) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
window.sessionStorage.setItem(LOGIN_SURROGATE_MARKER, '1');
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Storage can be unavailable (private modes, blocked cookies). The `window.name` check still
|
|
35
|
+
// covers the case where nothing cross-origin happened in between.
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/** Whether this document is the surrogate login window. */
|
|
39
|
+
export const isSurrogate = () => {
|
|
40
|
+
if (typeof window === 'undefined') {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (window.name === LOGIN_SURROGATE_NAME) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
return window.sessionStorage.getItem(LOGIN_SURROGATE_MARKER) === '1';
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/** Forget the surrogate marker — called once its token has been handed back. */
|
|
54
|
+
export const clearSurrogate = () => {
|
|
55
|
+
if (typeof window === 'undefined') {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
window.sessionStorage.removeItem(LOGIN_SURROGATE_MARKER);
|
|
60
|
+
}
|
|
61
|
+
catch { /* nothing to clean up if storage was never available */ }
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Default login environment.
|
|
65
|
+
*
|
|
66
|
+
* The single source of environment truth for cascade selection — a plugin's `match` reads this
|
|
67
|
+
* and never probes `window` itself, so a non-DOM host can drive the same plugins by supplying its
|
|
68
|
+
* own descriptor.
|
|
69
|
+
*/
|
|
70
|
+
export const defaultLoginEnv = () => {
|
|
71
|
+
const hasWindow = typeof window !== 'undefined';
|
|
72
|
+
if (!hasWindow) {
|
|
73
|
+
return { hasWindow, embedded: false, surrogate: false, hasOpener: false };
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
hasWindow,
|
|
77
|
+
embedded: isEmbedded(),
|
|
78
|
+
surrogate: isSurrogate(),
|
|
79
|
+
// `Cross-Origin-Opener-Policy: same-origin` from the provider severs this permanently, which
|
|
80
|
+
// is why it is observed rather than assumed from "we were opened by someone".
|
|
81
|
+
hasOpener: window.opener != null,
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/login/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAG1E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,GAAY,EAAE;IACtC,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,GAAG,CAAA;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAAS,EAAE;IACtC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;QAC1E,OAAM;IACR,CAAC;IACD,IAAI,CAAC;QACH,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAA;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,6FAA6F;QAC7F,kEAAkE;IACpE,CAAC;AACH,CAAC,CAAA;AAED,2DAA2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAG,GAAY,EAAE;IACvC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;QACzC,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,sBAAsB,CAAC,KAAK,GAAG,CAAA;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC,CAAA;AAED,gFAAgF;AAChF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAS,EAAE;IACvC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAM;IACR,CAAC;IACD,IAAI,CAAC;QACH,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAA;IAC1D,CAAC;IAAC,MAAM,CAAC,CAAC,wDAAwD,CAAC,CAAC;AACtE,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAa,EAAE;IAC5C,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW,CAAA;IAC/C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;IAC3E,CAAC;IAED,OAAO;QACL,SAAS;QACT,QAAQ,EAAE,UAAU,EAAE;QACtB,SAAS,EAAE,WAAW,EAAE;QACxB,6FAA6F;QAC7F,8EAA8E;QAC9E,SAAS,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;KACjC,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FlowModel } from '@owlmeans/flow';
|
|
2
|
+
/**
|
|
3
|
+
* Bring a freshly booted standard OIDC flow to the step an authorization request can be made from.
|
|
4
|
+
*
|
|
5
|
+
* `stdOidcFlow` starts at `Dispatch`, but `OidcAuthService.authenticate` refuses any state that is
|
|
6
|
+
* not `Ephemeral` and returns null — so an application whose flow was only booted can ask for an
|
|
7
|
+
* authorization URL all day and be told nothing, forever. The dispatcher in this package has always
|
|
8
|
+
* done this transition inline; a relying party that replaces that dispatcher (`web-oidc-rp`,
|
|
9
|
+
* `mui-oidc-rp`) inherited the requirement without the code, which is what left a sign-in button
|
|
10
|
+
* that reported no error and did nothing at all.
|
|
11
|
+
*
|
|
12
|
+
* `Ephemeral` is the branch for an application that is its OWN authority — its flow configuration
|
|
13
|
+
* maps the auth service to a placeholder, which is exactly the generated-application case. An app
|
|
14
|
+
* federated with a real auth service keeps its target and is left alone.
|
|
15
|
+
*
|
|
16
|
+
* Idempotent, and safe to call on every attempt: a flow already past `Dispatch`, or one that is
|
|
17
|
+
* not the standard OIDC flow at all, is returned untouched.
|
|
18
|
+
*/
|
|
19
|
+
export declare const enterOidcAuthorization: (model: FlowModel) => FlowModel;
|
|
20
|
+
//# sourceMappingURL=flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/login/flow.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG/C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,UAAW,SAAS,KAAG,SAsBzD,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { FLOW_PLACEHOLDER, OidcAuthStep, STD_OIDC_FLOW } from '@owlmeans/flow';
|
|
2
|
+
import { DEFAULT_ENTITY } from '../consts.js';
|
|
3
|
+
/**
|
|
4
|
+
* Bring a freshly booted standard OIDC flow to the step an authorization request can be made from.
|
|
5
|
+
*
|
|
6
|
+
* `stdOidcFlow` starts at `Dispatch`, but `OidcAuthService.authenticate` refuses any state that is
|
|
7
|
+
* not `Ephemeral` and returns null — so an application whose flow was only booted can ask for an
|
|
8
|
+
* authorization URL all day and be told nothing, forever. The dispatcher in this package has always
|
|
9
|
+
* done this transition inline; a relying party that replaces that dispatcher (`web-oidc-rp`,
|
|
10
|
+
* `mui-oidc-rp`) inherited the requirement without the code, which is what left a sign-in button
|
|
11
|
+
* that reported no error and did nothing at all.
|
|
12
|
+
*
|
|
13
|
+
* `Ephemeral` is the branch for an application that is its OWN authority — its flow configuration
|
|
14
|
+
* maps the auth service to a placeholder, which is exactly the generated-application case. An app
|
|
15
|
+
* federated with a real auth service keeps its target and is left alone.
|
|
16
|
+
*
|
|
17
|
+
* Idempotent, and safe to call on every attempt: a flow already past `Dispatch`, or one that is
|
|
18
|
+
* not the standard OIDC flow at all, is returned untouched.
|
|
19
|
+
*/
|
|
20
|
+
export const enterOidcAuthorization = (model) => {
|
|
21
|
+
const state = model.state();
|
|
22
|
+
if (state.flow !== STD_OIDC_FLOW || state.step !== OidcAuthStep.Dispatch) {
|
|
23
|
+
return model;
|
|
24
|
+
}
|
|
25
|
+
const target = model.step().service;
|
|
26
|
+
if (state.service == null || state.service === '') {
|
|
27
|
+
model.target(target);
|
|
28
|
+
}
|
|
29
|
+
// The entity travels to this app's own backend, which resolves its default provider by `def`
|
|
30
|
+
// alone. It still has to BE there: the init endpoint rejects a body without one.
|
|
31
|
+
if (state.entityId == null) {
|
|
32
|
+
model.entity(DEFAULT_ENTITY);
|
|
33
|
+
}
|
|
34
|
+
if (target === FLOW_PLACEHOLDER) {
|
|
35
|
+
model.transit(OidcAuthStep.Ephemeral, true);
|
|
36
|
+
}
|
|
37
|
+
return model;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/login/flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE9E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAgB,EAAa,EAAE;IACpE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;IAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,QAAQ,EAAE,CAAC;QACzE,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAA;IACnC,IAAI,KAAK,CAAC,OAAO,IAAI,IAAI,IAAI,KAAK,CAAC,OAAO,KAAK,EAAE,EAAE,CAAC;QAClD,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACtB,CAAC;IAED,6FAA6F;IAC7F,iFAAiF;IACjF,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC3B,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;IAC9B,CAAC;IAED,IAAI,MAAM,KAAK,gBAAgB,EAAE,CAAC;QAChC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;IAC7C,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { MouseEvent } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Wiring for a "Log in" control: where it points, and what it does when clicked.
|
|
4
|
+
*
|
|
5
|
+
* The caller renders one control and attaches one handler — which browsing context the flow can
|
|
6
|
+
* actually complete in is the login service's problem, not the app's. An ordinary tab redirects;
|
|
7
|
+
* an app embedded in a frame runs the flow one window up, because the provider refuses to be
|
|
8
|
+
* framed and its cookies are third-party there.
|
|
9
|
+
*
|
|
10
|
+
* The returned handler is deliberately NOT async and awaits nothing before delegating: a window
|
|
11
|
+
* opened after the user gesture has finished being handled is eaten by the popup blocker.
|
|
12
|
+
*
|
|
13
|
+
* The dispatcher entrypoint is resolved INSIDE the hook, never at module scope. Module bodies run
|
|
14
|
+
* while the app is still being imported, before `registerEntrypoints` has put anything on the
|
|
15
|
+
* context, and a top-level lookup throws `Entrypoint dispatcher not found` — which escapes during
|
|
16
|
+
* import, takes the whole render down, and paints an empty page with no component at fault.
|
|
17
|
+
*/
|
|
18
|
+
export declare const useLogin: (target?: string) => readonly [string, (event?: MouseEvent) => void];
|
|
19
|
+
/**
|
|
20
|
+
* Wiring for a "Log out" control.
|
|
21
|
+
*
|
|
22
|
+
* One control, one handler, no decision — the mirror of {@link useLogin}. Where the session has to
|
|
23
|
+
* be ended (here, or one window up in a surrogate whose storage partition this document cannot
|
|
24
|
+
* reach) is the login plugin's call.
|
|
25
|
+
*
|
|
26
|
+
* NOT async, and nothing is awaited before delegating: logging out of a framed application opens a
|
|
27
|
+
* window, and a window opened after the gesture has finished being handled is eaten by the popup
|
|
28
|
+
* blocker. The surrogate entrypoint is resolved INSIDE the hook for the same reason `useLogin`
|
|
29
|
+
* resolves the dispatcher there.
|
|
30
|
+
*
|
|
31
|
+
* The return shape stays a bare handler rather than `useLogin`'s tuple: a logout control has no
|
|
32
|
+
* address to point at, and every generated application carries a copy of a component that writes
|
|
33
|
+
* `const onLogOut = useLogout()`. `(event?: MouseEvent) => void` is assignable to `() => void`, so
|
|
34
|
+
* `onClick={onLogOut}` keeps compiling everywhere.
|
|
35
|
+
*/
|
|
36
|
+
export declare const useLogout: (target?: string) => ((event?: MouseEvent) => void);
|
|
37
|
+
//# sourceMappingURL=hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/login/hook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAUvC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ,YAAa,MAAM,KAAG,SAAS,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,UAAU,KAAK,IAAI,CAmBxF,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,SAAS,YAAa,MAAM,KAAG,CAAC,CAAC,KAAK,CAAC,EAAE,UAAU,KAAK,IAAI,CAcxE,CAAA"}
|