@owlmeans/server-auth 0.1.18-rc.55 → 0.1.18-rc.56
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 +36 -4
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-auth/SKILL.md +64 -4
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/manager/entrypoints.d.ts.map +1 -1
- package/build/manager/entrypoints.js +1 -9
- package/build/manager/entrypoints.js.map +1 -1
- package/build/manager/plugins/export.d.ts +4 -0
- package/build/manager/plugins/export.d.ts.map +1 -1
- package/build/manager/plugins/export.js +3 -0
- package/build/manager/plugins/export.js.map +1 -1
- package/build/manager/plugins/re-captcha/consts.d.ts +7 -0
- package/build/manager/plugins/re-captcha/consts.d.ts.map +1 -0
- package/build/manager/plugins/re-captcha/consts.js +7 -0
- package/build/manager/plugins/re-captcha/consts.js.map +1 -0
- package/build/manager/plugins/re-captcha/consts.local.d.ts +7 -0
- package/build/manager/plugins/re-captcha/consts.local.d.ts.map +1 -0
- package/build/manager/plugins/re-captcha/consts.local.js +9 -0
- package/build/manager/plugins/re-captcha/consts.local.js.map +1 -0
- package/build/manager/plugins/re-captcha/policy.d.ts +3 -0
- package/build/manager/plugins/re-captcha/policy.d.ts.map +1 -0
- package/build/manager/plugins/re-captcha/policy.js +44 -0
- package/build/manager/plugins/re-captcha/policy.js.map +1 -0
- package/build/manager/plugins/re-captcha/types.d.ts +79 -0
- package/build/manager/plugins/re-captcha/types.d.ts.map +1 -0
- package/build/manager/plugins/re-captcha/types.js +2 -0
- package/build/manager/plugins/re-captcha/types.js.map +1 -0
- package/build/manager/plugins/re-captcha/verifier.d.ts +12 -0
- package/build/manager/plugins/re-captcha/verifier.d.ts.map +1 -0
- package/build/manager/plugins/re-captcha/verifier.js +62 -0
- package/build/manager/plugins/re-captcha/verifier.js.map +1 -0
- package/build/manager/plugins/re-captcha.d.ts +9 -0
- package/build/manager/plugins/re-captcha.d.ts.map +1 -1
- package/build/manager/plugins/re-captcha.js +46 -33
- package/build/manager/plugins/re-captcha.js.map +1 -1
- package/build/manager/plugins/types.d.ts +0 -13
- package/build/manager/plugins/types.d.ts.map +1 -1
- package/build/re-captcha/guard.d.ts +12 -0
- package/build/re-captcha/guard.d.ts.map +1 -0
- package/build/re-captcha/guard.js +43 -0
- package/build/re-captcha/guard.js.map +1 -0
- package/build/re-captcha/index.d.ts +4 -0
- package/build/re-captcha/index.d.ts.map +1 -0
- package/build/re-captcha/index.js +3 -0
- package/build/re-captcha/index.js.map +1 -0
- package/build/re-captcha/token.d.ts +6 -0
- package/build/re-captcha/token.d.ts.map +1 -0
- package/build/re-captcha/token.js +74 -0
- package/build/re-captcha/token.js.map +1 -0
- package/build/re-captcha/types.d.ts +44 -0
- package/build/re-captcha/types.d.ts.map +1 -0
- package/build/re-captcha/types.js +2 -0
- package/build/re-captcha/types.js.map +1 -0
- package/build/service.d.ts.map +1 -1
- package/build/service.js +7 -2
- package/build/service.js.map +1 -1
- package/package.json +20 -20
- package/src/index.ts +1 -1
- package/src/manager/README.md +1 -1
- package/src/manager/entrypoints.ts +1 -10
- package/src/manager/plugins/export.ts +4 -0
- package/src/manager/plugins/re-captcha/consts.local.ts +8 -0
- package/src/manager/plugins/re-captcha/consts.ts +8 -0
- package/src/manager/plugins/re-captcha/policy.ts +56 -0
- package/src/manager/plugins/re-captcha/types.ts +85 -0
- package/src/manager/plugins/re-captcha/verifier.ts +74 -0
- package/src/manager/plugins/re-captcha.ts +54 -39
- package/src/manager/plugins/types.ts +0 -14
- package/src/re-captcha/guard.ts +52 -0
- package/src/re-captcha/index.ts +3 -0
- package/src/re-captcha/token.ts +89 -0
- package/src/re-captcha/types.ts +45 -0
- package/src/service.ts +7 -2
- package/tests/re-captcha.spec.ts +298 -0
- package/build/manager/actions/manager.d.ts +0 -18
- package/build/manager/actions/manager.d.ts.map +0 -1
- package/build/manager/actions/manager.js +0 -11
- package/build/manager/actions/manager.js.map +0 -1
- package/build/manager/plugins/replay-policy.d.ts +0 -8
- package/build/manager/plugins/replay-policy.d.ts.map +0 -1
- package/build/manager/plugins/replay-policy.js +0 -9
- package/build/manager/plugins/replay-policy.js.map +0 -1
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { AppContext, AppConfig } from '../types.js';
|
|
2
2
|
import type { AuthPlugin } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The reCAPTCHA sign-in: proves that a person solved a challenge, and nothing about who they are.
|
|
5
|
+
*
|
|
6
|
+
* The token the manager signs for it is a GUEST credential — `GUEST_ID`, role Guest, `[AUTH_SCOPE]`,
|
|
7
|
+
* type ReCaptcha — whatever identity the caller posted: a profile, an organization, permissions,
|
|
8
|
+
* groups, an expiry and a `source` are dropped before it is signed. Its single-use key is the
|
|
9
|
+
* server-issued challenge it carries. A route accepts it only through `makeReCaptchaGuard`; the
|
|
10
|
+
* bearer exchange refuses it.
|
|
11
|
+
*/
|
|
3
12
|
export declare const makeReCaptchaPlugin: <C extends AppConfig, T extends AppContext<C>>(context: T) => AuthPlugin;
|
|
4
13
|
//# sourceMappingURL=re-captcha.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"re-captcha.d.ts","sourceRoot":"","sources":["../../../src/manager/plugins/re-captcha.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"re-captcha.d.ts","sourceRoot":"","sources":["../../../src/manager/plugins/re-captcha.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAQ5C;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,KAAG,UAqD9F,CAAA"}
|
|
@@ -1,46 +1,59 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PLUGINS } from '@owlmeans/config';
|
|
3
|
-
import { PluginMissconfigured } from '@owlmeans/config';
|
|
4
|
-
import { EntrypointOutcome } from '@owlmeans/entrypoint';
|
|
1
|
+
import { AUTH_SCOPE, AuthenticationType, AuthRole, GUEST_ID, MOD_RECAPTCHA } from '@owlmeans/auth';
|
|
2
|
+
import { PLUGINS, PluginMissconfigured } from '@owlmeans/config';
|
|
5
3
|
import { base64 } from '@scure/base';
|
|
6
4
|
import { randomBytes } from '@noble/hashes/utils.js';
|
|
7
5
|
import { authPluginHelper } from './utils.js';
|
|
6
|
+
import { RECAPTCHA_VERIFIER } from './re-captcha/consts.js';
|
|
7
|
+
import { RECAPTCHA_CREDENTIAL_FIELDS } from './re-captcha/consts.local.js';
|
|
8
|
+
import { makeReCaptchaPolicyModel } from './re-captcha/policy.js';
|
|
9
|
+
import { createReCaptchaVerifierService } from './re-captcha/verifier.js';
|
|
10
|
+
/**
|
|
11
|
+
* The reCAPTCHA sign-in: proves that a person solved a challenge, and nothing about who they are.
|
|
12
|
+
*
|
|
13
|
+
* The token the manager signs for it is a GUEST credential — `GUEST_ID`, role Guest, `[AUTH_SCOPE]`,
|
|
14
|
+
* type ReCaptcha — whatever identity the caller posted: a profile, an organization, permissions,
|
|
15
|
+
* groups, an expiry and a `source` are dropped before it is signed. Its single-use key is the
|
|
16
|
+
* server-issued challenge it carries. A route accepts it only through `makeReCaptchaGuard`; the
|
|
17
|
+
* bearer exchange refuses it.
|
|
18
|
+
*/
|
|
8
19
|
export const makeReCaptchaPlugin = (context) => {
|
|
20
|
+
const verifier = () => context.hasService(RECAPTCHA_VERIFIER)
|
|
21
|
+
? context.service(RECAPTCHA_VERIFIER)
|
|
22
|
+
: createReCaptchaVerifierService();
|
|
23
|
+
/** The secret and the policy of the `MOD_RECAPTCHA` record; no secret = no reCAPTCHA sign-in. */
|
|
24
|
+
const configured = async () => {
|
|
25
|
+
const record = await context.getConfigResource(PLUGINS).load(MOD_RECAPTCHA);
|
|
26
|
+
if (record == null || typeof record.value !== 'string' || record.value === '') {
|
|
27
|
+
throw new PluginMissconfigured('value');
|
|
28
|
+
}
|
|
29
|
+
return [record.value, makeReCaptchaPolicyModel(record)];
|
|
30
|
+
};
|
|
31
|
+
const resetIdentity = (credential) => {
|
|
32
|
+
const fields = credential;
|
|
33
|
+
for (const field of Object.keys(fields)) {
|
|
34
|
+
if (!RECAPTCHA_CREDENTIAL_FIELDS.includes(field)) {
|
|
35
|
+
delete fields[field];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
credential.type = AuthenticationType.ReCaptcha;
|
|
39
|
+
credential.role = AuthRole.Guest;
|
|
40
|
+
credential.userId = GUEST_ID;
|
|
41
|
+
credential.scopes = [AUTH_SCOPE];
|
|
42
|
+
};
|
|
9
43
|
const plugin = {
|
|
10
44
|
type: AuthenticationType.ReCaptcha,
|
|
11
45
|
init: async (request) => {
|
|
12
46
|
authPluginHelper.assertType(request.type, plugin);
|
|
13
|
-
|
|
14
|
-
return { challenge };
|
|
47
|
+
return { challenge: base64.encode(randomBytes(32)) };
|
|
15
48
|
},
|
|
16
49
|
authenticate: async (credential) => {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
body: {
|
|
25
|
-
secret: config.value,
|
|
26
|
-
response: credential.credential
|
|
27
|
-
},
|
|
28
|
-
headers: { 'content-type': 'application/x-www-form-urlencoded' }
|
|
29
|
-
});
|
|
30
|
-
if (status !== EntrypointOutcome.Ok) {
|
|
31
|
-
throw new AuthPluginError('recaptcha:api');
|
|
32
|
-
}
|
|
33
|
-
if (!result.success) {
|
|
34
|
-
throw new AuthenFailed('recaptcha:' + (result['error-codes']?.join(',') ?? 'unknown'));
|
|
35
|
-
}
|
|
36
|
-
credential.scopes = [AUTH_SCOPE];
|
|
37
|
-
credential.role = AuthRole.Guest;
|
|
38
|
-
credential.type = AuthenticationType.ReCaptcha;
|
|
39
|
-
const [previous, challenge] = credential.challenge.split(':');
|
|
40
|
-
if (challenge != null) {
|
|
41
|
-
credential.challenge = previous;
|
|
42
|
-
return { token: previous };
|
|
43
|
-
}
|
|
50
|
+
const [secret, policy] = await configured();
|
|
51
|
+
// Read before the policy is judged: a misconfigured record fails before Google is asked.
|
|
52
|
+
policy.minScore();
|
|
53
|
+
const answer = await verifier().verify({ secret, response: credential.credential });
|
|
54
|
+
policy.assert(answer);
|
|
55
|
+
resetIdentity(credential);
|
|
56
|
+
// '' keeps the manager's own server-issued challenge on the token: that is its spend key.
|
|
44
57
|
return { token: '' };
|
|
45
58
|
}
|
|
46
59
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"re-captcha.js","sourceRoot":"","sources":["../../../src/manager/plugins/re-captcha.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"re-captcha.js","sourceRoot":"","sources":["../../../src/manager/plugins/re-captcha.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { AllowanceResponse } from '@owlmeans/auth';
|
|
2
2
|
import type { AppConfig, AppContext, AuthModel } from '../types.js';
|
|
3
|
-
import type { AbstractRequest } from '@owlmeans/entrypoint';
|
|
4
3
|
import type { RedisResource } from '@owlmeans/redis-resource';
|
|
5
4
|
import type { ResourceRecord } from '@owlmeans/resource';
|
|
6
5
|
import type { AuthChallengeReplayPolicy } from './consts.js';
|
|
@@ -12,18 +11,6 @@ export interface AuthPlugin extends Omit<AuthModel, "rely"> {
|
|
|
12
11
|
*/
|
|
13
12
|
challengeReplayPolicy?: AuthChallengeReplayPolicy;
|
|
14
13
|
}
|
|
15
|
-
export interface RecpatchaResponse {
|
|
16
|
-
success: boolean;
|
|
17
|
-
challenge_ts: number;
|
|
18
|
-
hostname: string;
|
|
19
|
-
'error-codes'?: string[];
|
|
20
|
-
}
|
|
21
|
-
export interface RecaptchaRequest extends AbstractRequest<{
|
|
22
|
-
secret: string;
|
|
23
|
-
response: string;
|
|
24
|
-
remoteip?: string;
|
|
25
|
-
}> {
|
|
26
|
-
}
|
|
27
14
|
export interface RelyRecord extends ResourceRecord, AllowanceResponse {
|
|
28
15
|
}
|
|
29
16
|
export interface AuthRedisResource extends RedisResource<RelyRecord> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/manager/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/manager/plugins/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAE5D,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,qBAAqB,CAAC,EAAE,yBAAyB,CAAA;CAClD;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc,EAAE,iBAAiB;CACpE;AAED,MAAM,WAAW,iBAAkB,SAAQ,aAAa,CAAC,UAAU,CAAC;CAAG;AAEvE,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,UAAU,CAAA;CACvE;AAED,kGAAkG;AAClG,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;IACtD;;;;OAIG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;CACjF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GuardService } from '@owlmeans/entrypoint';
|
|
2
|
+
/**
|
|
3
|
+
* The guard of a route a reCAPTCHA-proven guest may call once (`RECAPTCHA_GUARD`):
|
|
4
|
+
* `Authorization: RE-CAPTCHA <token>`, the token the auth manager's reCAPTCHA plugin issued.
|
|
5
|
+
*
|
|
6
|
+
* Every check of `ReCaptchaTokenHelper.inspect`, then the spend — a token admits one request. The
|
|
7
|
+
* request's `auth` is a guest (`GUEST_ID`, role Guest, `[AUTH_SCOPE]`, type ReCaptcha) with an empty
|
|
8
|
+
* `token`: whatever reads an authorization downstream may log it. A refused token is no credential at
|
|
9
|
+
* all, so the request is unauthenticated (401).
|
|
10
|
+
*/
|
|
11
|
+
export declare const makeReCaptchaGuard: (alias?: string) => GuardService;
|
|
12
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/re-captcha/guard.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAqC,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAI3F;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,WAAW,MAAM,KAAqB,YAkCpE,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { AUTH_SCOPE, AuthenticationType, AuthRole, GUEST_ID, RECAPTCHA_GUARD } from '@owlmeans/auth';
|
|
2
|
+
import { extractAuthToken } from '@owlmeans/auth-common/utils';
|
|
3
|
+
import { createService } from '@owlmeans/context';
|
|
4
|
+
import { reCaptchaTokenOf } from './token.js';
|
|
5
|
+
/**
|
|
6
|
+
* The guard of a route a reCAPTCHA-proven guest may call once (`RECAPTCHA_GUARD`):
|
|
7
|
+
* `Authorization: RE-CAPTCHA <token>`, the token the auth manager's reCAPTCHA plugin issued.
|
|
8
|
+
*
|
|
9
|
+
* Every check of `ReCaptchaTokenHelper.inspect`, then the spend — a token admits one request. The
|
|
10
|
+
* request's `auth` is a guest (`GUEST_ID`, role Guest, `[AUTH_SCOPE]`, type ReCaptcha) with an empty
|
|
11
|
+
* `token`: whatever reads an authorization downstream may log it. A refused token is no credential at
|
|
12
|
+
* all, so the request is unauthenticated (401).
|
|
13
|
+
*/
|
|
14
|
+
export const makeReCaptchaGuard = (alias = RECAPTCHA_GUARD) => {
|
|
15
|
+
const service = createService(alias, {
|
|
16
|
+
match: async (req) => req != null && extractAuthToken(req, AuthenticationType.ReCaptcha) != null,
|
|
17
|
+
handle: async (req, res) => {
|
|
18
|
+
const context = service.assertCtx();
|
|
19
|
+
const tokens = reCaptchaTokenOf(context);
|
|
20
|
+
const guest = await tokens.inspect(req);
|
|
21
|
+
if (guest == null || !await tokens.spend(guest)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const auth = {
|
|
25
|
+
token: '',
|
|
26
|
+
type: AuthenticationType.ReCaptcha,
|
|
27
|
+
role: AuthRole.Guest,
|
|
28
|
+
userId: GUEST_ID,
|
|
29
|
+
scopes: [AUTH_SCOPE],
|
|
30
|
+
isUser: false,
|
|
31
|
+
source: context.cfg.service,
|
|
32
|
+
createdAt: new Date(),
|
|
33
|
+
expiresAt: guest.expiresAt,
|
|
34
|
+
};
|
|
35
|
+
res.resolve(auth);
|
|
36
|
+
return true;
|
|
37
|
+
},
|
|
38
|
+
/** Server-side guard: it verifies what arrives, it never produces a credential. */
|
|
39
|
+
authenticated: async () => null,
|
|
40
|
+
});
|
|
41
|
+
return service;
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/re-captcha/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAEpG,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAK,GAAW,eAAe,EAAgB,EAAE;IAClF,MAAM,OAAO,GAAiB,aAAa,CAAe,KAAK,EAAE;QAC/D,KAAK,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE,CAAC,GAAG,IAAI,IAAI,IAAI,gBAAgB,CAAC,GAAG,EAAE,kBAAkB,CAAC,SAAS,CAAC,IAAI,IAAI;QAE9F,MAAM,EAAE,KAAK,EAAK,GAAoB,EAAE,GAA2B,EAAE,EAAE;YACrE,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAmB,CAAA;YACpD,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;YAExC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YACvC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChD,OAAO,KAAU,CAAA;YACnB,CAAC;YAED,MAAM,IAAI,GAAS;gBACjB,KAAK,EAAE,EAAE;gBACT,IAAI,EAAE,kBAAkB,CAAC,SAAS;gBAClC,IAAI,EAAE,QAAQ,CAAC,KAAK;gBACpB,MAAM,EAAE,QAAQ;gBAChB,MAAM,EAAE,CAAC,UAAU,CAAC;gBACpB,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO;gBAC3B,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B,CAAA;YACD,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YAEjB,OAAO,IAAS,CAAA;QAClB,CAAC;QAED,mFAAmF;QACnF,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;KAChC,CAAC,CAAA;IAEF,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/re-captcha/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,YAAY,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/re-captcha/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Context } from '../types.local.js';
|
|
2
|
+
import type { ReCaptchaTokenHelper } from './types.js';
|
|
3
|
+
export declare const makeReCaptchaTokenHelper: (context: Context) => ReCaptchaTokenHelper;
|
|
4
|
+
/** The reCAPTCHA token checks of a context — built once per context. */
|
|
5
|
+
export declare const reCaptchaTokenOf: (target: Context) => ReCaptchaTokenHelper;
|
|
6
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/re-captcha/token.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAU,OAAO,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAoC,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAIxF,eAAO,MAAM,wBAAwB,YAAa,OAAO,KAAG,oBAoE3D,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,2CAA+C,CAAA"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { AuthenticationType, AuthRole, AuthUnavailable, GUEST_ID } from '@owlmeans/auth';
|
|
2
|
+
import { extractAuthToken, trust } from '@owlmeans/auth-common/utils';
|
|
3
|
+
import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope';
|
|
4
|
+
import { TRUSTED } from '@owlmeans/config';
|
|
5
|
+
import { memoHelper } from '@owlmeans/context';
|
|
6
|
+
import { logger } from '@owlmeans/log';
|
|
7
|
+
import { RecordExists } from '@owlmeans/resource';
|
|
8
|
+
import { AUTH_CACHE, AUTH_SRV_KEY, AUTHEN_TIMEFRAME } from '../consts.js';
|
|
9
|
+
const log = logger('server-auth:re-captcha');
|
|
10
|
+
export const makeReCaptchaTokenHelper = (context) => {
|
|
11
|
+
const refuse = (reason) => {
|
|
12
|
+
log.debug('reCAPTCHA token refused', { reason }, { event: 'auth.refused' });
|
|
13
|
+
return null;
|
|
14
|
+
};
|
|
15
|
+
const verify = async (token) => {
|
|
16
|
+
let envelope;
|
|
17
|
+
try {
|
|
18
|
+
envelope = makeEnvelopeModel(token, EnvelopeKind.Token);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return refuse('token');
|
|
22
|
+
}
|
|
23
|
+
if (envelope.type() !== AuthenticationType.ReCaptcha) {
|
|
24
|
+
return refuse('type');
|
|
25
|
+
}
|
|
26
|
+
// A guest token lives no longer than its spend record does, so it can never be spent twice.
|
|
27
|
+
const ttl = envelope.envelope.ttl;
|
|
28
|
+
if (ttl == null || ttl > AUTHEN_TIMEFRAME) {
|
|
29
|
+
return refuse('ttl');
|
|
30
|
+
}
|
|
31
|
+
const signer = await trust(context, TRUSTED, AUTH_SRV_KEY);
|
|
32
|
+
// Signature and expiry: an envelope past `dt + ttl` does not verify.
|
|
33
|
+
if (!await envelope.verify(signer.key)) {
|
|
34
|
+
return refuse('signature');
|
|
35
|
+
}
|
|
36
|
+
const credential = envelope.message();
|
|
37
|
+
if (credential == null || typeof credential !== 'object') {
|
|
38
|
+
return refuse('token');
|
|
39
|
+
}
|
|
40
|
+
if (credential.credential !== signer.user.id) {
|
|
41
|
+
return refuse('issuer');
|
|
42
|
+
}
|
|
43
|
+
if (credential.type !== AuthenticationType.ReCaptcha || credential.role !== AuthRole.Guest
|
|
44
|
+
|| credential.userId !== GUEST_ID) {
|
|
45
|
+
return refuse('guest');
|
|
46
|
+
}
|
|
47
|
+
if (typeof credential.challenge !== 'string' || credential.challenge === '') {
|
|
48
|
+
return refuse('challenge');
|
|
49
|
+
}
|
|
50
|
+
return { credential, challenge: credential.challenge, expiresAt: new Date(envelope.envelope.dt + ttl) };
|
|
51
|
+
};
|
|
52
|
+
const inspect = async (req) => {
|
|
53
|
+
const token = extractAuthToken(req, AuthenticationType.ReCaptcha);
|
|
54
|
+
return token == null || token === '' ? null : await verify(token);
|
|
55
|
+
};
|
|
56
|
+
const spend = async (guest) => {
|
|
57
|
+
try {
|
|
58
|
+
await context.resource(AUTH_CACHE)
|
|
59
|
+
.create({ id: guest.challenge }, { ttl: AUTHEN_TIMEFRAME / 1000 });
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error instanceof RecordExists || error?.type === RecordExists.typeName) {
|
|
63
|
+
log.debug('reCAPTCHA token refused', { reason: 'spent' }, { event: 'auth.refused' });
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
throw new AuthUnavailable('auth-cache');
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
};
|
|
70
|
+
return { inspect, verify, spend };
|
|
71
|
+
};
|
|
72
|
+
/** The reCAPTCHA token checks of a context — built once per context. */
|
|
73
|
+
export const reCaptchaTokenOf = memoHelper.oncePer(makeReCaptchaTokenHelper);
|
|
74
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/re-captcha/token.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AuthCredentials } from '@owlmeans/auth';
|
|
2
|
+
import type { AbstractRequest } from '@owlmeans/entrypoint';
|
|
3
|
+
/** A reCAPTCHA guest token that passed every check but the spend. */
|
|
4
|
+
export interface ReCaptchaGuest {
|
|
5
|
+
/**
|
|
6
|
+
* The credential the auth manager signed: `GUEST_ID`, role Guest, type ReCaptcha, stamped with
|
|
7
|
+
* the auth service record's id. It names nobody.
|
|
8
|
+
*/
|
|
9
|
+
credential: AuthCredentials;
|
|
10
|
+
/** The server-issued challenge the token carries — the key it is spent under in `AUTH_CACHE`. */
|
|
11
|
+
challenge: string;
|
|
12
|
+
/** When the token stops being accepted. */
|
|
13
|
+
expiresAt: Date;
|
|
14
|
+
}
|
|
15
|
+
/** Anything that carries request headers: an entrypoint request, or a raw Fastify request. */
|
|
16
|
+
export interface ReCaptchaCarrier extends Partial<Pick<AbstractRequest, 'headers'>> {
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The checks of a reCAPTCHA guest token (`Authorization: RE-CAPTCHA <token>`), bound to the context
|
|
20
|
+
* whose `TRUSTED` record `AUTH_SRV_KEY` signed it and whose `AUTH_CACHE` spends it.
|
|
21
|
+
*/
|
|
22
|
+
export interface ReCaptchaTokenHelper {
|
|
23
|
+
/**
|
|
24
|
+
* The guest a request carries, checked WITHOUT spending: envelope type, signature by the auth
|
|
25
|
+
* service key, TTL (at most `AUTHEN_TIMEFRAME`), the auth record's stamp, type ReCaptcha, role
|
|
26
|
+
* Guest, `GUEST_ID`, a server-issued challenge. Made for a pre-parse check (before a body is read);
|
|
27
|
+
* the route itself still needs the guard, which spends.
|
|
28
|
+
*
|
|
29
|
+
* @returns `null` for a request without such a header or with a token that fails a check.
|
|
30
|
+
* @throws {SyntaxError} when the context has no `AUTH_SRV_KEY` trusted record (a configuration fault).
|
|
31
|
+
*/
|
|
32
|
+
inspect: (req: ReCaptchaCarrier) => Promise<ReCaptchaGuest | null>;
|
|
33
|
+
/** {@link inspect} for a bare token (the value after `RE-CAPTCHA `). */
|
|
34
|
+
verify: (token: string) => Promise<ReCaptchaGuest | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Spend the token: an atomic create-once of its challenge in `AUTH_CACHE` (Redis `SET NX` in a
|
|
37
|
+
* backend context), under the same key a bearer exchange and the IAM finalizer claim.
|
|
38
|
+
*
|
|
39
|
+
* @returns `false` when the token was spent before.
|
|
40
|
+
* @throws {AuthUnavailable} when the cache cannot answer.
|
|
41
|
+
*/
|
|
42
|
+
spend: (guest: ReCaptchaGuest) => Promise<boolean>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/re-captcha/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3D,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,UAAU,EAAE,eAAe,CAAA;IAC3B,iGAAiG;IACjG,SAAS,EAAE,MAAM,CAAA;IACjB,2CAA2C;IAC3C,SAAS,EAAE,IAAI,CAAA;CAChB;AAED,8FAA8F;AAC9F,MAAM,WAAW,gBAAiB,SAAQ,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;CAAG;AAEtF;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;OAQG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IAClE,wEAAwE;IACxE,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACzD;;;;;;OAMG;IACH,KAAK,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACnD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/re-captcha/types.ts"],"names":[],"mappings":""}
|
package/build/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAG7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAa,MAAM,YAAY,CAAA;AAa3E,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,kBAAkB,CAAA;AAKvD,eAAO,MAAM,eAAe,WAAW,MAAM,KAAmB,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAG7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAa,MAAM,YAAY,CAAA;AAa3E,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,kBAAkB,CAAA;AAKvD,eAAO,MAAM,eAAe,WAAW,MAAM,KAAmB,WAqM/D,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,OACvE,CAAC,UAAS,MAAM,KACpB,CAAC,GAAG,iBAiBN,CAAA"}
|
package/build/service.js
CHANGED
|
@@ -2,7 +2,7 @@ import { TRUSTED } from '@owlmeans/config';
|
|
|
2
2
|
import { AUTH_CACHE, AUTH_SRV_KEY, AUTHEN_TIMEFRAME, DEFAULT_ALIAS } from './consts.js';
|
|
3
3
|
import { assertContext, createService } from '@owlmeans/context';
|
|
4
4
|
import { EnvelopeKind, makeEnvelopeModel } from '@owlmeans/basic-envelope';
|
|
5
|
-
import { AuthenFailed, AuthorizationError, AuthroizationType, AuthUnavailable } from '@owlmeans/auth';
|
|
5
|
+
import { AuthenFailed, AuthenticationType, AuthorizationError, AuthroizationType, AuthUnavailable } from '@owlmeans/auth';
|
|
6
6
|
import { createStaticResource } from '@owlmeans/static-resource';
|
|
7
7
|
import { trust, extractAuthToken } from '@owlmeans/auth-common/utils';
|
|
8
8
|
import { ENTITY_RESOLVER, TOKEN_UPDATE } from '@owlmeans/auth-common';
|
|
@@ -146,7 +146,12 @@ export const makeAuthService = (alias = DEFAULT_ALIAS) => {
|
|
|
146
146
|
}
|
|
147
147
|
const credentials = envelope.message();
|
|
148
148
|
const msg = credentials.challenge;
|
|
149
|
-
//
|
|
149
|
+
// A reCAPTCHA token proves a solved challenge, never a person: it is spent by
|
|
150
|
+
// `makeReCaptchaGuard` on the one route that takes it and never becomes a session. Refused
|
|
151
|
+
// before the spend, so a token presented here stays usable where it belongs.
|
|
152
|
+
if (envelope.type() === AuthenticationType.ReCaptcha || credentials.type === AuthenticationType.ReCaptcha) {
|
|
153
|
+
throw refuse('guest', new AuthenFailed('guest'), credentials.userId);
|
|
154
|
+
}
|
|
150
155
|
try {
|
|
151
156
|
await cache(context).create({ id: msg }, { ttl: AUTHEN_TIMEFRAME / 1000 });
|
|
152
157
|
}
|
package/build/service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEvF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAmC,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/server-auth",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.56",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -37,31 +37,31 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@noble/hashes": "^2.4.0",
|
|
40
|
-
"@owlmeans/api": "^0.1.18-rc.
|
|
41
|
-
"@owlmeans/api-config-server": "^0.1.18-rc.
|
|
42
|
-
"@owlmeans/auth": "^0.1.18-rc.
|
|
43
|
-
"@owlmeans/auth-common": "^0.1.18-rc.
|
|
44
|
-
"@owlmeans/basic-envelope": "^0.1.18-rc.
|
|
45
|
-
"@owlmeans/basic-ids": "^0.1.18-rc.
|
|
46
|
-
"@owlmeans/basic-keys": "^0.1.18-rc.
|
|
47
|
-
"@owlmeans/client-config": "^0.1.18-rc.
|
|
48
|
-
"@owlmeans/client-entrypoint": "^0.1.18-rc.
|
|
40
|
+
"@owlmeans/api": "^0.1.18-rc.49",
|
|
41
|
+
"@owlmeans/api-config-server": "^0.1.18-rc.53",
|
|
42
|
+
"@owlmeans/auth": "^0.1.18-rc.41",
|
|
43
|
+
"@owlmeans/auth-common": "^0.1.18-rc.49",
|
|
44
|
+
"@owlmeans/basic-envelope": "^0.1.18-rc.48",
|
|
45
|
+
"@owlmeans/basic-ids": "^0.1.18-rc.39",
|
|
46
|
+
"@owlmeans/basic-keys": "^0.1.18-rc.50",
|
|
47
|
+
"@owlmeans/client-config": "^0.1.18-rc.45",
|
|
48
|
+
"@owlmeans/client-entrypoint": "^0.1.18-rc.49",
|
|
49
49
|
"@owlmeans/config": "^0.1.18-rc.44",
|
|
50
50
|
"@owlmeans/context": "^0.1.18-rc.34",
|
|
51
|
-
"@owlmeans/kluster": "^0.1.18-rc.
|
|
52
|
-
"@owlmeans/log": "^0.1.18-rc.
|
|
51
|
+
"@owlmeans/kluster": "^0.1.18-rc.44",
|
|
52
|
+
"@owlmeans/log": "^0.1.18-rc.3",
|
|
53
53
|
"@owlmeans/entrypoint": "^0.1.18-rc.41",
|
|
54
|
-
"@owlmeans/redis-resource": "^0.1.18-rc.
|
|
54
|
+
"@owlmeans/redis-resource": "^0.1.18-rc.46",
|
|
55
55
|
"@owlmeans/resource": "^0.1.18-rc.40",
|
|
56
56
|
"@owlmeans/route": "^0.1.18-rc.35",
|
|
57
|
-
"@owlmeans/server-api": "^0.1.18-rc.
|
|
58
|
-
"@owlmeans/server-auth-identity": "^0.1.18-rc.
|
|
59
|
-
"@owlmeans/server-auth-session": "^0.1.18-rc.
|
|
60
|
-
"@owlmeans/server-context": "^0.1.18-rc.
|
|
57
|
+
"@owlmeans/server-api": "^0.1.18-rc.53",
|
|
58
|
+
"@owlmeans/server-auth-identity": "^0.1.18-rc.49",
|
|
59
|
+
"@owlmeans/server-auth-session": "^0.1.18-rc.18",
|
|
60
|
+
"@owlmeans/server-context": "^0.1.18-rc.44",
|
|
61
61
|
"@owlmeans/server-entrypoint": "^0.1.18-rc.40",
|
|
62
62
|
"@owlmeans/server-route": "^0.1.18-rc.34",
|
|
63
|
-
"@owlmeans/server-socket": "^0.1.18-rc.
|
|
64
|
-
"@owlmeans/socket": "^0.1.18-rc.
|
|
63
|
+
"@owlmeans/server-socket": "^0.1.18-rc.56",
|
|
64
|
+
"@owlmeans/socket": "^0.1.18-rc.42",
|
|
65
65
|
"@owlmeans/static-resource": "^0.1.18-rc.39",
|
|
66
66
|
"@scure/base": "^2.4.0"
|
|
67
67
|
},
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@owlmeans/dep-config": "workspace:*",
|
|
73
|
-
"@owlmeans/test-auth": "^0.1.18-rc.
|
|
73
|
+
"@owlmeans/test-auth": "^0.1.18-rc.48",
|
|
74
74
|
"@types/bun": "^1.4.2",
|
|
75
75
|
"@types/node": "^26.6.4",
|
|
76
76
|
"nodemon": "^3.1.14",
|
package/src/index.ts
CHANGED
package/src/manager/README.md
CHANGED
|
@@ -38,7 +38,7 @@ The manager is built on the OwlMeans entrypoint system, providing:
|
|
|
38
38
|
This manager app is part of the `@owlmeans/server-auth` package:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
npm install @owlmeans/server-auth@^0.1.18-rc.
|
|
41
|
+
npm install @owlmeans/server-auth@^0.1.18-rc.56
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
## API Reference
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import { MOD_RECAPTCHA } from '@owlmeans/auth'
|
|
3
1
|
import { authProtocols } from '@owlmeans/auth-common'
|
|
4
2
|
import { entrypoints as apiConfigBindings } from '@owlmeans/api-config-server'
|
|
5
3
|
import { bind } from '@owlmeans/server-entrypoint'
|
|
6
|
-
import { decorateEntrypoint
|
|
4
|
+
import { decorateEntrypoint } from '@owlmeans/entrypoint'
|
|
7
5
|
import * as actions from './actions/index.js'
|
|
8
|
-
import { backend, route, RouteMethod } from '@owlmeans/route'
|
|
9
6
|
import { DEFAULT_RELY } from './consts.js'
|
|
10
7
|
|
|
11
8
|
const relyProtocol = decorateEntrypoint(authProtocols.rely, { guards: DEFAULT_RELY })
|
|
12
|
-
const reCaptchaProtocol = openProtocol(route(MOD_RECAPTCHA, '/api/siteverify', backend({
|
|
13
|
-
host: 'https://www.google.com',
|
|
14
|
-
base: 'recaptcha',
|
|
15
|
-
secure: true,
|
|
16
|
-
}, RouteMethod.POST)))
|
|
17
9
|
|
|
18
10
|
/** Server entrypoints for the full authentication manager. */
|
|
19
11
|
export const entrypoints = [
|
|
@@ -22,5 +14,4 @@ export const entrypoints = [
|
|
|
22
14
|
bind(authProtocols.authenticate, actions.authenticate(authProtocols.authenticate)),
|
|
23
15
|
bind(relyProtocol, actions.rely(relyProtocol)),
|
|
24
16
|
...apiConfigBindings,
|
|
25
|
-
bind(reCaptchaProtocol),
|
|
26
17
|
]
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
export type * from './types.js'
|
|
3
|
+
export type * from './re-captcha/types.js'
|
|
3
4
|
export * from './consts.js'
|
|
5
|
+
export * from './re-captcha/consts.js'
|
|
6
|
+
export * from './re-captcha/policy.js'
|
|
7
|
+
export * from './re-captcha/verifier.js'
|
|
4
8
|
export * from './basic-ed25519.js'
|
|
5
9
|
export * from './re-captcha.js'
|
|
6
10
|
export * from './basic-rely.js'
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only credential fields a reCAPTCHA guest token keeps. Everything else the caller posted —
|
|
3
|
+
* a profile, an organization (`entitySlug` or `entityId`), permissions, groups, an expiry, a
|
|
4
|
+
* `source` — is dropped: the token proves a solved challenge, never an identity.
|
|
5
|
+
*/
|
|
6
|
+
export const RECAPTCHA_CREDENTIAL_FIELDS: readonly string[] = Object.freeze([
|
|
7
|
+
'type', 'role', 'userId', 'scopes', 'challenge', 'credential',
|
|
8
|
+
])
|