@hearth-auth/sdk 0.0.1 → 1.0.1
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/dist/admin.d.ts +43 -0
- package/dist/admin.js +126 -0
- package/dist/admin.js.map +1 -0
- package/dist/browser-auth.d.ts +32 -0
- package/dist/browser-auth.js +99 -0
- package/dist/browser-auth.js.map +1 -0
- package/dist/claims.d.ts +86 -0
- package/dist/claims.js +137 -0
- package/dist/claims.js.map +1 -0
- package/dist/client.d.ts +77 -0
- package/dist/client.js +190 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +114 -0
- package/{src/errors.ts → dist/errors.js} +83 -97
- package/dist/errors.js.map +1 -0
- package/dist/hearth-client.d.ts +133 -0
- package/dist/hearth-client.js +192 -0
- package/dist/hearth-client.js.map +1 -0
- package/dist/hearth.d.ts +105 -0
- package/dist/hearth.js +109 -0
- package/dist/hearth.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/introspection-client.d.ts +59 -0
- package/dist/introspection-client.js +36 -0
- package/dist/introspection-client.js.map +1 -0
- package/dist/jwks-client.d.ts +28 -0
- package/dist/jwks-client.js +28 -0
- package/dist/jwks-client.js.map +1 -0
- package/dist/middleware.d.ts +38 -0
- package/dist/middleware.js +51 -0
- package/dist/middleware.js.map +1 -0
- package/dist/pkce.d.ts +64 -0
- package/dist/pkce.js +64 -0
- package/dist/pkce.js.map +1 -0
- package/dist/react.d.ts +32 -0
- package/dist/react.js +41 -0
- package/dist/react.js.map +1 -0
- package/dist/session-version-cache.d.ts +50 -0
- package/dist/session-version-cache.js +129 -0
- package/dist/session-version-cache.js.map +1 -0
- package/dist/types.d.ts +168 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +13 -4
- package/CHANGELOG.md +0 -12
- package/src/admin.ts +0 -157
- package/src/browser-auth.ts +0 -130
- package/src/claims.ts +0 -180
- package/src/client.ts +0 -251
- package/src/generated/google/api/annotations_pb.ts +0 -44
- package/src/generated/google/api/http_pb.ts +0 -467
- package/src/generated/hearth/authz/v1/authz_pb.ts +0 -593
- package/src/generated/hearth/cluster/v1/raft_pb.ts +0 -183
- package/src/generated/hearth/events/v1/audit_pb.ts +0 -886
- package/src/generated/hearth/identity/v1/identity_pb.ts +0 -1673
- package/src/generated/hearth/identity/v1/oauth_pb.ts +0 -1138
- package/src/generated/hearth/rbac/v1/rbac_pb.ts +0 -2000
- package/src/hearth-client.ts +0 -288
- package/src/hearth.ts +0 -224
- package/src/index.ts +0 -106
- package/src/introspection-client.ts +0 -83
- package/src/jwks-client.ts +0 -45
- package/src/middleware.ts +0 -82
- package/src/pkce.ts +0 -129
- package/src/react.tsx +0 -57
- package/src/session-version-cache.ts +0 -167
- package/src/types.ts +0 -188
- package/tests/admin-crud.test.ts +0 -97
- package/tests/auth-flow.test.ts +0 -75
- package/tests/authorize.test.ts +0 -386
- package/tests/claims.test.ts +0 -159
- package/tests/hasPermission.test.ts +0 -152
- package/tests/hearth-client.test.ts +0 -243
- package/tests/helpers.ts +0 -90
- package/tests/jwks.test.ts +0 -62
- package/tests/pkce.test.ts +0 -210
- package/tests/react-useHasPermission.test.tsx +0 -92
- package/tests/required-action.test.ts +0 -276
- package/tests/session-version.test.ts +0 -391
- package/tsconfig.json +0 -16
- package/vitest.config.ts +0 -8
package/src/client.ts
DELETED
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import { decodeJwt } from "jose";
|
|
2
|
-
import { RequiredActionError } from "./errors.js";
|
|
3
|
-
import type {
|
|
4
|
-
AuthorizeParams,
|
|
5
|
-
AuthorizeResponse,
|
|
6
|
-
BootstrapResponse,
|
|
7
|
-
JwksDocument,
|
|
8
|
-
MePermissionsResponse,
|
|
9
|
-
RegisterClientParams,
|
|
10
|
-
OAuthClient,
|
|
11
|
-
TokenExchangeParams,
|
|
12
|
-
TokenResponse,
|
|
13
|
-
UserInfoResponse,
|
|
14
|
-
} from "./types.js";
|
|
15
|
-
|
|
16
|
-
/** Parameters for the PKCE authorization-code callback handler (spec §7). */
|
|
17
|
-
export interface HandleCallbackParams {
|
|
18
|
-
/** Full callback URL including query parameters (`code`, `state`, etc.). */
|
|
19
|
-
callbackUrl: string;
|
|
20
|
-
/** OAuth 2.0 client ID. */
|
|
21
|
-
clientId: string;
|
|
22
|
-
/** Redirect URI registered for this client. */
|
|
23
|
-
redirectUri: string;
|
|
24
|
-
/** PKCE code verifier generated during `login()` (RFC 7636). */
|
|
25
|
-
codeVerifier?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Error thrown when the Hearth API returns an error. */
|
|
29
|
-
export class HearthError extends Error {
|
|
30
|
-
constructor(
|
|
31
|
-
public readonly status: number,
|
|
32
|
-
public readonly body: unknown,
|
|
33
|
-
) {
|
|
34
|
-
super(`Hearth API error ${status}: ${JSON.stringify(body)}`);
|
|
35
|
-
this.name = "HearthError";
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Configuration for HearthApiClient. */
|
|
40
|
-
export interface HearthApiClientConfig {
|
|
41
|
-
baseUrl: string;
|
|
42
|
-
realmId: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Low-level Hearth HTTP API client for auth code flows, token management,
|
|
47
|
-
* JWKS retrieval, and live RBAC claim resolution.
|
|
48
|
-
*
|
|
49
|
-
* @deprecated Use {@link HearthClient} from `hearth-client.js` as the
|
|
50
|
-
* recommended entry point. This class is kept as a lower-level primitive.
|
|
51
|
-
*/
|
|
52
|
-
export class HearthApiClient {
|
|
53
|
-
private readonly baseUrl: string;
|
|
54
|
-
private readonly realmId: string;
|
|
55
|
-
|
|
56
|
-
constructor(config: HearthApiClientConfig) {
|
|
57
|
-
this.baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
58
|
-
this.realmId = config.realmId;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** POST /admin/bootstrap — create realm, admin user, tokens (dev mode only). */
|
|
62
|
-
static async bootstrap(baseUrl: string): Promise<BootstrapResponse> {
|
|
63
|
-
const url = `${baseUrl.replace(/\/$/, "")}/admin/bootstrap`;
|
|
64
|
-
const resp = await fetch(url, { method: "POST" });
|
|
65
|
-
if (!resp.ok) {
|
|
66
|
-
throw new HearthError(resp.status, await resp.json());
|
|
67
|
-
}
|
|
68
|
-
return resp.json() as Promise<BootstrapResponse>;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** POST /clients — register an OAuth 2.0 client. */
|
|
72
|
-
async registerClient(params: RegisterClientParams): Promise<OAuthClient> {
|
|
73
|
-
return this.post("/clients", {
|
|
74
|
-
client_name: params.clientName,
|
|
75
|
-
redirect_uris: params.redirectUris,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** POST /authorize — initiate an authorization code flow. */
|
|
80
|
-
async authorize(params: AuthorizeParams): Promise<AuthorizeResponse> {
|
|
81
|
-
return this.post("/authorize", {
|
|
82
|
-
client_id: params.clientId,
|
|
83
|
-
redirect_uri: params.redirectUri,
|
|
84
|
-
scope: params.scope,
|
|
85
|
-
state: params.state,
|
|
86
|
-
response_type: params.responseType ?? "code",
|
|
87
|
-
user_id: params.userId,
|
|
88
|
-
code_challenge: params.codeChallenge,
|
|
89
|
-
code_challenge_method: params.codeChallengeMethod,
|
|
90
|
-
nonce: params.nonce,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/** POST /token — exchange an authorization code for tokens. */
|
|
95
|
-
async exchangeCode(params: TokenExchangeParams): Promise<TokenResponse> {
|
|
96
|
-
return this.post("/token", {
|
|
97
|
-
client_id: params.clientId,
|
|
98
|
-
code: params.code,
|
|
99
|
-
redirect_uri: params.redirectUri,
|
|
100
|
-
code_verifier: params.codeVerifier,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Handle a PKCE authorization-code callback (spec §7).
|
|
106
|
-
*
|
|
107
|
-
* Extracts the `code` from `callbackUrl`, exchanges it for tokens, then
|
|
108
|
-
* inspects the JWT's `token_type` claim before returning:
|
|
109
|
-
*
|
|
110
|
-
* - If `token_type === "required_action"`: throws {@link RequiredActionError}
|
|
111
|
-
* with `requiredActions` populated from the JWT's `required_actions` claim.
|
|
112
|
-
* - If the callback URL contains `required_action_redirect_uri`: throws
|
|
113
|
-
* {@link RequiredActionError} with `redirectUri` set to that value.
|
|
114
|
-
* - Otherwise: returns the token response normally.
|
|
115
|
-
*/
|
|
116
|
-
async handleCallback(params: HandleCallbackParams): Promise<TokenResponse> {
|
|
117
|
-
const url = new URL(params.callbackUrl);
|
|
118
|
-
const code = url.searchParams.get("code");
|
|
119
|
-
const requiredActionRedirectUri = url.searchParams.get(
|
|
120
|
-
"required_action_redirect_uri",
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
if (!code) {
|
|
124
|
-
throw new Error("handleCallback: no authorization code found in callback URL");
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const tokens = await this.exchangeCode({
|
|
128
|
-
clientId: params.clientId,
|
|
129
|
-
code,
|
|
130
|
-
redirectUri: params.redirectUri,
|
|
131
|
-
codeVerifier: params.codeVerifier,
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// Decode the access token to read Hearth-specific claims.
|
|
135
|
-
let jwtPayload: Record<string, unknown> = {};
|
|
136
|
-
try {
|
|
137
|
-
jwtPayload = decodeJwt(tokens.access_token) as Record<string, unknown>;
|
|
138
|
-
} catch {
|
|
139
|
-
// Non-JWT access tokens (opaque) skip required-action detection.
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const tokenType = jwtPayload["token_type"];
|
|
143
|
-
const requiredActions = Array.isArray(jwtPayload["required_actions"])
|
|
144
|
-
? (jwtPayload["required_actions"] as string[])
|
|
145
|
-
: [];
|
|
146
|
-
|
|
147
|
-
if (tokenType === "required_action") {
|
|
148
|
-
throw new RequiredActionError(
|
|
149
|
-
requiredActions,
|
|
150
|
-
requiredActionRedirectUri ?? undefined,
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (requiredActionRedirectUri !== null) {
|
|
155
|
-
throw new RequiredActionError([], requiredActionRedirectUri);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return tokens;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/** POST /token — refresh tokens using a refresh token. */
|
|
162
|
-
async refreshTokens(
|
|
163
|
-
clientId: string,
|
|
164
|
-
refreshToken: string,
|
|
165
|
-
): Promise<TokenResponse> {
|
|
166
|
-
return this.post("/token", {
|
|
167
|
-
client_id: clientId,
|
|
168
|
-
grant_type: "refresh_token",
|
|
169
|
-
refresh_token: refreshToken,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* GET /v1/me/permissions — fetch the freshly-resolved RBAC claim set
|
|
175
|
-
* for the bearer-token user.
|
|
176
|
-
*
|
|
177
|
-
* Unlike `hasPermission()` on a `createHearth()` client (which reads
|
|
178
|
-
* the cached set from the JWT), this call queries the server and
|
|
179
|
-
* reflects any role/group assignments made since the token was issued.
|
|
180
|
-
*/
|
|
181
|
-
async permissions(accessToken: string): Promise<MePermissionsResponse> {
|
|
182
|
-
const resp = await fetch(`${this.baseUrl}/v1/me/permissions`, {
|
|
183
|
-
headers: {
|
|
184
|
-
"X-Realm-ID": this.realmId,
|
|
185
|
-
Authorization: `Bearer ${accessToken}`,
|
|
186
|
-
},
|
|
187
|
-
});
|
|
188
|
-
if (!resp.ok) {
|
|
189
|
-
throw new HearthError(resp.status, await resp.json());
|
|
190
|
-
}
|
|
191
|
-
return resp.json() as Promise<MePermissionsResponse>;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/** GET /userinfo — retrieve user claims using an access token. */
|
|
195
|
-
async userinfo(accessToken: string): Promise<UserInfoResponse> {
|
|
196
|
-
const resp = await fetch(`${this.baseUrl}/userinfo`, {
|
|
197
|
-
headers: {
|
|
198
|
-
"X-Realm-ID": this.realmId,
|
|
199
|
-
Authorization: `Bearer ${accessToken}`,
|
|
200
|
-
},
|
|
201
|
-
});
|
|
202
|
-
if (!resp.ok) {
|
|
203
|
-
throw new HearthError(resp.status, await resp.json());
|
|
204
|
-
}
|
|
205
|
-
return resp.json() as Promise<UserInfoResponse>;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/** GET /jwks — retrieve the JWKS document. */
|
|
209
|
-
async jwks(): Promise<JwksDocument> {
|
|
210
|
-
const resp = await fetch(`${this.baseUrl}/jwks`);
|
|
211
|
-
if (!resp.ok) {
|
|
212
|
-
throw new HearthError(resp.status, await resp.json());
|
|
213
|
-
}
|
|
214
|
-
return resp.json() as Promise<JwksDocument>;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/** GET /.well-known/openid-configuration — OIDC discovery document. */
|
|
218
|
-
async discovery(): Promise<Record<string, unknown>> {
|
|
219
|
-
const resp = await fetch(
|
|
220
|
-
`${this.baseUrl}/.well-known/openid-configuration`,
|
|
221
|
-
);
|
|
222
|
-
if (!resp.ok) {
|
|
223
|
-
throw new HearthError(resp.status, await resp.json());
|
|
224
|
-
}
|
|
225
|
-
return resp.json() as Promise<Record<string, unknown>>;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/** Creates an AdminClient using the given access token. */
|
|
229
|
-
admin(accessToken: string): AdminClient {
|
|
230
|
-
return new AdminClient(this.baseUrl, this.realmId, accessToken);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
private async post<T>(path: string, body: unknown): Promise<T> {
|
|
235
|
-
const resp = await fetch(`${this.baseUrl}${path}`, {
|
|
236
|
-
method: "POST",
|
|
237
|
-
headers: {
|
|
238
|
-
"Content-Type": "application/json",
|
|
239
|
-
"X-Realm-ID": this.realmId,
|
|
240
|
-
},
|
|
241
|
-
body: JSON.stringify(body),
|
|
242
|
-
});
|
|
243
|
-
if (!resp.ok) {
|
|
244
|
-
throw new HearthError(resp.status, await resp.json());
|
|
245
|
-
}
|
|
246
|
-
return resp.json() as Promise<T>;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// AdminClient is imported here to avoid circular deps — it's re-exported from index.
|
|
251
|
-
import { AdminClient } from "./admin.js";
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// Copyright 2015 Google LLC
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
|
|
15
|
-
// Vendored from github.com/googleapis/googleapis (Apache-2.0).
|
|
16
|
-
// Kept minimal: only annotations.proto + http.proto are needed for
|
|
17
|
-
// google.api.http method annotations. Replaces the buf.build remote
|
|
18
|
-
// dependency so CI never needs the buf module cache hydrated.
|
|
19
|
-
|
|
20
|
-
// @generated by protoc-gen-es v2.12.0 with parameter "target=ts"
|
|
21
|
-
// @generated from file google/api/annotations.proto (package google.api, syntax proto3)
|
|
22
|
-
/* eslint-disable */
|
|
23
|
-
|
|
24
|
-
import type { GenExtension, GenFile } from "@bufbuild/protobuf/codegenv2";
|
|
25
|
-
import { extDesc, fileDesc } from "@bufbuild/protobuf/codegenv2";
|
|
26
|
-
import type { HttpRule } from "./http_pb";
|
|
27
|
-
import { file_google_api_http } from "./http_pb";
|
|
28
|
-
import type { MethodOptions } from "@bufbuild/protobuf/wkt";
|
|
29
|
-
import { file_google_protobuf_descriptor } from "@bufbuild/protobuf/wkt";
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Describes the file google/api/annotations.proto.
|
|
33
|
-
*/
|
|
34
|
-
export const file_google_api_annotations: GenFile = /*@__PURE__*/
|
|
35
|
-
fileDesc("Chxnb29nbGUvYXBpL2Fubm90YXRpb25zLnByb3RvEgpnb29nbGUuYXBpOksKBGh0dHASHi5nb29nbGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucxiwyrwiIAEoCzIULmdvb2dsZS5hcGkuSHR0cFJ1bGVSBGh0dHBCbgoOY29tLmdvb2dsZS5hcGlCEEFubm90YXRpb25zUHJvdG9QAVpBZ29vZ2xlLmdvbGFuZy5vcmcvZ2VucHJvdG8vZ29vZ2xlYXBpcy9hcGkvYW5ub3RhdGlvbnM7YW5ub3RhdGlvbnOiAgRHQVBJYgZwcm90bzM", [file_google_api_http, file_google_protobuf_descriptor]);
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* See `HttpRule`.
|
|
39
|
-
*
|
|
40
|
-
* @generated from extension: google.api.HttpRule http = 72295728;
|
|
41
|
-
*/
|
|
42
|
-
export const http: GenExtension<MethodOptions, HttpRule> = /*@__PURE__*/
|
|
43
|
-
extDesc(file_google_api_annotations, 0);
|
|
44
|
-
|