@fabrika/iam-contract 0.8.2 → 0.9.0-cloudflare.2
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/package.json +7 -5
- package/src/access.ts +3 -0
- package/src/index.ts +160 -13
- package/src/oauth.ts +71 -10
- package/src/password-policy.ts +43 -0
- package/types/src/access.d.ts +27 -0
- package/types/src/index.d.ts +745 -0
- package/types/src/oauth.d.ts +136 -0
- package/types/src/password-policy.d.ts +34 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { KeyGrant } from '@fabrika/auth-core';
|
|
2
|
+
/** Managed CIMD registrations only; public dynamic registration is not part of this contract. */
|
|
3
|
+
export interface OAuthManagedClient {
|
|
4
|
+
provider: 'chatgpt' | 'claude';
|
|
5
|
+
clientId: string;
|
|
6
|
+
redirectUris: string[];
|
|
7
|
+
}
|
|
8
|
+
/** RFC 7523 §2.2: the `client_assertion_type` of a JWT client assertion (`private_key_jwt`). */
|
|
9
|
+
export declare const OAUTH_CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
10
|
+
/** The signing algorithms IAM verifies a client assertion with. */
|
|
11
|
+
export declare const OAUTH_CLIENT_ASSERTION_ALGORITHMS: readonly ["RS256"];
|
|
12
|
+
export type OAuthClientAssertionAlgorithm = (typeof OAUTH_CLIENT_ASSERTION_ALGORITHMS)[number];
|
|
13
|
+
interface OAuthClientMetadataFields {
|
|
14
|
+
client_id: string;
|
|
15
|
+
client_name?: string;
|
|
16
|
+
redirect_uris: string[];
|
|
17
|
+
grant_types: ('authorization_code' | 'refresh_token')[];
|
|
18
|
+
response_types: ['code'];
|
|
19
|
+
}
|
|
20
|
+
/** A public client, or one that authenticates with a JWT signed by a key its document publishes. */
|
|
21
|
+
export type OAuthClientMetadataDocument = (OAuthClientMetadataFields & {
|
|
22
|
+
token_endpoint_auth_method: 'none';
|
|
23
|
+
}) | (OAuthClientMetadataFields & {
|
|
24
|
+
token_endpoint_auth_method: 'private_key_jwt';
|
|
25
|
+
/** HTTPS, on the client id's own origin. */
|
|
26
|
+
jwks_uri: string;
|
|
27
|
+
token_endpoint_auth_signing_alg: OAuthClientAssertionAlgorithm;
|
|
28
|
+
});
|
|
29
|
+
/** How a token or revocation request authenticates its client: no credential, or a JWT assertion. */
|
|
30
|
+
export type OAuthClientCredential = {
|
|
31
|
+
method: 'none';
|
|
32
|
+
} | {
|
|
33
|
+
method: 'private_key_jwt';
|
|
34
|
+
assertion: string;
|
|
35
|
+
};
|
|
36
|
+
export interface OAuthResourceDto {
|
|
37
|
+
app: string;
|
|
38
|
+
resource: string;
|
|
39
|
+
/** IAM resolves these app-owned grants; OAuth scope text alone never authorizes an action. */
|
|
40
|
+
scopeGrants: {
|
|
41
|
+
scope: string;
|
|
42
|
+
permissions: KeyGrant[];
|
|
43
|
+
}[];
|
|
44
|
+
/** Used only when scope is omitted. No configured default means invalid_scope, never all scopes. */
|
|
45
|
+
defaultScopes?: string[];
|
|
46
|
+
}
|
|
47
|
+
/** No access token, refresh token, hash, or authorization code appears in a grant DTO. */
|
|
48
|
+
export interface OAuthGrantDto {
|
|
49
|
+
id: string;
|
|
50
|
+
principalId: string;
|
|
51
|
+
clientId: string;
|
|
52
|
+
app: string;
|
|
53
|
+
resource: string;
|
|
54
|
+
scopes: string[];
|
|
55
|
+
createdAt: number;
|
|
56
|
+
expiresAt: number;
|
|
57
|
+
revokedAt: number | null;
|
|
58
|
+
}
|
|
59
|
+
export interface OAuthAuthorizationRequest {
|
|
60
|
+
response_type: 'code';
|
|
61
|
+
client_id: string;
|
|
62
|
+
redirect_uri: string;
|
|
63
|
+
resource: string;
|
|
64
|
+
scope?: string;
|
|
65
|
+
state?: string;
|
|
66
|
+
code_challenge: string;
|
|
67
|
+
code_challenge_method: 'S256';
|
|
68
|
+
}
|
|
69
|
+
export type OAuthAuthorizationCoordinates = Omit<OAuthAuthorizationRequest, 'scope'>;
|
|
70
|
+
export type OAuthAuthorizationParseResult = {
|
|
71
|
+
kind: 'valid';
|
|
72
|
+
request: OAuthAuthorizationRequest;
|
|
73
|
+
} | {
|
|
74
|
+
kind: 'invalid_scope';
|
|
75
|
+
coordinates: OAuthAuthorizationCoordinates;
|
|
76
|
+
rawScope: string;
|
|
77
|
+
} | {
|
|
78
|
+
kind: 'invalid_request';
|
|
79
|
+
};
|
|
80
|
+
export type OAuthTokenRequest = {
|
|
81
|
+
grant_type: 'authorization_code';
|
|
82
|
+
client_id: string;
|
|
83
|
+
code: string;
|
|
84
|
+
redirect_uri: string;
|
|
85
|
+
code_verifier: string;
|
|
86
|
+
resource: string;
|
|
87
|
+
} | {
|
|
88
|
+
grant_type: 'refresh_token';
|
|
89
|
+
client_id: string;
|
|
90
|
+
refresh_token: string;
|
|
91
|
+
resource: string;
|
|
92
|
+
};
|
|
93
|
+
export interface OAuthTokenResponse {
|
|
94
|
+
access_token: string;
|
|
95
|
+
token_type: 'Bearer';
|
|
96
|
+
expires_in: number;
|
|
97
|
+
refresh_token?: string;
|
|
98
|
+
scope: string;
|
|
99
|
+
}
|
|
100
|
+
export interface OAuthRevocationRequest {
|
|
101
|
+
client_id: string;
|
|
102
|
+
token: string;
|
|
103
|
+
token_type_hint?: 'access_token' | 'refresh_token';
|
|
104
|
+
}
|
|
105
|
+
export interface OAuthAuthorizationServerMetadata {
|
|
106
|
+
issuer: string;
|
|
107
|
+
authorization_endpoint: string;
|
|
108
|
+
token_endpoint: string;
|
|
109
|
+
revocation_endpoint: string;
|
|
110
|
+
jwks_uri: string;
|
|
111
|
+
response_types_supported: ['code'];
|
|
112
|
+
grant_types_supported: ['authorization_code', 'refresh_token'];
|
|
113
|
+
code_challenge_methods_supported: ['S256'];
|
|
114
|
+
token_endpoint_auth_methods_supported: ['none', 'private_key_jwt'];
|
|
115
|
+
token_endpoint_auth_signing_alg_values_supported: OAuthClientAssertionAlgorithm[];
|
|
116
|
+
revocation_endpoint_auth_methods_supported: ['none', 'private_key_jwt'];
|
|
117
|
+
revocation_endpoint_auth_signing_alg_values_supported: OAuthClientAssertionAlgorithm[];
|
|
118
|
+
/** RFC 9207: every authorization response carries `iss`. */
|
|
119
|
+
authorization_response_iss_parameter_supported: true;
|
|
120
|
+
client_id_metadata_document_supported: true;
|
|
121
|
+
}
|
|
122
|
+
export declare function parseOAuthManagedClient(value: unknown): OAuthManagedClient | null;
|
|
123
|
+
/** A fetched document cannot enlarge the managed registration's exact redirect allowlist. */
|
|
124
|
+
export declare function parseOAuthClientMetadata(value: unknown, registration: OAuthManagedClient): OAuthClientMetadataDocument | null;
|
|
125
|
+
export declare function parseOAuthResourceDto(value: unknown): OAuthResourceDto | null;
|
|
126
|
+
export declare function resolveOAuthAuthorizationScopes(scope: string | undefined, resource: OAuthResourceDto): string[] | null;
|
|
127
|
+
export declare function parseOAuthAuthorizationAttempt(value: unknown): OAuthAuthorizationParseResult;
|
|
128
|
+
export declare function parseOAuthAuthorizationRequest(value: unknown): OAuthAuthorizationRequest | null;
|
|
129
|
+
export declare function parseOAuthTokenRequest(value: unknown): OAuthTokenRequest | null;
|
|
130
|
+
/**
|
|
131
|
+
* The client credential of a token or revocation request (RFC 7521 §4.2). Neither assertion field is no
|
|
132
|
+
* credential; a half-present pair, another assertion type or an oversized assertion is null.
|
|
133
|
+
*/
|
|
134
|
+
export declare function parseOAuthClientCredential(value: unknown): OAuthClientCredential | null;
|
|
135
|
+
export declare function parseOAuthRevocationRequest(value: unknown): OAuthRevocationRequest | null;
|
|
136
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** The minimum of an installation that never set one: NIST SP 800-63B's for a password that is the only factor. */
|
|
2
|
+
export declare const PASSWORD_DEFAULT_MIN_LENGTH = 15;
|
|
3
|
+
/**
|
|
4
|
+
* The lowest minimum IAM accepts on a runtime whose verifiers meet OWASP's PBKDF2 cost. Below it a password is a PIN, and
|
|
5
|
+
* no throttle makes it one a person can be trusted with.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PASSWORD_MIN_LENGTH_FLOOR = 4;
|
|
8
|
+
/** The most code points a password may have, whatever the minimum. */
|
|
9
|
+
export declare const PASSWORD_MAX_LENGTH = 256;
|
|
10
|
+
/** Below this NIST asks for a second factor, which IAM does not have; the console says so. */
|
|
11
|
+
export declare const PASSWORD_SINGLE_FACTOR_FLOOR = 8;
|
|
12
|
+
/** The password policy as IAM applies it now. */
|
|
13
|
+
export interface PasswordPolicyDto {
|
|
14
|
+
/** The minimum length in Unicode code points that IAM applies to every new password. */
|
|
15
|
+
minLength: number;
|
|
16
|
+
/** The minimum of an installation that never set one, `PASSWORD_DEFAULT_MIN_LENGTH`. */
|
|
17
|
+
defaultMinLength: number;
|
|
18
|
+
/**
|
|
19
|
+
* The lowest minimum this IAM accepts. `PASSWORD_MIN_LENGTH_FLOOR` where verifiers meet OWASP's PBKDF2 cost; the
|
|
20
|
+
* default on a runtime whose cost is lower (a Cloudflare Worker, backlog 201), where a short password is cheap to
|
|
21
|
+
* crack offline.
|
|
22
|
+
*/
|
|
23
|
+
minLengthFloor: number;
|
|
24
|
+
/** The most code points a password may have. */
|
|
25
|
+
maxLength: number;
|
|
26
|
+
/** Whether the installation enables password sign-in at all; the minimum waits for it when it does not. */
|
|
27
|
+
passwordEnabled: boolean;
|
|
28
|
+
/** When an administrator last changed the minimum, in epoch seconds; null when nobody ever did. */
|
|
29
|
+
updatedAt: number | null;
|
|
30
|
+
}
|
|
31
|
+
export interface SetPasswordPolicyRequest {
|
|
32
|
+
/** A whole number from `minLengthFloor` to `maxLength`. */
|
|
33
|
+
minLength: number;
|
|
34
|
+
}
|