chukyo-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +227 -0
- package/dist/cjs/albo/client.js +133 -0
- package/dist/cjs/albo/index.js +55 -0
- package/dist/cjs/albo/parser/albo.js +110 -0
- package/dist/cjs/albo/types/albo.js +351 -0
- package/dist/cjs/albo/types/alboCalendar.js +51 -0
- package/dist/cjs/albo/types/alboCommon.js +55 -0
- package/dist/cjs/albo/types/alboInformation.js +136 -0
- package/dist/cjs/albo/types/alboMenu.js +92 -0
- package/dist/cjs/albo/types/alboQuestionnaire.js +229 -0
- package/dist/cjs/albo/types/alboSharedItem.js +137 -0
- package/dist/cjs/albo/types/alboSystem.js +103 -0
- package/dist/cjs/albo/types/alboUniversalForm.js +51 -0
- package/dist/cjs/common/dom.js +137 -0
- package/dist/cjs/common/utils.js +29 -0
- package/dist/cjs/constants.js +127 -0
- package/dist/cjs/core/request.js +39 -0
- package/dist/cjs/cubics/client.js +49 -0
- package/dist/cjs/cubics/index.js +22 -0
- package/dist/cjs/cubics/parser/cubics.js +103 -0
- package/dist/cjs/cubics/types/cubics.js +90 -0
- package/dist/cjs/errors.js +55 -0
- package/dist/cjs/index.js +50 -0
- package/dist/cjs/manabo/client.js +135 -0
- package/dist/cjs/manabo/index.js +44 -0
- package/dist/cjs/manabo/parser/manaboClass.js +386 -0
- package/dist/cjs/manabo/parser/manaboEntry.js +38 -0
- package/dist/cjs/manabo/parser/manaboMail.js +153 -0
- package/dist/cjs/manabo/parser/manaboNews.js +26 -0
- package/dist/cjs/manabo/parser/manaboTimetable.js +93 -0
- package/dist/cjs/manabo/types/manaboClass.js +223 -0
- package/dist/cjs/manabo/types/manaboEntry.js +43 -0
- package/dist/cjs/manabo/types/manaboMail.js +117 -0
- package/dist/cjs/manabo/types/manaboNews.js +20 -0
- package/dist/cjs/manabo/types/manaboTimetable.js +79 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/shib/builder.js +239 -0
- package/dist/cjs/shib/index.js +32 -0
- package/dist/cjs/shib/parser/shibLogin.js +138 -0
- package/dist/cjs/shib/parser/shibUser.js +51 -0
- package/dist/cjs/shib/types/common.js +2 -0
- package/dist/cjs/shib/types/shibLogin.js +92 -0
- package/dist/cjs/shib/types/shibUser.js +44 -0
- package/dist/cjs/transports/fetch.js +84 -0
- package/dist/cjs/types.js +9 -0
- package/dist/esm/albo/client.d.ts +80 -0
- package/dist/esm/albo/client.d.ts.map +1 -0
- package/dist/esm/albo/client.js +129 -0
- package/dist/esm/albo/index.d.ts +12 -0
- package/dist/esm/albo/index.d.ts.map +1 -0
- package/dist/esm/albo/index.js +11 -0
- package/dist/esm/albo/parser/albo.d.ts +69 -0
- package/dist/esm/albo/parser/albo.d.ts.map +1 -0
- package/dist/esm/albo/parser/albo.js +84 -0
- package/dist/esm/albo/types/albo.d.ts +460 -0
- package/dist/esm/albo/types/albo.d.ts.map +1 -0
- package/dist/esm/albo/types/albo.js +348 -0
- package/dist/esm/albo/types/alboCalendar.d.ts +58 -0
- package/dist/esm/albo/types/alboCalendar.d.ts.map +1 -0
- package/dist/esm/albo/types/alboCalendar.js +48 -0
- package/dist/esm/albo/types/alboCommon.d.ts +52 -0
- package/dist/esm/albo/types/alboCommon.d.ts.map +1 -0
- package/dist/esm/albo/types/alboCommon.js +51 -0
- package/dist/esm/albo/types/alboInformation.d.ts +214 -0
- package/dist/esm/albo/types/alboInformation.d.ts.map +1 -0
- package/dist/esm/albo/types/alboInformation.js +133 -0
- package/dist/esm/albo/types/alboMenu.d.ts +114 -0
- package/dist/esm/albo/types/alboMenu.d.ts.map +1 -0
- package/dist/esm/albo/types/alboMenu.js +89 -0
- package/dist/esm/albo/types/alboQuestionnaire.d.ts +442 -0
- package/dist/esm/albo/types/alboQuestionnaire.d.ts.map +1 -0
- package/dist/esm/albo/types/alboQuestionnaire.js +226 -0
- package/dist/esm/albo/types/alboSharedItem.d.ts +205 -0
- package/dist/esm/albo/types/alboSharedItem.d.ts.map +1 -0
- package/dist/esm/albo/types/alboSharedItem.js +134 -0
- package/dist/esm/albo/types/alboSystem.d.ts +129 -0
- package/dist/esm/albo/types/alboSystem.d.ts.map +1 -0
- package/dist/esm/albo/types/alboSystem.js +100 -0
- package/dist/esm/albo/types/alboUniversalForm.d.ts +63 -0
- package/dist/esm/albo/types/alboUniversalForm.d.ts.map +1 -0
- package/dist/esm/albo/types/alboUniversalForm.js +48 -0
- package/dist/esm/common/dom.d.ts +35 -0
- package/dist/esm/common/dom.d.ts.map +1 -0
- package/dist/esm/common/dom.js +120 -0
- package/dist/esm/common/utils.d.ts +15 -0
- package/dist/esm/common/utils.d.ts.map +1 -0
- package/dist/esm/common/utils.js +22 -0
- package/dist/esm/constants.d.ts +113 -0
- package/dist/esm/constants.d.ts.map +1 -0
- package/dist/esm/constants.js +124 -0
- package/dist/esm/core/request.d.ts +29 -0
- package/dist/esm/core/request.d.ts.map +1 -0
- package/dist/esm/core/request.js +33 -0
- package/dist/esm/cubics/client.d.ts +13 -0
- package/dist/esm/cubics/client.d.ts.map +1 -0
- package/dist/esm/cubics/client.js +45 -0
- package/dist/esm/cubics/index.d.ts +4 -0
- package/dist/esm/cubics/index.d.ts.map +1 -0
- package/dist/esm/cubics/index.js +3 -0
- package/dist/esm/cubics/parser/cubics.d.ts +8 -0
- package/dist/esm/cubics/parser/cubics.d.ts.map +1 -0
- package/dist/esm/cubics/parser/cubics.js +99 -0
- package/dist/esm/cubics/types/cubics.d.ts +94 -0
- package/dist/esm/cubics/types/cubics.d.ts.map +1 -0
- package/dist/esm/cubics/types/cubics.js +87 -0
- package/dist/esm/errors.d.ts +46 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +46 -0
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +25 -0
- package/dist/esm/manabo/client.d.ts +75 -0
- package/dist/esm/manabo/client.d.ts.map +1 -0
- package/dist/esm/manabo/client.js +131 -0
- package/dist/esm/manabo/index.d.ts +12 -0
- package/dist/esm/manabo/index.d.ts.map +1 -0
- package/dist/esm/manabo/index.js +11 -0
- package/dist/esm/manabo/parser/manaboClass.d.ts +9 -0
- package/dist/esm/manabo/parser/manaboClass.d.ts.map +1 -0
- package/dist/esm/manabo/parser/manaboClass.js +377 -0
- package/dist/esm/manabo/parser/manaboEntry.d.ts +8 -0
- package/dist/esm/manabo/parser/manaboEntry.d.ts.map +1 -0
- package/dist/esm/manabo/parser/manaboEntry.js +33 -0
- package/dist/esm/manabo/parser/manaboMail.d.ts +8 -0
- package/dist/esm/manabo/parser/manaboMail.d.ts.map +1 -0
- package/dist/esm/manabo/parser/manaboMail.js +145 -0
- package/dist/esm/manabo/parser/manaboNews.d.ts +7 -0
- package/dist/esm/manabo/parser/manaboNews.d.ts.map +1 -0
- package/dist/esm/manabo/parser/manaboNews.js +22 -0
- package/dist/esm/manabo/parser/manaboTimetable.d.ts +4 -0
- package/dist/esm/manabo/parser/manaboTimetable.d.ts.map +1 -0
- package/dist/esm/manabo/parser/manaboTimetable.js +89 -0
- package/dist/esm/manabo/types/manaboClass.d.ts +294 -0
- package/dist/esm/manabo/types/manaboClass.d.ts.map +1 -0
- package/dist/esm/manabo/types/manaboClass.js +220 -0
- package/dist/esm/manabo/types/manaboEntry.d.ts +24 -0
- package/dist/esm/manabo/types/manaboEntry.d.ts.map +1 -0
- package/dist/esm/manabo/types/manaboEntry.js +40 -0
- package/dist/esm/manabo/types/manaboMail.d.ts +103 -0
- package/dist/esm/manabo/types/manaboMail.d.ts.map +1 -0
- package/dist/esm/manabo/types/manaboMail.js +114 -0
- package/dist/esm/manabo/types/manaboNews.d.ts +15 -0
- package/dist/esm/manabo/types/manaboNews.d.ts.map +1 -0
- package/dist/esm/manabo/types/manaboNews.js +17 -0
- package/dist/esm/manabo/types/manaboTimetable.d.ts +88 -0
- package/dist/esm/manabo/types/manaboTimetable.d.ts.map +1 -0
- package/dist/esm/manabo/types/manaboTimetable.js +76 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/shib/builder.d.ts +154 -0
- package/dist/esm/shib/builder.d.ts.map +1 -0
- package/dist/esm/shib/builder.js +212 -0
- package/dist/esm/shib/index.d.ts +15 -0
- package/dist/esm/shib/index.d.ts.map +1 -0
- package/dist/esm/shib/index.js +14 -0
- package/dist/esm/shib/parser/shibLogin.d.ts +47 -0
- package/dist/esm/shib/parser/shibLogin.d.ts.map +1 -0
- package/dist/esm/shib/parser/shibLogin.js +127 -0
- package/dist/esm/shib/parser/shibUser.d.ts +11 -0
- package/dist/esm/shib/parser/shibUser.d.ts.map +1 -0
- package/dist/esm/shib/parser/shibUser.js +46 -0
- package/dist/esm/shib/types/common.d.ts +20 -0
- package/dist/esm/shib/types/common.d.ts.map +1 -0
- package/dist/esm/shib/types/common.js +1 -0
- package/dist/esm/shib/types/shibLogin.d.ts +62 -0
- package/dist/esm/shib/types/shibLogin.d.ts.map +1 -0
- package/dist/esm/shib/types/shibLogin.js +89 -0
- package/dist/esm/shib/types/shibUser.d.ts +36 -0
- package/dist/esm/shib/types/shibUser.d.ts.map +1 -0
- package/dist/esm/shib/types/shibUser.js +41 -0
- package/dist/esm/transports/fetch.d.ts +36 -0
- package/dist/esm/transports/fetch.d.ts.map +1 -0
- package/dist/esm/transports/fetch.js +80 -0
- package/dist/esm/types.d.ts +71 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +8 -0
- package/package.json +72 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { getAttribute, loadDocument, queryOne } from "../../common/dom";
|
|
2
|
+
import { ShibCheckTypeSchema, ShibLoginResultSchema, ShibWebauthnAuthSchema, ShibWebauthnRegistrationSchema, } from "../types/shibLogin";
|
|
3
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
4
|
+
/**
|
|
5
|
+
* 認証エラー(ID/PW・OTP 誤り等)を示すメッセージ要素のセレクタ。
|
|
6
|
+
*
|
|
7
|
+
* ページは英語・日本語どちらでも描画されうるため、表示テキストではなく
|
|
8
|
+
* 言語非依存な CSS クラス(`c-message _error`)で判定する。実キャプチャ上、
|
|
9
|
+
* この要素は「認証失敗の POST 応答」でのみ出現し、初期ログインページや
|
|
10
|
+
* SAML 成功応答には現れない(誤検出しない)ことを確認済み。
|
|
11
|
+
*/
|
|
12
|
+
const AUTH_ERROR_SELECTOR = ".c-message._error";
|
|
13
|
+
// ============================================
|
|
14
|
+
// フロー制御ヘルパ(レスポンス由来。ZodSafeParseResult ではなく素の値を返す)
|
|
15
|
+
// ============================================
|
|
16
|
+
/** URL の `AuthState` クエリを取り出す。 */
|
|
17
|
+
export const extractAuthStateFromUrl = (url) => {
|
|
18
|
+
try {
|
|
19
|
+
return new URL(url).searchParams.get("AuthState");
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/** HTML の hidden input から `AuthState` を取り出す。 */
|
|
26
|
+
export const extractAuthStateFromHtml = (html) => {
|
|
27
|
+
const input = queryOne('input[name="AuthState"]', loadDocument(html));
|
|
28
|
+
return getAttribute(input, "value");
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* loginuserpass ページの `AuthState` を解決する(URL クエリ優先、無ければ HTML hidden)。
|
|
32
|
+
* ログインの各 POST に必須の識別子。
|
|
33
|
+
*/
|
|
34
|
+
export const resolveAuthState = (finalUrl, html) => extractAuthStateFromUrl(finalUrl) ?? extractAuthStateFromHtml(html);
|
|
35
|
+
/**
|
|
36
|
+
* 3xx 応答の遷移先(Location)を返す。SDK の Transport はヘッダのキーを小文字化する。
|
|
37
|
+
* リダイレクト追従自体は呼び出し側が行う。
|
|
38
|
+
*/
|
|
39
|
+
export const extractRedirectLocation = (response) => response.headers["location"] ?? null;
|
|
40
|
+
// ============================================
|
|
41
|
+
// パーサ
|
|
42
|
+
// ============================================
|
|
43
|
+
/** `checktype.php` の JSON 応答をパースする。 */
|
|
44
|
+
export const parseShibCheckType = (input) => {
|
|
45
|
+
let data;
|
|
46
|
+
try {
|
|
47
|
+
data = JSON.parse(input);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
data = null;
|
|
51
|
+
}
|
|
52
|
+
const authType = isRecord(data) && Array.isArray(data["authType"])
|
|
53
|
+
? data["authType"].filter((v) => typeof v === "string")
|
|
54
|
+
: [];
|
|
55
|
+
const sessioninfo = isRecord(data) ? data["sessioninfo"] : undefined;
|
|
56
|
+
const authState = isRecord(sessioninfo) && typeof sessioninfo["AuthState"] === "string" ? sessioninfo["AuthState"] : null;
|
|
57
|
+
return ShibCheckTypeSchema.safeParse({ authType, authState });
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* `loginuserpass.php` のログイン結果をパースする。
|
|
61
|
+
*
|
|
62
|
+
* 表示テキスト(英語 "confirmation code" / 日本語 "確認コード" 等)に依存せず、
|
|
63
|
+
* 言語非依存な構造で判定する:
|
|
64
|
+
* 1. SAMLResponse hidden がある → 認証成立(SAML 自動 POST フォーム)
|
|
65
|
+
* 2. エラーメッセージ要素({@link AUTH_ERROR_SELECTOR})がある → 認証失敗
|
|
66
|
+
* 3. どちらも無い → 次の要素(OTP)が必要(`otpRequired`)
|
|
67
|
+
*
|
|
68
|
+
* ※ ページテンプレートは OTP セクションの markup("確認コード" / "resend" 等)を
|
|
69
|
+
* 常に内包するため、テキスト一致では password 画面と OTP 画面を判別できない。
|
|
70
|
+
* 到達段階の判別は上記の構造シグナルで行う。
|
|
71
|
+
*/
|
|
72
|
+
export const parseShibLoginResult = (html) => {
|
|
73
|
+
const document = loadDocument(html);
|
|
74
|
+
const samlInput = queryOne('input[name="SAMLResponse"]', document);
|
|
75
|
+
if (samlInput) {
|
|
76
|
+
const form = queryOne("form", document);
|
|
77
|
+
const relayInput = queryOne('input[name="RelayState"]', document);
|
|
78
|
+
return ShibLoginResultSchema.safeParse({
|
|
79
|
+
kind: "samlForm",
|
|
80
|
+
action: getAttribute(form, "action") ?? "",
|
|
81
|
+
samlResponse: getAttribute(samlInput, "value") ?? "",
|
|
82
|
+
relayState: getAttribute(relayInput, "value") ?? "",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (queryOne(AUTH_ERROR_SELECTOR, document)) {
|
|
86
|
+
return ShibLoginResultSchema.safeParse({ kind: "error" });
|
|
87
|
+
}
|
|
88
|
+
return ShibLoginResultSchema.safeParse({ kind: "otpRequired" });
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* ログインフロー用 `webauthn.php`(start/finish-authentication)の応答をパースする。
|
|
92
|
+
* `revoked`(HTTP 4xx か status≠0)はパスキー無効化を示す構造として返す(throw しない)。
|
|
93
|
+
*/
|
|
94
|
+
export const parseShibWebauthnAuthentication = (response) => {
|
|
95
|
+
const httpRevoked = response.status >= 400 && response.status < 500;
|
|
96
|
+
let data;
|
|
97
|
+
try {
|
|
98
|
+
data = JSON.parse(response.body);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
data = null;
|
|
102
|
+
}
|
|
103
|
+
const status = isRecord(data) && typeof data["status"] === "number" ? data["status"] : null;
|
|
104
|
+
const params = isRecord(data) ? data["params"] : undefined;
|
|
105
|
+
const challenge = isRecord(params) && typeof params["challenge"] === "string" ? params["challenge"] : null;
|
|
106
|
+
const revoked = httpRevoked || (status !== null && status !== 0);
|
|
107
|
+
const ok = response.status === 200 && status === 0;
|
|
108
|
+
return ShibWebauthnAuthSchema.safeParse({ ok, revoked, status, challenge });
|
|
109
|
+
};
|
|
110
|
+
/** `User/webauthn`(start-registration)の応答をパースする。 */
|
|
111
|
+
export const parseShibWebauthnRegistration = (input) => {
|
|
112
|
+
let data;
|
|
113
|
+
try {
|
|
114
|
+
data = JSON.parse(input);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
data = null;
|
|
118
|
+
}
|
|
119
|
+
const params = isRecord(data) ? data["params"] : undefined;
|
|
120
|
+
return ShibWebauthnRegistrationSchema.safeParse({
|
|
121
|
+
status: isRecord(data) ? data["status"] : undefined,
|
|
122
|
+
challenge: isRecord(params) ? params["challenge"] : undefined,
|
|
123
|
+
user: isRecord(params) ? params["user"] : undefined,
|
|
124
|
+
rp: isRecord(params) ? params["rp"] : undefined,
|
|
125
|
+
pubKeyCredParams: isRecord(params) ? params["pubKeyCredParams"] : undefined,
|
|
126
|
+
});
|
|
127
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACE User ポータル(`/User/*`)のページパーサ。
|
|
3
|
+
* CSRF トークン・procchk・登録済みデバイス一覧を抽出する。
|
|
4
|
+
*/
|
|
5
|
+
import type { ZodSafeParseResult } from "zod";
|
|
6
|
+
import { type ShibCsrfTokenDTO, type ShibFido2DeviceListDTO } from "../types/shibUser";
|
|
7
|
+
/** 任意の ACE User ページから ACEUSER_CSRFTOKEN と procchk を抽出する。 */
|
|
8
|
+
export declare const parseShibCsrfToken: (html: string) => ZodSafeParseResult<ShibCsrfTokenDTO>;
|
|
9
|
+
/** `Fido2DeviceList` の一覧ページをパースする。 */
|
|
10
|
+
export declare const parseShibFido2DeviceList: (html: string) => ZodSafeParseResult<ShibFido2DeviceListDTO>;
|
|
11
|
+
//# sourceMappingURL=shibUser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shibUser.d.ts","sourceRoot":"","sources":["../../../../src/shib/parser/shibUser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,KAAK,CAAC;AAI9C,OAAO,EAGH,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC9B,MAAM,mBAAmB,CAAC;AAW3B,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,kBAAkB,CAAC,gBAAgB,CAMpF,CAAC;AAEF,sCAAsC;AACtC,eAAO,MAAM,wBAAwB,GAAI,MAAM,MAAM,KAAG,kBAAkB,CAAC,sBAAsB,CA2BhG,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { closest, getAttribute, getTextContent, loadDocument, queryAll, queryOne } from "../../common/dom";
|
|
2
|
+
import { normalizeWhitespace } from "../../common/utils";
|
|
3
|
+
import { ShibCsrfTokenSchema, ShibFido2DeviceListSchema, } from "../types/shibUser";
|
|
4
|
+
/** hidden input(name 指定)の value を返す。要素が無ければ null、value 属性のみ無ければ ""。 */
|
|
5
|
+
const getInputValue = (root, name) => {
|
|
6
|
+
const input = queryOne(`input[name="${name}"]`, root);
|
|
7
|
+
if (!input) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return getAttribute(input, "value") ?? "";
|
|
11
|
+
};
|
|
12
|
+
/** 任意の ACE User ページから ACEUSER_CSRFTOKEN と procchk を抽出する。 */
|
|
13
|
+
export const parseShibCsrfToken = (html) => {
|
|
14
|
+
const document = loadDocument(html);
|
|
15
|
+
return ShibCsrfTokenSchema.safeParse({
|
|
16
|
+
csrfToken: getInputValue(document, "ACEUSER_CSRFTOKEN") ?? "",
|
|
17
|
+
procchk: getInputValue(document, "procchk"),
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
/** `Fido2DeviceList` の一覧ページをパースする。 */
|
|
21
|
+
export const parseShibFido2DeviceList = (html) => {
|
|
22
|
+
const document = loadDocument(html);
|
|
23
|
+
const devices = queryAll("td.c-table_check", document).map((checkCell) => {
|
|
24
|
+
const credentialId = getAttribute(checkCell, "id") ?? "";
|
|
25
|
+
const row = closest(checkCell, "tr");
|
|
26
|
+
const cells = row ? queryAll("td", row) : [];
|
|
27
|
+
// cells[0] はチェックボックス列。以降が 名前 / 署名カウンタ / 登録日時 / 最終利用日時。
|
|
28
|
+
const text = (index) => normalizeWhitespace(getTextContent(cells[index] ?? null));
|
|
29
|
+
const signCountText = text(2);
|
|
30
|
+
const signCount = signCountText !== "" && /^\d+$/.test(signCountText) ? Number(signCountText) : null;
|
|
31
|
+
const registeredAt = text(3);
|
|
32
|
+
const lastUsedAt = text(4);
|
|
33
|
+
return {
|
|
34
|
+
credentialId,
|
|
35
|
+
name: text(1),
|
|
36
|
+
signCount,
|
|
37
|
+
registeredAt: registeredAt !== "" ? registeredAt : null,
|
|
38
|
+
lastUsedAt: lastUsedAt !== "" ? lastUsedAt : null,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
return ShibFido2DeviceListSchema.safeParse({
|
|
42
|
+
csrfToken: getInputValue(document, "ACEUSER_CSRFTOKEN"),
|
|
43
|
+
procchk: getInputValue(document, "procchk"),
|
|
44
|
+
devices,
|
|
45
|
+
});
|
|
46
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* shib(Shibboleth 認証フロー)モジュール共通の型。
|
|
3
|
+
*
|
|
4
|
+
* この SDK は認証を「実行」しない。ビルダは各ステップの
|
|
5
|
+
* リクエスト記述子({@link ShibRequest})を返すだけで、実際の HTTP 送信・
|
|
6
|
+
* Cookie 管理・リダイレクト追従は呼び出し側が行う。
|
|
7
|
+
*/
|
|
8
|
+
import type { TransportRequest, TransportResponse } from "../../types";
|
|
9
|
+
/**
|
|
10
|
+
* ビルダが返すリクエスト記述子。{@link TransportRequest} と同形で、
|
|
11
|
+
* そのまま `Transport#request` や任意の HTTP クライアントに渡せる。
|
|
12
|
+
* `Content-Type` / `Origin` は `headers` に含めて返す。
|
|
13
|
+
*/
|
|
14
|
+
export type ShibRequest = Pick<TransportRequest, "method" | "url" | "headers" | "body">;
|
|
15
|
+
/**
|
|
16
|
+
* パーサが受け取るレスポンス(`status` / `body` を参照するもの向け)。
|
|
17
|
+
* ボディ文字列だけを見るパーサは `(input: string)` を取る(fixture テスト harness と互換)。
|
|
18
|
+
*/
|
|
19
|
+
export type ShibResponse = Pick<TransportResponse, "status" | "url" | "body" | "headers">;
|
|
20
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../../src/shib/types/common.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEvE;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC;AAExF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ログインフロー(CloudLink IdP)の各レスポンスを構造化する DTO。
|
|
3
|
+
*
|
|
4
|
+
* checktype.php → loginuserpass.php(PW / OTP / Passkey)→ webauthn.php の
|
|
5
|
+
* レスポンスを、後続処理に必要な最小情報へ落とし込む。値はサーバが返すものを通し、
|
|
6
|
+
* 判断(再認証・ログアウト等)は呼び出し側に委ねる。
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
/** `checktype.php` の応答(利用可能な認証方式) */
|
|
10
|
+
export declare const ShibCheckTypeSchema: z.ZodObject<{
|
|
11
|
+
authType: z.ZodArray<z.ZodString>;
|
|
12
|
+
authState: z.ZodNullable<z.ZodString>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
export type ShibCheckTypeDTO = z.infer<typeof ShibCheckTypeSchema>;
|
|
15
|
+
/**
|
|
16
|
+
* `loginuserpass.php` のログイン結果。
|
|
17
|
+
* - `samlForm`: 認証成功。SP ACS への自動 POST フォームを抽出できた(次は SAML ACS へ POST)。
|
|
18
|
+
* - `otpRequired`: OTP 入力ページが表示された(authtype=2 で再送する)。
|
|
19
|
+
* - `error`: ID/PW(または OTP)誤り等の認証エラー。
|
|
20
|
+
*/
|
|
21
|
+
export declare const ShibLoginResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
22
|
+
kind: z.ZodLiteral<"samlForm">;
|
|
23
|
+
action: z.ZodString;
|
|
24
|
+
samlResponse: z.ZodString;
|
|
25
|
+
relayState: z.ZodString;
|
|
26
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
27
|
+
kind: z.ZodLiteral<"otpRequired">;
|
|
28
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
29
|
+
kind: z.ZodLiteral<"error">;
|
|
30
|
+
}, z.core.$strip>], "kind">;
|
|
31
|
+
export type ShibLoginResultDTO = z.infer<typeof ShibLoginResultSchema>;
|
|
32
|
+
/**
|
|
33
|
+
* ログインフロー用 `webauthn.php`(start/finish-authentication)の応答。
|
|
34
|
+
* `revoked`(HTTP 4xx か status≠0)はパスキー無効化を示す構造として返す。SDK は自動処理しない。
|
|
35
|
+
*/
|
|
36
|
+
export declare const ShibWebauthnAuthSchema: z.ZodObject<{
|
|
37
|
+
ok: z.ZodBoolean;
|
|
38
|
+
revoked: z.ZodBoolean;
|
|
39
|
+
status: z.ZodNullable<z.ZodNumber>;
|
|
40
|
+
challenge: z.ZodNullable<z.ZodString>;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
export type ShibWebauthnAuthDTO = z.infer<typeof ShibWebauthnAuthSchema>;
|
|
43
|
+
/** `User/webauthn`(start-registration)の応答。登録に必要な challenge / user を抽出する。 */
|
|
44
|
+
export declare const ShibWebauthnRegistrationSchema: z.ZodObject<{
|
|
45
|
+
status: z.ZodNumber;
|
|
46
|
+
challenge: z.ZodString;
|
|
47
|
+
user: z.ZodObject<{
|
|
48
|
+
id: z.ZodString;
|
|
49
|
+
name: z.ZodString;
|
|
50
|
+
displayName: z.ZodString;
|
|
51
|
+
}, z.core.$strip>;
|
|
52
|
+
rp: z.ZodObject<{
|
|
53
|
+
id: z.ZodString;
|
|
54
|
+
name: z.ZodString;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
pubKeyCredParams: z.ZodArray<z.ZodObject<{
|
|
57
|
+
type: z.ZodString;
|
|
58
|
+
alg: z.ZodNumber;
|
|
59
|
+
}, z.core.$strip>>;
|
|
60
|
+
}, z.core.$strip>;
|
|
61
|
+
export type ShibWebauthnRegistrationDTO = z.infer<typeof ShibWebauthnRegistrationSchema>;
|
|
62
|
+
//# sourceMappingURL=shibLogin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shibLogin.d.ts","sourceRoot":"","sources":["../../../../src/shib/types/shibLogin.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,qCAAqC;AACrC,eAAO,MAAM,mBAAmB;;;iBAQ9B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;2BAoBhC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEvE;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;iBAYjC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEzE,4EAA4E;AAC5E,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;iBAyBzC,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ログインフロー(CloudLink IdP)の各レスポンスを構造化する DTO。
|
|
3
|
+
*
|
|
4
|
+
* checktype.php → loginuserpass.php(PW / OTP / Passkey)→ webauthn.php の
|
|
5
|
+
* レスポンスを、後続処理に必要な最小情報へ落とし込む。値はサーバが返すものを通し、
|
|
6
|
+
* 判断(再認証・ログアウト等)は呼び出し側に委ねる。
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
/** `checktype.php` の応答(利用可能な認証方式) */
|
|
10
|
+
export const ShibCheckTypeSchema = z.object({
|
|
11
|
+
/** 利用可能な認証方式("Password" / "OTP" / "Passkey" 等) @example ["Password","OTP"] */
|
|
12
|
+
authType: z.array(z.string()).meta({ description: "利用可能な認証方式", example: ["Password", "OTP"] }),
|
|
13
|
+
/** 応答に含まれる sessioninfo.AuthState(無ければ null) @example "_dummyauthstate:https://shib.chukyo-u.ac.jp/..." */
|
|
14
|
+
authState: z
|
|
15
|
+
.string()
|
|
16
|
+
.nullable()
|
|
17
|
+
.meta({ description: "sessioninfo.AuthState", example: "_dummyauthstate:https://shib.chukyo-u.ac.jp/..." }),
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* `loginuserpass.php` のログイン結果。
|
|
21
|
+
* - `samlForm`: 認証成功。SP ACS への自動 POST フォームを抽出できた(次は SAML ACS へ POST)。
|
|
22
|
+
* - `otpRequired`: OTP 入力ページが表示された(authtype=2 で再送する)。
|
|
23
|
+
* - `error`: ID/PW(または OTP)誤り等の認証エラー。
|
|
24
|
+
*/
|
|
25
|
+
export const ShibLoginResultSchema = z.discriminatedUnion("kind", [
|
|
26
|
+
z.object({
|
|
27
|
+
kind: z.literal("samlForm"),
|
|
28
|
+
/** SAML 自動 POST の action URL @example "https://shib.chukyo-u.ac.jp/clsp/saml/acs?client_name=idp1" */
|
|
29
|
+
action: z
|
|
30
|
+
.string()
|
|
31
|
+
.meta({ description: "SAML 自動 POST の action", example: "https://shib.chukyo-u.ac.jp/clsp/saml/acs?client_name=idp1" }),
|
|
32
|
+
/** Base64 の SAMLResponse @example "PHNhbWxwOlJlc3BvbnNlPi4uLg==" */
|
|
33
|
+
samlResponse: z.string().meta({ description: "Base64 の SAMLResponse", example: "PHNhbWxwOlJlc3BvbnNlPi4uLg==" }),
|
|
34
|
+
/** RelayState @example "https://shib.chukyo-u.ac.jp/clsp/saml/acs?client_name=idp1" */
|
|
35
|
+
relayState: z
|
|
36
|
+
.string()
|
|
37
|
+
.meta({ description: "RelayState", example: "https://shib.chukyo-u.ac.jp/clsp/saml/acs?client_name=idp1" }),
|
|
38
|
+
}),
|
|
39
|
+
z.object({
|
|
40
|
+
kind: z.literal("otpRequired"),
|
|
41
|
+
}),
|
|
42
|
+
z.object({
|
|
43
|
+
kind: z.literal("error"),
|
|
44
|
+
}),
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* ログインフロー用 `webauthn.php`(start/finish-authentication)の応答。
|
|
48
|
+
* `revoked`(HTTP 4xx か status≠0)はパスキー無効化を示す構造として返す。SDK は自動処理しない。
|
|
49
|
+
*/
|
|
50
|
+
export const ShibWebauthnAuthSchema = z.object({
|
|
51
|
+
/** 正常応答か(HTTP 200 かつ status===0) @example true */
|
|
52
|
+
ok: z.boolean().meta({ description: "正常応答か", example: true }),
|
|
53
|
+
/** パスキー無効化を示すか(HTTP 4xx か status≠0) @example false */
|
|
54
|
+
revoked: z.boolean().meta({ description: "パスキー無効化を示すか", example: false }),
|
|
55
|
+
/** 応答の status フィールド(4xx でボディ無しの場合 null) @example 0 */
|
|
56
|
+
status: z.number().nullable().meta({ description: "status フィールド", example: 0 }),
|
|
57
|
+
/** 署名用チャレンジ(base64url、取得できなければ null) @example "X95CVnQJfLd9DwcjBkaDZelkEH0Dthn7e2-iV_5aah0" */
|
|
58
|
+
challenge: z
|
|
59
|
+
.string()
|
|
60
|
+
.nullable()
|
|
61
|
+
.meta({ description: "署名用チャレンジ", example: "X95CVnQJfLd9DwcjBkaDZelkEH0Dthn7e2-iV_5aah0" }),
|
|
62
|
+
});
|
|
63
|
+
/** `User/webauthn`(start-registration)の応答。登録に必要な challenge / user を抽出する。 */
|
|
64
|
+
export const ShibWebauthnRegistrationSchema = z.object({
|
|
65
|
+
/** status フィールド(0 で正常) @example 0 */
|
|
66
|
+
status: z.number().meta({ description: "status フィールド", example: 0 }),
|
|
67
|
+
/** 生成用チャレンジ(base64url) @example "1SZVUGityQOpj8TzCWc0KmAKpOGM7QfcJ8llEsIDH4k" */
|
|
68
|
+
challenge: z.string().meta({ description: "生成用チャレンジ", example: "1SZVUGityQOpj8TzCWc0KmAKpOGM7QfcJ8llEsIDH4k" }),
|
|
69
|
+
/** サーバが割り当てるユーザ情報 */
|
|
70
|
+
user: z.object({
|
|
71
|
+
/** User Handle(base64url) @example "bZ7pOaxNOfQn51w1p4PEDxouFn5R_CA1TLmgGKjutdo" */
|
|
72
|
+
id: z.string().meta({ description: "User Handle", example: "bZ7pOaxNOfQn51w1p4PEDxouFn5R_CA1TLmgGKjutdo" }),
|
|
73
|
+
/** ユーザ名(学籍番号) @example "T000000" */
|
|
74
|
+
name: z.string().meta({ description: "ユーザ名(学籍番号)", example: "T000000" }),
|
|
75
|
+
/** 表示名 @example "umebo for ios (a3f9k2x1)" */
|
|
76
|
+
displayName: z.string().meta({ description: "表示名", example: "umebo for ios (a3f9k2x1)" }),
|
|
77
|
+
}),
|
|
78
|
+
/** RP 情報 */
|
|
79
|
+
rp: z.object({
|
|
80
|
+
/** RP ID @example "shib.chukyo-u.ac.jp" */
|
|
81
|
+
id: z.string().meta({ description: "RP ID", example: "shib.chukyo-u.ac.jp" }),
|
|
82
|
+
/** RP 名 @example "Chukyo University FIDO" */
|
|
83
|
+
name: z.string().meta({ description: "RP 名", example: "Chukyo University FIDO" }),
|
|
84
|
+
}),
|
|
85
|
+
/** 許可される公開鍵アルゴリズム @example [{"type":"public-key","alg":-7}] */
|
|
86
|
+
pubKeyCredParams: z
|
|
87
|
+
.array(z.object({ type: z.string(), alg: z.number() }))
|
|
88
|
+
.meta({ description: "許可される公開鍵アルゴリズム", example: [{ type: "public-key", alg: -7 }] }),
|
|
89
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACE User ポータル(`/User/*`)の各ページを構造化する DTO。
|
|
3
|
+
*
|
|
4
|
+
* これらのページは全 POST に CSRF トークン(ACEUSER_CSRFTOKEN)を伴い、
|
|
5
|
+
* hidden input に次リクエスト用の値(procchk 等)が埋め込まれている。
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
/** 任意の ACE User ページから抽出する CSRF トークンと procchk。 */
|
|
9
|
+
export declare const ShibCsrfTokenSchema: z.ZodObject<{
|
|
10
|
+
csrfToken: z.ZodString;
|
|
11
|
+
procchk: z.ZodNullable<z.ZodString>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
export type ShibCsrfTokenDTO = z.infer<typeof ShibCsrfTokenSchema>;
|
|
14
|
+
/** 登録済み FIDO2 デバイス 1 件。 */
|
|
15
|
+
export declare const ShibFido2DeviceSchema: z.ZodObject<{
|
|
16
|
+
credentialId: z.ZodString;
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
signCount: z.ZodNullable<z.ZodNumber>;
|
|
19
|
+
registeredAt: z.ZodNullable<z.ZodString>;
|
|
20
|
+
lastUsedAt: z.ZodNullable<z.ZodString>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
export type ShibFido2DeviceDTO = z.infer<typeof ShibFido2DeviceSchema>;
|
|
23
|
+
/** `Fido2DeviceList` の一覧ページ。 */
|
|
24
|
+
export declare const ShibFido2DeviceListSchema: z.ZodObject<{
|
|
25
|
+
csrfToken: z.ZodNullable<z.ZodString>;
|
|
26
|
+
procchk: z.ZodNullable<z.ZodString>;
|
|
27
|
+
devices: z.ZodArray<z.ZodObject<{
|
|
28
|
+
credentialId: z.ZodString;
|
|
29
|
+
name: z.ZodString;
|
|
30
|
+
signCount: z.ZodNullable<z.ZodNumber>;
|
|
31
|
+
registeredAt: z.ZodNullable<z.ZodString>;
|
|
32
|
+
lastUsedAt: z.ZodNullable<z.ZodString>;
|
|
33
|
+
}, z.core.$strip>>;
|
|
34
|
+
}, z.core.$strip>;
|
|
35
|
+
export type ShibFido2DeviceListDTO = z.infer<typeof ShibFido2DeviceListSchema>;
|
|
36
|
+
//# sourceMappingURL=shibUser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shibUser.d.ts","sourceRoot":"","sources":["../../../../src/shib/types/shibUser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,iDAAiD;AACjD,eAAO,MAAM,mBAAmB;;;iBAO9B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEnE,2BAA2B;AAC3B,eAAO,MAAM,qBAAqB;;;;;;iBAWhC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEvE,gCAAgC;AAChC,eAAO,MAAM,yBAAyB;;;;;;;;;;iBAUpC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACE User ポータル(`/User/*`)の各ページを構造化する DTO。
|
|
3
|
+
*
|
|
4
|
+
* これらのページは全 POST に CSRF トークン(ACEUSER_CSRFTOKEN)を伴い、
|
|
5
|
+
* hidden input に次リクエスト用の値(procchk 等)が埋め込まれている。
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
/** 任意の ACE User ページから抽出する CSRF トークンと procchk。 */
|
|
9
|
+
export const ShibCsrfTokenSchema = z.object({
|
|
10
|
+
/** ACEUSER_CSRFTOKEN の値(次 POST に必須) @example "AAAA-BBBB-CCCC-DDDD-EEEE-FFFF-GGGG-HHHH" */
|
|
11
|
+
csrfToken: z
|
|
12
|
+
.string()
|
|
13
|
+
.meta({ description: "ACEUSER_CSRFTOKEN の値", example: "AAAA-BBBB-CCCC-DDDD-EEEE-FFFF-GGGG-HHHH" }),
|
|
14
|
+
/** procchk hidden input の値(存在しなければ null、空文字はそのまま) @example "" */
|
|
15
|
+
procchk: z.string().nullable().meta({ description: "procchk hidden の値", example: "" }),
|
|
16
|
+
});
|
|
17
|
+
/** 登録済み FIDO2 デバイス 1 件。 */
|
|
18
|
+
export const ShibFido2DeviceSchema = z.object({
|
|
19
|
+
/** Credential ID(削除時の selectedNmId / checkedKeys に使う) @example "Xyjw5D-UU8oFEtpXXz-jY-UET1U" */
|
|
20
|
+
credentialId: z.string().meta({ description: "Credential ID", example: "Xyjw5D-UU8oFEtpXXz-jY-UET1U" }),
|
|
21
|
+
/** デバイス表示名 @example "umebo for ios (a3f9k2x1)" */
|
|
22
|
+
name: z.string().meta({ description: "デバイス表示名", example: "umebo for ios (a3f9k2x1)" }),
|
|
23
|
+
/** 署名カウンタ(取得できなければ null) @example 0 */
|
|
24
|
+
signCount: z.number().nullable().meta({ description: "署名カウンタ", example: 0 }),
|
|
25
|
+
/** 登録日時(表示文字列のまま) @example "2026/07/09 02:03:32 (JST)" */
|
|
26
|
+
registeredAt: z.string().nullable().meta({ description: "登録日時", example: "2026/07/09 02:03:32 (JST)" }),
|
|
27
|
+
/** 最終利用日時(表示文字列のまま) @example "2026/07/09 02:03:32 (JST)" */
|
|
28
|
+
lastUsedAt: z.string().nullable().meta({ description: "最終利用日時", example: "2026/07/09 02:03:32 (JST)" }),
|
|
29
|
+
});
|
|
30
|
+
/** `Fido2DeviceList` の一覧ページ。 */
|
|
31
|
+
export const ShibFido2DeviceListSchema = z.object({
|
|
32
|
+
/** ページの ACEUSER_CSRFTOKEN(無ければ null) @example "AAAA-BBBB-CCCC-DDDD-EEEE-FFFF-GGGG-HHHH" */
|
|
33
|
+
csrfToken: z
|
|
34
|
+
.string()
|
|
35
|
+
.nullable()
|
|
36
|
+
.meta({ description: "ACEUSER_CSRFTOKEN", example: "AAAA-BBBB-CCCC-DDDD-EEEE-FFFF-GGGG-HHHH" }),
|
|
37
|
+
/** procchk hidden の値(削除完了 POST で使う。無ければ null) @example "bsTtqjrVjJgHU2yVadt0hc5qTkTq7RsX" */
|
|
38
|
+
procchk: z.string().nullable().meta({ description: "procchk hidden の値", example: "bsTtqjrVjJgHU2yVadt0hc5qTkTq7RsX" }),
|
|
39
|
+
/** 登録済みデバイス一覧 */
|
|
40
|
+
devices: z.array(ShibFido2DeviceSchema).meta({ description: "登録済みデバイス一覧" }),
|
|
41
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Transport, TransportResponse } from "../types";
|
|
2
|
+
type FetchLike = (input: string, init?: FetchInit) => Promise<FetchResponse>;
|
|
3
|
+
interface FetchInit {
|
|
4
|
+
method?: string;
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
body?: string;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
credentials?: "omit" | "same-origin" | "include";
|
|
9
|
+
redirect?: "follow" | "manual" | "error";
|
|
10
|
+
}
|
|
11
|
+
interface FetchResponse {
|
|
12
|
+
status: number;
|
|
13
|
+
url: string;
|
|
14
|
+
ok: boolean;
|
|
15
|
+
headers: {
|
|
16
|
+
forEach(cb: (value: string, key: string) => void): void;
|
|
17
|
+
};
|
|
18
|
+
text(): Promise<string>;
|
|
19
|
+
}
|
|
20
|
+
export interface FetchTransportOptions {
|
|
21
|
+
/** タイムアウト(ms)。既定 10 秒 */
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
/** 付与する User-Agent(ブラウザでは無視される) */
|
|
24
|
+
userAgent?: string;
|
|
25
|
+
/** Cookie 送信ポリシー。既定 "omit"。拡張でブラウザの Cookie を使うなら "include" */
|
|
26
|
+
credentials?: "omit" | "same-origin" | "include";
|
|
27
|
+
/**
|
|
28
|
+
* 異常ステータスをエラーへ変換するフック。Error を返すと throw、
|
|
29
|
+
* null/undefined を返すとレスポンスをそのまま通す(既定は 503 のみ
|
|
30
|
+
* {@link ChukyoMaintenanceError} に変換し、他の 4xx/5xx はそのまま通す)。
|
|
31
|
+
*/
|
|
32
|
+
mapErrorStatus?: (status: number, res: TransportResponse) => Error | null | undefined;
|
|
33
|
+
}
|
|
34
|
+
export declare const fetchTransport: (fetchImpl?: FetchLike, options?: FetchTransportOptions) => Transport;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/transports/fetch.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAoB,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE/E,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;AAE7E,UAAU,SAAS;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CAC5C;AAED,UAAU,aAAa;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE;QAAE,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAA;KAAE,CAAC;IACrE,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IAClC,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IACjD;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,KAAK,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;CACzF;AAKD,eAAO,MAAM,cAAc,GACvB,YAAW,SAAoD,EAC/D,UAAS,qBAA0B,KACpC,SA0EF,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHATWG `fetch` を {@link Transport} に適合させる Adapter。
|
|
3
|
+
*
|
|
4
|
+
* - Node: 引数省略で `globalThis.fetch`(Node 18+)
|
|
5
|
+
* - Expo: `fetch` に `expo/fetch` の `fetch` を渡す
|
|
6
|
+
* - ブラウザ拡張: `fetchTransport(fetch, { credentials: "include" })` で
|
|
7
|
+
* ブラウザの Cookie ジャーを自動送信(SessionProvider 不要)
|
|
8
|
+
*/
|
|
9
|
+
import { ChukyoMaintenanceError, NetworkError, TimeoutError } from "../errors";
|
|
10
|
+
const isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
11
|
+
export const fetchTransport = (fetchImpl = globalThis.fetch, options = {}) => {
|
|
12
|
+
const timeoutMs = options.timeoutMs ?? 10_000;
|
|
13
|
+
return {
|
|
14
|
+
async request(req) {
|
|
15
|
+
const controller = new AbortController();
|
|
16
|
+
let timedOut = false;
|
|
17
|
+
const timeoutId = setTimeout(() => {
|
|
18
|
+
timedOut = true;
|
|
19
|
+
controller.abort();
|
|
20
|
+
}, timeoutMs);
|
|
21
|
+
const onExternalAbort = () => controller.abort();
|
|
22
|
+
if (req.signal) {
|
|
23
|
+
if (req.signal.aborted) {
|
|
24
|
+
controller.abort();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
req.signal.addEventListener("abort", onExternalAbort);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const headers = { ...req.headers };
|
|
31
|
+
if (options.userAgent) {
|
|
32
|
+
headers["User-Agent"] = options.userAgent;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const res = await fetchImpl(req.url, {
|
|
36
|
+
method: req.method,
|
|
37
|
+
headers,
|
|
38
|
+
...(req.body != null ? { body: req.body } : {}),
|
|
39
|
+
signal: controller.signal,
|
|
40
|
+
credentials: options.credentials ?? "omit",
|
|
41
|
+
});
|
|
42
|
+
const responseHeaders = {};
|
|
43
|
+
res.headers.forEach((value, key) => {
|
|
44
|
+
responseHeaders[key.toLowerCase()] = value;
|
|
45
|
+
});
|
|
46
|
+
const result = {
|
|
47
|
+
status: res.status,
|
|
48
|
+
url: res.url || req.url,
|
|
49
|
+
body: await res.text(),
|
|
50
|
+
headers: responseHeaders,
|
|
51
|
+
};
|
|
52
|
+
const mapped = options.mapErrorStatus
|
|
53
|
+
? options.mapErrorStatus(res.status, result)
|
|
54
|
+
: res.status === 503
|
|
55
|
+
? new ChukyoMaintenanceError()
|
|
56
|
+
: null;
|
|
57
|
+
if (mapped) {
|
|
58
|
+
throw mapped;
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof ChukyoMaintenanceError) {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
if (isAbortError(error) && timedOut) {
|
|
67
|
+
throw new TimeoutError({ cause: error });
|
|
68
|
+
}
|
|
69
|
+
// fetch 自体が throw(DNS 失敗・接続拒否・TLS・URL 不正など。HTTP 応答なし)
|
|
70
|
+
throw new NetworkError({ cause: error });
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
clearTimeout(timeoutId);
|
|
74
|
+
if (req.signal) {
|
|
75
|
+
req.signal.removeEventListener("abort", onExternalAbort);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK コアが依存する Adapter インターフェース群。
|
|
3
|
+
*
|
|
4
|
+
* SDK は「HTTP をどう実行するか({@link Transport})」と「Cookie をどう供給するか
|
|
5
|
+
* ({@link SessionProvider})」を知らない。これらを注入することで、Node / ブラウザ /
|
|
6
|
+
* ブラウザ拡張 / Expo / カスタムなど任意の環境で同じコードが動く。
|
|
7
|
+
*/
|
|
8
|
+
/** HTTP リクエスト1回分の入力 */
|
|
9
|
+
export interface TransportRequest {
|
|
10
|
+
/** HTTP メソッド */
|
|
11
|
+
method: "GET" | "POST";
|
|
12
|
+
/** 完全な URL */
|
|
13
|
+
url: string;
|
|
14
|
+
/** 追加ヘッダ */
|
|
15
|
+
headers?: Record<string, string>;
|
|
16
|
+
/** リクエストボディ(form-urlencoded / JSON 文字列など) */
|
|
17
|
+
body?: string;
|
|
18
|
+
/** 中断用シグナル */
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
}
|
|
21
|
+
/** HTTP リクエスト1回分の結果 */
|
|
22
|
+
export interface TransportResponse {
|
|
23
|
+
/** HTTP ステータスコード */
|
|
24
|
+
status: number;
|
|
25
|
+
/** リダイレクト後の最終 URL(CUBICS のセッション判定に使う) */
|
|
26
|
+
url: string;
|
|
27
|
+
/** レスポンスボディ(テキストとして読み出し済み) */
|
|
28
|
+
body: string;
|
|
29
|
+
/** レスポンスヘッダ(キーは小文字化しておくこと) */
|
|
30
|
+
headers: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 1回の HTTP リクエストを実行する Adapter。
|
|
34
|
+
* リダイレクトの自動追従は実装依存でよい(データ取得はそれで足りる)。
|
|
35
|
+
*/
|
|
36
|
+
export interface Transport {
|
|
37
|
+
request(req: TransportRequest): Promise<TransportResponse>;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* ポータルサービスの記述子。「enterUrl へアクセス → SSO → goalUrl 到達で
|
|
41
|
+
* Cookie 取得」という共通パターンのための情報。
|
|
42
|
+
*/
|
|
43
|
+
export interface PortalService {
|
|
44
|
+
/** セッションキャッシュのキー(例: "manabo" / "cubics" / "albo") */
|
|
45
|
+
readonly key: string;
|
|
46
|
+
/** ログイン起点 URL */
|
|
47
|
+
readonly enterUrl: string;
|
|
48
|
+
/** 認証完了とみなす到達先 URL */
|
|
49
|
+
readonly goalUrl: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Cookie / セッションを供給する Adapter(任意)。
|
|
53
|
+
*
|
|
54
|
+
* 未指定の場合、SDK は Cookie ヘッダを付与せず {@link Transport} の credentials 設定に
|
|
55
|
+
* 委ねる(ブラウザ拡張でブラウザの Cookie ジャーを使うユースケース)。
|
|
56
|
+
* 指定する場合、失効時の再認証は実装側の責務(例: umebo の PortalSessionManager)。
|
|
57
|
+
*/
|
|
58
|
+
export interface SessionProvider {
|
|
59
|
+
/** HTTP ヘッダ用の Cookie 文字列を返す。失効していれば内部で再認証する */
|
|
60
|
+
getCookieHeader(service: PortalService): Promise<string>;
|
|
61
|
+
/** セッション無効を検知した際に呼ぶ(次回アクセスで再認証させる) */
|
|
62
|
+
invalidate(serviceKey: string): void;
|
|
63
|
+
}
|
|
64
|
+
/** createChukyoClient のオプション */
|
|
65
|
+
export interface ChukyoClientOptions {
|
|
66
|
+
/** HTTP 実行 Adapter(必須) */
|
|
67
|
+
transport: Transport;
|
|
68
|
+
/** Cookie 供給 Adapter(任意。省略時は Cookie を付与しない) */
|
|
69
|
+
session?: SessionProvider;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=types.d.ts.map
|