@yielded/auth 0.1.0-beta.3 → 0.1.0-beta.5
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/DrizzleD1.d.mts +51 -2
- package/dist/DrizzleLibsql.d.mts +53 -4
- package/dist/DrizzleMysql2.d.mts +53 -4
- package/dist/DrizzlePglite.d.mts +53 -4
- package/dist/DrizzlePostgres.d.mts +55 -6
- package/dist/DrizzleSqliteBun.d.mts +51 -2
- package/dist/DrizzleSqliteDo.d.mts +53 -4
- package/dist/DrizzleSqliteNode.d.mts +53 -4
- package/dist/DrizzleSqliteWasm.d.mts +55 -6
- package/dist/GitHub.d.mts +2 -1
- package/dist/GitHub.mjs +2 -1
- package/dist/OpenIdClient.d.mts +2 -1
- package/dist/OpenIdClient.mjs +2 -1
- package/dist/drizzle/oauth-connected-state.d.mts +1 -1
- package/dist/drizzle/oauth-registration.d.mts +1 -1
- package/dist/drizzle/oauth-registration.mjs +3 -2
- package/dist/drizzle/oauth-registration.mjs.map +1 -1
- package/dist/oauth/OAuthConnectedRevocations.d.mts +10 -0
- package/dist/oauth/OAuthRegistrationIntents.d.mts +9 -0
- package/dist/oauth/accountsModels.d.mts +5 -0
- package/dist/oauth/connected.d.mts +22 -0
- package/dist/oauth/connectedModels.d.mts +115 -0
- package/dist/oauth/definition.d.mts +111 -3
- package/dist/oauth/github/identity.mjs +11 -9
- package/dist/oauth/github/identity.mjs.map +1 -1
- package/dist/oauth/github/profile.d.mts +61 -0
- package/dist/oauth/github/profile.mjs +72 -0
- package/dist/oauth/github/profile.mjs.map +1 -0
- package/dist/oauth/github/protocol.mjs +2 -2
- package/dist/oauth/github/protocol.mjs.map +1 -1
- package/dist/oauth/openid-client/connected/protocol.mjs +3 -0
- package/dist/oauth/openid-client/connected/protocol.mjs.map +1 -1
- package/dist/oauth/openid-client/profile.d.mts +39 -0
- package/dist/oauth/openid-client/profile.mjs +58 -0
- package/dist/oauth/openid-client/profile.mjs.map +1 -0
- package/dist/oauth/openid-client/protocol.mjs +3 -0
- package/dist/oauth/openid-client/protocol.mjs.map +1 -1
- package/dist/oauth/registrationModels.d.mts +22 -0
- package/dist/oauth/registrationModels.mjs +4 -1
- package/dist/oauth/registrationModels.mjs.map +1 -1
- package/dist/oauth/registrationSecrets.mjs +1 -0
- package/dist/oauth/registrationSecrets.mjs.map +1 -1
- package/dist/oauth/signInModels.d.mts +18 -0
- package/dist/oauth/signInModels.mjs +11 -1
- package/dist/oauth/signInModels.mjs.map +1 -1
- package/dist/oauth/signInModule.d.mts +43 -4
- package/dist/oauth/signInModule.mjs +1 -1
- package/dist/oauth/signInModule.mjs.map +1 -1
- package/dist/oauth/signInSnapshot.mjs +1 -1
- package/dist/oauth/signInSnapshot.mjs.map +1 -1
- package/package.json +1 -1
- package/src/GitHub.ts +1 -0
- package/src/OpenIdClient.ts +2 -0
- package/src/drizzle/oauth-registration.ts +4 -0
- package/src/oauth/github/identity.ts +11 -7
- package/src/oauth/github/profile.ts +64 -0
- package/src/oauth/github/protocol.ts +3 -2
- package/src/oauth/openid-client/connected/protocol.ts +4 -0
- package/src/oauth/openid-client/profile.ts +68 -0
- package/src/oauth/openid-client/protocol.ts +4 -0
- package/src/oauth/registrationModels.ts +4 -0
- package/src/oauth/registrationSecrets.ts +1 -0
- package/src/oauth/signInModels.ts +18 -0
- package/src/oauth/signInModule.ts +4 -0
- package/src/oauth/signInSnapshot.ts +2 -1
|
@@ -22,7 +22,7 @@ import { ModuleService } from "../sessions/module.mjs";
|
|
|
22
22
|
import "../Identity.mjs";
|
|
23
23
|
import { OAuthRegistrationAccess, OAuthRegistrationInspection, OAuthRegistrationIntent, OAuthRegistrationPolicy } from "./registrationModels.mjs";
|
|
24
24
|
import { OAuthConfigurationError, OAuthMethodUnsupported, OAuthRejected, OAuthUnavailable } from "./signInErrors.mjs";
|
|
25
|
-
import { OAuthCleanupInput, OAuthCredentialSnapshot, OAuthSignInPolicy } from "./signInModels.mjs";
|
|
25
|
+
import { OAuthCleanupInput, OAuthCredentialSnapshot, OAuthSignInPolicy, OAuthVerifiedExternalIdentity } from "./signInModels.mjs";
|
|
26
26
|
import { OAuthSignInPersistence, PrepareOAuthCommit } from "./OAuthSignInPersistence.mjs";
|
|
27
27
|
import { OAuthAccountsPolicy, OAuthActionRequired } from "./accountsModels.mjs";
|
|
28
28
|
import { OAuthConnectedActionRequired, OAuthConnectedBusy, OAuthConnectedPolicy, OAuthConnectedReauthorizationRequired } from "./connectedModels.mjs";
|
|
@@ -77,7 +77,7 @@ declare const bindDefine: <const Namespace extends string | undefined, Claims ex
|
|
|
77
77
|
layer: Layer.Layer<BindingModule<Id, "oauth-entry">, RequestBindingConfigurationError, import("effect/Crypto").Crypto | RequestBindingConfig | SubtleCrypto>;
|
|
78
78
|
}>;
|
|
79
79
|
ClaimsForOAuth: import("effect/Context").Service<OAuthModule<Id, "claims", Claims["Type"]>, {
|
|
80
|
-
readonly resolve: (credential: OAuthCredentialSnapshot) => import("effect/Effect").Effect<Claims["Type"], OAuthUnavailable, never>;
|
|
80
|
+
readonly resolve: (credential: OAuthCredentialSnapshot, verified: OAuthVerifiedExternalIdentity) => import("effect/Effect").Effect<Claims["Type"], OAuthUnavailable, never>;
|
|
81
81
|
}>;
|
|
82
82
|
SignIn: import("effect/Context").Service<OAuthModule<Id, "sign-in", Claims["Type"]>, {
|
|
83
83
|
readonly begin: (input: {
|
|
@@ -904,6 +904,13 @@ declare const bindDefine: <const Namespace extends string | undefined, Claims ex
|
|
|
904
904
|
readonly profile?: {
|
|
905
905
|
readonly displayName?: string | undefined;
|
|
906
906
|
readonly handle?: string | undefined;
|
|
907
|
+
readonly avatarUrl?: string | undefined;
|
|
908
|
+
readonly profileUrl?: string | undefined;
|
|
909
|
+
readonly email?: string | undefined;
|
|
910
|
+
readonly emailVerified?: boolean | undefined;
|
|
911
|
+
readonly providerData?: {
|
|
912
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
913
|
+
} | undefined;
|
|
907
914
|
} | undefined;
|
|
908
915
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
909
916
|
}[];
|
|
@@ -1047,6 +1054,11 @@ declare const bindDefine: <const Namespace extends string | undefined, Claims ex
|
|
|
1047
1054
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
1048
1055
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1049
1056
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1057
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1058
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1059
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1060
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
1061
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
1050
1062
|
}>>;
|
|
1051
1063
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
1052
1064
|
}>>;
|
|
@@ -1069,6 +1081,11 @@ declare const bindDefine: <const Namespace extends string | undefined, Claims ex
|
|
|
1069
1081
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
1070
1082
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1071
1083
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1084
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1085
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1086
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1087
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
1088
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
1072
1089
|
}>>;
|
|
1073
1090
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
1074
1091
|
}>>;
|
|
@@ -1179,6 +1196,13 @@ declare const bindDefine: <const Namespace extends string | undefined, Claims ex
|
|
|
1179
1196
|
readonly profile?: {
|
|
1180
1197
|
readonly displayName?: string | undefined;
|
|
1181
1198
|
readonly handle?: string | undefined;
|
|
1199
|
+
readonly avatarUrl?: string | undefined;
|
|
1200
|
+
readonly profileUrl?: string | undefined;
|
|
1201
|
+
readonly email?: string | undefined;
|
|
1202
|
+
readonly emailVerified?: boolean | undefined;
|
|
1203
|
+
readonly providerData?: {
|
|
1204
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
1205
|
+
} | undefined;
|
|
1182
1206
|
} | undefined;
|
|
1183
1207
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
1184
1208
|
}[];
|
|
@@ -1250,6 +1274,11 @@ declare const bindDefine: <const Namespace extends string | undefined, Claims ex
|
|
|
1250
1274
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
1251
1275
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1252
1276
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1277
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1278
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1279
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
1280
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
1281
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
1253
1282
|
}>>;
|
|
1254
1283
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
1255
1284
|
}>>;
|
|
@@ -1323,6 +1352,13 @@ declare const bindDefine: <const Namespace extends string | undefined, Claims ex
|
|
|
1323
1352
|
readonly profile?: {
|
|
1324
1353
|
readonly displayName?: string | undefined;
|
|
1325
1354
|
readonly handle?: string | undefined;
|
|
1355
|
+
readonly avatarUrl?: string | undefined;
|
|
1356
|
+
readonly profileUrl?: string | undefined;
|
|
1357
|
+
readonly email?: string | undefined;
|
|
1358
|
+
readonly emailVerified?: boolean | undefined;
|
|
1359
|
+
readonly providerData?: {
|
|
1360
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
1361
|
+
} | undefined;
|
|
1326
1362
|
} | undefined;
|
|
1327
1363
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
1328
1364
|
}[];
|
|
@@ -1683,7 +1719,7 @@ declare const bindDefineRegistration: <Registration extends ClaimsCodec, const N
|
|
|
1683
1719
|
layer: Layer.Layer<BindingModule<Id, "oauth-entry">, RequestBindingConfigurationError, import("effect/Crypto").Crypto | RequestBindingConfig | SubtleCrypto>;
|
|
1684
1720
|
}>;
|
|
1685
1721
|
ClaimsForOAuth: import("effect/Context").Service<OAuthModule<Id, "claims", Claims["Type"]>, {
|
|
1686
|
-
readonly resolve: (credential: OAuthCredentialSnapshot) => import("effect/Effect").Effect<Claims["Type"], OAuthUnavailable, never>;
|
|
1722
|
+
readonly resolve: (credential: OAuthCredentialSnapshot, verified: OAuthVerifiedExternalIdentity) => import("effect/Effect").Effect<Claims["Type"], OAuthUnavailable, never>;
|
|
1687
1723
|
}>;
|
|
1688
1724
|
SignIn: import("effect/Context").Service<OAuthModule<Id, "sign-in", Claims["Type"]>, {
|
|
1689
1725
|
readonly begin: (input: {
|
|
@@ -2358,6 +2394,13 @@ declare const bindDefineRegistration: <Registration extends ClaimsCodec, const N
|
|
|
2358
2394
|
readonly profile?: {
|
|
2359
2395
|
readonly displayName?: string | undefined;
|
|
2360
2396
|
readonly handle?: string | undefined;
|
|
2397
|
+
readonly avatarUrl?: string | undefined;
|
|
2398
|
+
readonly profileUrl?: string | undefined;
|
|
2399
|
+
readonly email?: string | undefined;
|
|
2400
|
+
readonly emailVerified?: boolean | undefined;
|
|
2401
|
+
readonly providerData?: {
|
|
2402
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
2403
|
+
} | undefined;
|
|
2361
2404
|
} | undefined;
|
|
2362
2405
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
2363
2406
|
}[];
|
|
@@ -2501,6 +2544,11 @@ declare const bindDefineRegistration: <Registration extends ClaimsCodec, const N
|
|
|
2501
2544
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
2502
2545
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2503
2546
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2547
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2548
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2549
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2550
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
2551
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
2504
2552
|
}>>;
|
|
2505
2553
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
2506
2554
|
}>>;
|
|
@@ -2523,6 +2571,11 @@ declare const bindDefineRegistration: <Registration extends ClaimsCodec, const N
|
|
|
2523
2571
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
2524
2572
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2525
2573
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2574
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2575
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2576
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2577
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
2578
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
2526
2579
|
}>>;
|
|
2527
2580
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
2528
2581
|
}>>;
|
|
@@ -2633,6 +2686,13 @@ declare const bindDefineRegistration: <Registration extends ClaimsCodec, const N
|
|
|
2633
2686
|
readonly profile?: {
|
|
2634
2687
|
readonly displayName?: string | undefined;
|
|
2635
2688
|
readonly handle?: string | undefined;
|
|
2689
|
+
readonly avatarUrl?: string | undefined;
|
|
2690
|
+
readonly profileUrl?: string | undefined;
|
|
2691
|
+
readonly email?: string | undefined;
|
|
2692
|
+
readonly emailVerified?: boolean | undefined;
|
|
2693
|
+
readonly providerData?: {
|
|
2694
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
2695
|
+
} | undefined;
|
|
2636
2696
|
} | undefined;
|
|
2637
2697
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
2638
2698
|
}[];
|
|
@@ -2704,6 +2764,11 @@ declare const bindDefineRegistration: <Registration extends ClaimsCodec, const N
|
|
|
2704
2764
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
2705
2765
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2706
2766
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2767
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2768
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2769
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
2770
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
2771
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
2707
2772
|
}>>;
|
|
2708
2773
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
2709
2774
|
}>>;
|
|
@@ -2777,6 +2842,13 @@ declare const bindDefineRegistration: <Registration extends ClaimsCodec, const N
|
|
|
2777
2842
|
readonly profile?: {
|
|
2778
2843
|
readonly displayName?: string | undefined;
|
|
2779
2844
|
readonly handle?: string | undefined;
|
|
2845
|
+
readonly avatarUrl?: string | undefined;
|
|
2846
|
+
readonly profileUrl?: string | undefined;
|
|
2847
|
+
readonly email?: string | undefined;
|
|
2848
|
+
readonly emailVerified?: boolean | undefined;
|
|
2849
|
+
readonly providerData?: {
|
|
2850
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
2851
|
+
} | undefined;
|
|
2780
2852
|
} | undefined;
|
|
2781
2853
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
2782
2854
|
}[];
|
|
@@ -3945,6 +4017,13 @@ declare const bindDefineConnected: <const Namespace extends string | undefined,
|
|
|
3945
4017
|
readonly profile?: {
|
|
3946
4018
|
readonly displayName?: string | undefined;
|
|
3947
4019
|
readonly handle?: string | undefined;
|
|
4020
|
+
readonly avatarUrl?: string | undefined;
|
|
4021
|
+
readonly profileUrl?: string | undefined;
|
|
4022
|
+
readonly email?: string | undefined;
|
|
4023
|
+
readonly emailVerified?: boolean | undefined;
|
|
4024
|
+
readonly providerData?: {
|
|
4025
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
4026
|
+
} | undefined;
|
|
3948
4027
|
} | undefined;
|
|
3949
4028
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
3950
4029
|
}[];
|
|
@@ -4088,6 +4167,11 @@ declare const bindDefineConnected: <const Namespace extends string | undefined,
|
|
|
4088
4167
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
4089
4168
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4090
4169
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4170
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4171
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4172
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4173
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
4174
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
4091
4175
|
}>>;
|
|
4092
4176
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
4093
4177
|
}>>;
|
|
@@ -4110,6 +4194,11 @@ declare const bindDefineConnected: <const Namespace extends string | undefined,
|
|
|
4110
4194
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
4111
4195
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4112
4196
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4197
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4198
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4199
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4200
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
4201
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
4113
4202
|
}>>;
|
|
4114
4203
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
4115
4204
|
}>>;
|
|
@@ -4220,6 +4309,13 @@ declare const bindDefineConnected: <const Namespace extends string | undefined,
|
|
|
4220
4309
|
readonly profile?: {
|
|
4221
4310
|
readonly displayName?: string | undefined;
|
|
4222
4311
|
readonly handle?: string | undefined;
|
|
4312
|
+
readonly avatarUrl?: string | undefined;
|
|
4313
|
+
readonly profileUrl?: string | undefined;
|
|
4314
|
+
readonly email?: string | undefined;
|
|
4315
|
+
readonly emailVerified?: boolean | undefined;
|
|
4316
|
+
readonly providerData?: {
|
|
4317
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
4318
|
+
} | undefined;
|
|
4223
4319
|
} | undefined;
|
|
4224
4320
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
4225
4321
|
}[];
|
|
@@ -4291,6 +4387,11 @@ declare const bindDefineConnected: <const Namespace extends string | undefined,
|
|
|
4291
4387
|
readonly profile: import("effect/Schema").optionalKey<import("effect/Schema").Struct<{
|
|
4292
4388
|
readonly displayName: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4293
4389
|
readonly handle: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4390
|
+
readonly avatarUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4391
|
+
readonly profileUrl: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4392
|
+
readonly email: import("effect/Schema").optionalKey<import("effect/Schema").String>;
|
|
4393
|
+
readonly emailVerified: import("effect/Schema").optionalKey<import("effect/Schema").Boolean>;
|
|
4394
|
+
readonly providerData: import("effect/Schema").optionalKey<import("effect/Schema").$Record<import("effect/Schema").String, import("effect/Schema").Codec<import("effect/Schema").Json, import("effect/Schema").Json, never, never>>>;
|
|
4294
4395
|
}>>;
|
|
4295
4396
|
readonly remoteRevocation: import("effect/Schema").Literals<readonly ["Pending", "Confirmed", "Unsupported", "Unknown"]>;
|
|
4296
4397
|
}>>;
|
|
@@ -4364,6 +4465,13 @@ declare const bindDefineConnected: <const Namespace extends string | undefined,
|
|
|
4364
4465
|
readonly profile?: {
|
|
4365
4466
|
readonly displayName?: string | undefined;
|
|
4366
4467
|
readonly handle?: string | undefined;
|
|
4468
|
+
readonly avatarUrl?: string | undefined;
|
|
4469
|
+
readonly profileUrl?: string | undefined;
|
|
4470
|
+
readonly email?: string | undefined;
|
|
4471
|
+
readonly emailVerified?: boolean | undefined;
|
|
4472
|
+
readonly providerData?: {
|
|
4473
|
+
readonly [x: string]: import("effect/Schema").Json;
|
|
4474
|
+
} | undefined;
|
|
4367
4475
|
} | undefined;
|
|
4368
4476
|
readonly remoteRevocation: "Confirmed" | "Pending" | "Unknown" | "Unsupported";
|
|
4369
4477
|
}[];
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { OAuthProviderKey } from "../schema.mjs";
|
|
2
2
|
import { OAuthProtocolRejected } from "../signInErrors.mjs";
|
|
3
|
+
import { GitHubUserProfile } from "./profile.mjs";
|
|
3
4
|
import { Effect, Schema } from "effect";
|
|
4
5
|
//#region src/oauth/github/identity.ts
|
|
5
6
|
const gitHubOAuthAppProviderKey = OAuthProviderKey.make("github");
|
|
6
|
-
const
|
|
7
|
-
id: Schema.Int.check(Schema.isBetween({
|
|
8
|
-
minimum: 1,
|
|
9
|
-
maximum: Number.MAX_SAFE_INTEGER
|
|
10
|
-
})),
|
|
11
|
-
login: Schema.optionalKey(Schema.NonEmptyString.check(Schema.isMaxLength(256)))
|
|
12
|
-
});
|
|
13
|
-
const decode = Schema.decodeUnknownEffect(identity);
|
|
7
|
+
const decode = Schema.decodeUnknownEffect(GitHubUserProfile);
|
|
14
8
|
const decodeGitHubIdentity = Effect.fn("GitHubOAuthApp.decodeIdentity")(function* (body) {
|
|
15
9
|
const value = yield* decode(body).pipe(Effect.mapError(() => OAuthProtocolRejected.make({})));
|
|
10
|
+
const displayName = value.name?.trim() || value.login;
|
|
16
11
|
return {
|
|
17
12
|
subject: String(value.id),
|
|
18
|
-
|
|
13
|
+
profile: {
|
|
14
|
+
...displayName === void 0 ? {} : { displayName },
|
|
15
|
+
...value.login === void 0 ? {} : { handle: value.login },
|
|
16
|
+
...value.avatar_url === void 0 ? {} : { avatarUrl: value.avatar_url },
|
|
17
|
+
...value.html_url === void 0 ? {} : { profileUrl: value.html_url },
|
|
18
|
+
...value.email === null || value.email === void 0 ? {} : { email: value.email },
|
|
19
|
+
providerData: value
|
|
20
|
+
}
|
|
19
21
|
};
|
|
20
22
|
});
|
|
21
23
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.mjs","names":[],"sources":["../../../src/oauth/github/identity.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\n\nimport type { PlainOAuthIdentity } from \"../openid-client/models\";\nimport { OAuthProviderKey } from \"../schema\";\nimport { OAuthProtocolRejected } from \"../signInErrors\";\n\nexport const gitHubOAuthAppProviderKey = OAuthProviderKey.make(\"github\");\n\
|
|
1
|
+
{"version":3,"file":"identity.mjs","names":[],"sources":["../../../src/oauth/github/identity.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\n\nimport type { PlainOAuthIdentity } from \"../openid-client/models\";\nimport { OAuthProviderKey } from \"../schema\";\nimport { OAuthProtocolRejected } from \"../signInErrors\";\nimport { GitHubUserProfile } from \"./profile\";\n\nexport const gitHubOAuthAppProviderKey = OAuthProviderKey.make(\"github\");\n\n// oxlint-disable-next-line no-restricted-properties -- GitHub /user is an untyped, freshly authenticated JSON boundary.\nconst decode = Schema.decodeUnknownEffect(GitHubUserProfile);\n\nexport const decodeGitHubIdentity = Effect.fn(\"GitHubOAuthApp.decodeIdentity\")(function* (\n body: unknown,\n): Effect.fn.Return<PlainOAuthIdentity, OAuthProtocolRejected> {\n const value = yield* decode(body).pipe(Effect.mapError(() => OAuthProtocolRejected.make({})));\n const displayName = value.name?.trim() || value.login;\n\n return {\n subject: String(value.id),\n profile: {\n ...(displayName === undefined ? {} : { displayName }),\n ...(value.login === undefined ? {} : { handle: value.login }),\n ...(value.avatar_url === undefined ? {} : { avatarUrl: value.avatar_url }),\n ...(value.html_url === undefined ? {} : { profileUrl: value.html_url }),\n ...(value.email === null || value.email === undefined ? {} : { email: value.email }),\n providerData: value,\n },\n };\n});\n"],"mappings":";;;;;AAOA,MAAa,4BAA4B,iBAAiB,KAAK,QAAQ;AAGvE,MAAM,SAAS,OAAO,oBAAoB,iBAAiB;AAE3D,MAAa,uBAAuB,OAAO,GAAG,+BAA+B,CAAC,CAAC,WAC7E,MAC6D;CAC7D,MAAM,QAAQ,OAAO,OAAO,IAAI,CAAC,CAAC,KAAK,OAAO,eAAe,sBAAsB,KAAK,CAAC,CAAC,CAAC,CAAC;CAC5F,MAAM,cAAc,MAAM,MAAM,KAAK,KAAK,MAAM;CAEhD,OAAO;EACL,SAAS,OAAO,MAAM,EAAE;EACxB,SAAS;GACP,GAAI,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY;GACnD,GAAI,MAAM,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,MAAM;GAC3D,GAAI,MAAM,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,WAAW;GACxE,GAAI,MAAM,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,YAAY,MAAM,SAAS;GACrE,GAAI,MAAM,UAAU,QAAQ,MAAM,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,MAAM,MAAM;GAClF,cAAc;EAChB;CACF;AACF,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
//#region src/oauth/github/profile.d.ts
|
|
3
|
+
/** All documented GitHub /user fields, with provider spelling and nulls retained.
|
|
4
|
+
* Only the numeric ID establishes identity. Other fields are optional because
|
|
5
|
+
* availability differs by permission and provider response. This does not fetch
|
|
6
|
+
* repositories, email lists, or any additional endpoint. Unknown fields are omitted.
|
|
7
|
+
* URLs are metadata, not approved redirect or server-fetch targets. */
|
|
8
|
+
declare const GitHubUserProfile: Schema.Struct<{
|
|
9
|
+
readonly id: Schema.Int;
|
|
10
|
+
readonly login: Schema.optionalKey<Schema.NonEmptyString>;
|
|
11
|
+
readonly name: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
12
|
+
readonly user_view_type: Schema.optionalKey<Schema.String>;
|
|
13
|
+
readonly node_id: Schema.optionalKey<Schema.String>;
|
|
14
|
+
readonly avatar_url: Schema.optionalKey<Schema.String>;
|
|
15
|
+
readonly gravatar_id: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
16
|
+
readonly url: Schema.optionalKey<Schema.String>;
|
|
17
|
+
readonly html_url: Schema.optionalKey<Schema.String>;
|
|
18
|
+
readonly followers_url: Schema.optionalKey<Schema.String>;
|
|
19
|
+
readonly following_url: Schema.optionalKey<Schema.String>;
|
|
20
|
+
readonly gists_url: Schema.optionalKey<Schema.String>;
|
|
21
|
+
readonly starred_url: Schema.optionalKey<Schema.String>;
|
|
22
|
+
readonly subscriptions_url: Schema.optionalKey<Schema.String>;
|
|
23
|
+
readonly organizations_url: Schema.optionalKey<Schema.String>;
|
|
24
|
+
readonly repos_url: Schema.optionalKey<Schema.String>;
|
|
25
|
+
readonly events_url: Schema.optionalKey<Schema.String>;
|
|
26
|
+
readonly received_events_url: Schema.optionalKey<Schema.String>;
|
|
27
|
+
readonly type: Schema.optionalKey<Schema.String>;
|
|
28
|
+
readonly site_admin: Schema.optionalKey<Schema.Boolean>;
|
|
29
|
+
readonly company: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
30
|
+
readonly blog: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
31
|
+
readonly location: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
32
|
+
readonly email: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
33
|
+
readonly notification_email: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
34
|
+
readonly hireable: Schema.optionalKey<Schema.NullOr<Schema.Boolean>>;
|
|
35
|
+
readonly bio: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
36
|
+
readonly twitter_username: Schema.optionalKey<Schema.NullOr<Schema.String>>;
|
|
37
|
+
readonly public_repos: Schema.optionalKey<Schema.Int>;
|
|
38
|
+
readonly public_gists: Schema.optionalKey<Schema.Int>;
|
|
39
|
+
readonly followers: Schema.optionalKey<Schema.Int>;
|
|
40
|
+
readonly following: Schema.optionalKey<Schema.Int>;
|
|
41
|
+
readonly created_at: Schema.optionalKey<Schema.String>;
|
|
42
|
+
readonly updated_at: Schema.optionalKey<Schema.String>;
|
|
43
|
+
readonly private_gists: Schema.optionalKey<Schema.Int>;
|
|
44
|
+
readonly total_private_repos: Schema.optionalKey<Schema.Int>;
|
|
45
|
+
readonly owned_private_repos: Schema.optionalKey<Schema.Int>;
|
|
46
|
+
readonly disk_usage: Schema.optionalKey<Schema.Int>;
|
|
47
|
+
readonly collaborators: Schema.optionalKey<Schema.Int>;
|
|
48
|
+
readonly two_factor_authentication: Schema.optionalKey<Schema.Boolean>;
|
|
49
|
+
readonly plan: Schema.optionalKey<Schema.Struct<{
|
|
50
|
+
readonly collaborators: Schema.Int;
|
|
51
|
+
readonly name: Schema.String;
|
|
52
|
+
readonly space: Schema.Int;
|
|
53
|
+
readonly private_repos: Schema.Int;
|
|
54
|
+
}>>;
|
|
55
|
+
readonly business_plus: Schema.optionalKey<Schema.Boolean>;
|
|
56
|
+
readonly ldap_dn: Schema.optionalKey<Schema.String>;
|
|
57
|
+
}>;
|
|
58
|
+
type GitHubUserProfile = typeof GitHubUserProfile.Type;
|
|
59
|
+
//#endregion
|
|
60
|
+
export { GitHubUserProfile };
|
|
61
|
+
//# sourceMappingURL=profile.d.mts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
//#region src/oauth/github/profile.ts
|
|
3
|
+
const text = Schema.String.check(Schema.isMaxLength(2048));
|
|
4
|
+
const name = Schema.String.check(Schema.isMaxLength(256));
|
|
5
|
+
const count = Schema.Int.check(Schema.isBetween({
|
|
6
|
+
minimum: 0,
|
|
7
|
+
maximum: Number.MAX_SAFE_INTEGER
|
|
8
|
+
}));
|
|
9
|
+
const optionalText = Schema.optionalKey(text);
|
|
10
|
+
const nullableText = Schema.optionalKey(Schema.NullOr(text));
|
|
11
|
+
/** All documented GitHub /user fields, with provider spelling and nulls retained.
|
|
12
|
+
* Only the numeric ID establishes identity. Other fields are optional because
|
|
13
|
+
* availability differs by permission and provider response. This does not fetch
|
|
14
|
+
* repositories, email lists, or any additional endpoint. Unknown fields are omitted.
|
|
15
|
+
* URLs are metadata, not approved redirect or server-fetch targets. */
|
|
16
|
+
const GitHubUserProfile = Schema.Struct({
|
|
17
|
+
id: Schema.Int.check(Schema.isBetween({
|
|
18
|
+
minimum: 1,
|
|
19
|
+
maximum: Number.MAX_SAFE_INTEGER
|
|
20
|
+
})),
|
|
21
|
+
login: Schema.optionalKey(Schema.NonEmptyString.check(Schema.isMaxLength(256))),
|
|
22
|
+
name: Schema.optionalKey(Schema.NullOr(name)),
|
|
23
|
+
user_view_type: optionalText,
|
|
24
|
+
node_id: optionalText,
|
|
25
|
+
avatar_url: optionalText,
|
|
26
|
+
gravatar_id: nullableText,
|
|
27
|
+
url: optionalText,
|
|
28
|
+
html_url: optionalText,
|
|
29
|
+
followers_url: optionalText,
|
|
30
|
+
following_url: optionalText,
|
|
31
|
+
gists_url: optionalText,
|
|
32
|
+
starred_url: optionalText,
|
|
33
|
+
subscriptions_url: optionalText,
|
|
34
|
+
organizations_url: optionalText,
|
|
35
|
+
repos_url: optionalText,
|
|
36
|
+
events_url: optionalText,
|
|
37
|
+
received_events_url: optionalText,
|
|
38
|
+
type: optionalText,
|
|
39
|
+
site_admin: Schema.optionalKey(Schema.Boolean),
|
|
40
|
+
company: nullableText,
|
|
41
|
+
blog: nullableText,
|
|
42
|
+
location: nullableText,
|
|
43
|
+
email: Schema.optionalKey(Schema.NullOr(Schema.String.check(Schema.isMaxLength(320)))),
|
|
44
|
+
notification_email: Schema.optionalKey(Schema.NullOr(Schema.String.check(Schema.isMaxLength(320)))),
|
|
45
|
+
hireable: Schema.optionalKey(Schema.NullOr(Schema.Boolean)),
|
|
46
|
+
bio: nullableText,
|
|
47
|
+
twitter_username: nullableText,
|
|
48
|
+
public_repos: Schema.optionalKey(count),
|
|
49
|
+
public_gists: Schema.optionalKey(count),
|
|
50
|
+
followers: Schema.optionalKey(count),
|
|
51
|
+
following: Schema.optionalKey(count),
|
|
52
|
+
created_at: optionalText,
|
|
53
|
+
updated_at: optionalText,
|
|
54
|
+
private_gists: Schema.optionalKey(count),
|
|
55
|
+
total_private_repos: Schema.optionalKey(count),
|
|
56
|
+
owned_private_repos: Schema.optionalKey(count),
|
|
57
|
+
disk_usage: Schema.optionalKey(count),
|
|
58
|
+
collaborators: Schema.optionalKey(count),
|
|
59
|
+
two_factor_authentication: Schema.optionalKey(Schema.Boolean),
|
|
60
|
+
plan: Schema.optionalKey(Schema.Struct({
|
|
61
|
+
collaborators: count,
|
|
62
|
+
name: text,
|
|
63
|
+
space: count,
|
|
64
|
+
private_repos: count
|
|
65
|
+
})),
|
|
66
|
+
business_plus: Schema.optionalKey(Schema.Boolean),
|
|
67
|
+
ldap_dn: optionalText
|
|
68
|
+
});
|
|
69
|
+
//#endregion
|
|
70
|
+
export { GitHubUserProfile };
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=profile.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.mjs","names":[],"sources":["../../../src/oauth/github/profile.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nconst text = Schema.String.check(Schema.isMaxLength(2048));\nconst name = Schema.String.check(Schema.isMaxLength(256));\nconst count = Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER }));\nconst optionalText = Schema.optionalKey(text);\nconst nullableText = Schema.optionalKey(Schema.NullOr(text));\n\n/** All documented GitHub /user fields, with provider spelling and nulls retained.\n * Only the numeric ID establishes identity. Other fields are optional because\n * availability differs by permission and provider response. This does not fetch\n * repositories, email lists, or any additional endpoint. Unknown fields are omitted.\n * URLs are metadata, not approved redirect or server-fetch targets. */\nexport const GitHubUserProfile = Schema.Struct({\n id: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER })),\n login: Schema.optionalKey(Schema.NonEmptyString.check(Schema.isMaxLength(256))),\n name: Schema.optionalKey(Schema.NullOr(name)),\n user_view_type: optionalText,\n node_id: optionalText,\n avatar_url: optionalText,\n gravatar_id: nullableText,\n url: optionalText,\n html_url: optionalText,\n followers_url: optionalText,\n following_url: optionalText,\n gists_url: optionalText,\n starred_url: optionalText,\n subscriptions_url: optionalText,\n organizations_url: optionalText,\n repos_url: optionalText,\n events_url: optionalText,\n received_events_url: optionalText,\n type: optionalText,\n site_admin: Schema.optionalKey(Schema.Boolean),\n company: nullableText,\n blog: nullableText,\n location: nullableText,\n email: Schema.optionalKey(Schema.NullOr(Schema.String.check(Schema.isMaxLength(320)))),\n notification_email: Schema.optionalKey(\n Schema.NullOr(Schema.String.check(Schema.isMaxLength(320))),\n ),\n hireable: Schema.optionalKey(Schema.NullOr(Schema.Boolean)),\n bio: nullableText,\n twitter_username: nullableText,\n public_repos: Schema.optionalKey(count),\n public_gists: Schema.optionalKey(count),\n followers: Schema.optionalKey(count),\n following: Schema.optionalKey(count),\n created_at: optionalText,\n updated_at: optionalText,\n private_gists: Schema.optionalKey(count),\n total_private_repos: Schema.optionalKey(count),\n owned_private_repos: Schema.optionalKey(count),\n disk_usage: Schema.optionalKey(count),\n collaborators: Schema.optionalKey(count),\n two_factor_authentication: Schema.optionalKey(Schema.Boolean),\n plan: Schema.optionalKey(\n Schema.Struct({ collaborators: count, name: text, space: count, private_repos: count }),\n ),\n business_plus: Schema.optionalKey(Schema.Boolean),\n ldap_dn: optionalText,\n});\n\nexport type GitHubUserProfile = typeof GitHubUserProfile.Type;\n"],"mappings":";;AAEA,MAAM,OAAO,OAAO,OAAO,MAAM,OAAO,YAAY,IAAI,CAAC;AACzD,MAAM,OAAO,OAAO,OAAO,MAAM,OAAO,YAAY,GAAG,CAAC;AACxD,MAAM,QAAQ,OAAO,IAAI,MAAM,OAAO,UAAU;CAAE,SAAS;CAAG,SAAS,OAAO;AAAiB,CAAC,CAAC;AACjG,MAAM,eAAe,OAAO,YAAY,IAAI;AAC5C,MAAM,eAAe,OAAO,YAAY,OAAO,OAAO,IAAI,CAAC;;;;;;AAO3D,MAAa,oBAAoB,OAAO,OAAO;CAC7C,IAAI,OAAO,IAAI,MAAM,OAAO,UAAU;EAAE,SAAS;EAAG,SAAS,OAAO;CAAiB,CAAC,CAAC;CACvF,OAAO,OAAO,YAAY,OAAO,eAAe,MAAM,OAAO,YAAY,GAAG,CAAC,CAAC;CAC9E,MAAM,OAAO,YAAY,OAAO,OAAO,IAAI,CAAC;CAC5C,gBAAgB;CAChB,SAAS;CACT,YAAY;CACZ,aAAa;CACb,KAAK;CACL,UAAU;CACV,eAAe;CACf,eAAe;CACf,WAAW;CACX,aAAa;CACb,mBAAmB;CACnB,mBAAmB;CACnB,WAAW;CACX,YAAY;CACZ,qBAAqB;CACrB,MAAM;CACN,YAAY,OAAO,YAAY,OAAO,OAAO;CAC7C,SAAS;CACT,MAAM;CACN,UAAU;CACV,OAAO,OAAO,YAAY,OAAO,OAAO,OAAO,OAAO,MAAM,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC;CACrF,oBAAoB,OAAO,YACzB,OAAO,OAAO,OAAO,OAAO,MAAM,OAAO,YAAY,GAAG,CAAC,CAAC,CAC5D;CACA,UAAU,OAAO,YAAY,OAAO,OAAO,OAAO,OAAO,CAAC;CAC1D,KAAK;CACL,kBAAkB;CAClB,cAAc,OAAO,YAAY,KAAK;CACtC,cAAc,OAAO,YAAY,KAAK;CACtC,WAAW,OAAO,YAAY,KAAK;CACnC,WAAW,OAAO,YAAY,KAAK;CACnC,YAAY;CACZ,YAAY;CACZ,eAAe,OAAO,YAAY,KAAK;CACvC,qBAAqB,OAAO,YAAY,KAAK;CAC7C,qBAAqB,OAAO,YAAY,KAAK;CAC7C,YAAY,OAAO,YAAY,KAAK;CACpC,eAAe,OAAO,YAAY,KAAK;CACvC,2BAA2B,OAAO,YAAY,OAAO,OAAO;CAC5D,MAAM,OAAO,YACX,OAAO,OAAO;EAAE,eAAe;EAAO,MAAM;EAAM,OAAO;EAAO,eAAe;CAAM,CAAC,CACxF;CACA,eAAe,OAAO,YAAY,OAAO,OAAO;CAChD,SAAS;AACX,CAAC"}
|
|
@@ -15,7 +15,7 @@ import { Effect, Encoding, Layer, Predicate, Redacted, Schema } from "effect";
|
|
|
15
15
|
//#region src/oauth/github/protocol.ts
|
|
16
16
|
const unavailable = () => OAuthUnavailable.make({});
|
|
17
17
|
const invalid = () => OpenIdClientConfigurationError.make({ reason: "provider" });
|
|
18
|
-
const issuer = OAuthIssuer.make("https://github.com");
|
|
18
|
+
const issuer = OAuthIssuer.make("https://github.com/login/oauth");
|
|
19
19
|
const headers = Object.freeze({
|
|
20
20
|
Accept: "application/vnd.github+json",
|
|
21
21
|
"User-Agent": "effect-auth-github-oauth-app",
|
|
@@ -61,7 +61,7 @@ const provider = (registration) => ({
|
|
|
61
61
|
issuance: registration.issuance,
|
|
62
62
|
issuer,
|
|
63
63
|
protocol: "oauth",
|
|
64
|
-
responseIssuerMode: "
|
|
64
|
+
responseIssuerMode: "required",
|
|
65
65
|
clientId: registration.clientId,
|
|
66
66
|
authentication: {
|
|
67
67
|
method: "client_secret_post",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.mjs","names":[],"sources":["../../../src/oauth/github/protocol.ts"],"sourcesContent":["import { Effect, Encoding, Layer, Predicate, Redacted, Schema } from \"effect\";\nimport type { CustomFetch } from \"openid-client\";\n\nimport { OAuthConnectedProfile } from \"../connectedModels\";\nimport { OAuthConnectedProtocol } from \"../OAuthConnectedProtocol\";\nimport { OAuthProtocol } from \"../OAuthProtocol\";\nimport {\n DefiniteTokenRejection,\n tokenCompatibility,\n type ConnectedCompatibility,\n} from \"../openid-client/compatibility\";\nimport { makeConnectedProtocolWithCompatibility } from \"../openid-client/connected/protocol\";\nimport {\n OpenIdClientConfigurationError,\n type OpenIdClientOAuthProvider,\n} from \"../openid-client/models\";\nimport { makeOpenIdClientOAuthProtocol } from \"../openid-client/protocol\";\nimport { ProviderRevocation } from \"../openid-client/ProviderRevocation\";\nimport { boundedFetch } from \"../openid-client/transport\";\nimport { OAuthUnavailable } from \"../signInErrors\";\nimport { OAuthCallbackId, OAuthGeneration, OAuthIssuer, OAuthRedirectUri } from \"../signInModels\";\nimport { snapshotOAuthSync } from \"../signInSnapshot\";\nimport { decodeGitHubIdentity, gitHubOAuthAppProviderKey } from \"./identity\";\nimport type {\n GitHubOAuthAppConnectedProtocolOptions,\n GitHubOAuthAppGeneration,\n GitHubOAuthAppProtocolOptions,\n} from \"./models\";\n\nconst unavailable = () => OAuthUnavailable.make({});\nconst invalid = () => OpenIdClientConfigurationError.make({ reason: \"provider\" });\nconst issuer = OAuthIssuer.make(\"https://github.com\");\n\nconst headers = Object.freeze({\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"effect-auth-github-oauth-app\",\n \"X-GitHub-Api-Version\": \"2026-03-10\",\n});\n\nconst generation = Schema.Struct({\n configurationGeneration: OAuthGeneration,\n issuance: Schema.Literals([\"active\", \"retired\"]),\n clientId: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9._-]{1,256}$/)),\n clientSecret: Schema.RedactedFromValue(Schema.NonEmptyString.check(Schema.isMaxLength(4096))),\n callbacks: Schema.Array(\n Schema.Struct({ callbackId: OAuthCallbackId, redirectUri: OAuthRedirectUri }),\n ).check(Schema.isMinLength(1), Schema.isMaxLength(16)),\n});\n\nconst generations = Schema.Array(generation).check(Schema.isMinLength(1), Schema.isMaxLength(64));\n\nconst connectedGenerations = Schema.Array(\n Schema.Struct({\n ...generation.fields,\n profiles: Schema.Array(OAuthConnectedProfile).check(\n Schema.isMinLength(1),\n Schema.isMaxLength(64),\n ),\n }),\n).check(Schema.isMinLength(1), Schema.isMaxLength(64));\n\nconst timeout = Schema.Finite.check(Schema.isBetween({ minimum: 1, maximum: 30 }));\nconst isTimeout = Schema.is(timeout);\n\nconst capture = <S extends Schema.Codec<unknown, unknown, never, never>>(\n schema: S,\n registrations: S[\"Type\"],\n options: {\n readonly timeoutSeconds: number;\n readonly fetch?: GitHubOAuthAppProtocolOptions[\"fetch\"];\n },\n) =>\n Effect.try({\n try: () => {\n const result = snapshotOAuthSync(schema, registrations);\n const fetch = options.fetch;\n const timeoutSeconds = options.timeoutSeconds;\n\n if (!isTimeout(timeoutSeconds) || (fetch !== undefined && !Predicate.isFunction(fetch)))\n throw invalid();\n\n return { registrations: result, timeoutSeconds, ...(fetch === undefined ? {} : { fetch }) };\n },\n catch: invalid,\n });\n\nconst provider = (\n registration: GitHubOAuthAppGeneration,\n): Omit<OpenIdClientOAuthProvider, \"scopes\"> => ({\n provider: gitHubOAuthAppProviderKey,\n configurationGeneration: registration.configurationGeneration,\n issuance: registration.issuance,\n issuer,\n protocol: \"oauth\",\n responseIssuerMode: \"unsupported\",\n clientId: registration.clientId,\n authentication: { method: \"client_secret_post\", secret: registration.clientSecret },\n callbacks: registration.callbacks,\n authorizationEndpoint: \"https://github.com/login/oauth/authorize\",\n tokenEndpoint: \"https://github.com/login/oauth/access_token\",\n pkceS256: true,\n identitySource: {\n url: \"https://api.github.com/user\",\n headers,\n decodeIdentity: decodeGitHubIdentity,\n },\n});\n\nconst csvCell = Schema.String.check(Schema.isPattern(/^[A-Za-z0-9_:-]{1,256}$/));\nconst isCell = Schema.is(csvCell);\n\n/** GitHub's receipt is comma-delimited, unlike the generic OAuth scope string. */\nconst scopes = (\n receipt: string | undefined,\n expected: ReadonlyArray<string>,\n): ReadonlyArray<string> => {\n if (receipt === undefined || receipt.length > 16447) throw unavailable();\n\n const result =\n receipt === \"\" ? [] : receipt.split(\",\").map((cell) => cell.replace(/^[ \\t]+|[ \\t]+$/g, \"\"));\n\n if (\n result.length > 64 ||\n result.some((cell) => !isCell(cell)) ||\n new Set(result).size !== result.length ||\n result.length !== expected.length ||\n result.some((cell) => !expected.includes(cell))\n )\n throw unavailable();\n\n return result;\n};\n\nconst token = Schema.NonEmptyString.check(Schema.isMaxLength(16384));\nconst expiry = Schema.Finite.check(Schema.isGreaterThan(0));\n\nconst receiptSchema = Schema.Struct({\n access_token: token,\n token_type: Schema.String.check(Schema.isPattern(/^[Bb][Ee][Aa][Rr][Ee][Rr]$/)),\n scope: Schema.String.check(Schema.isMaxLength(16447)),\n expires_in: Schema.optionalKey(expiry),\n refresh_token: Schema.optionalKey(token),\n refresh_token_expires_in: Schema.optionalKey(expiry),\n});\n\n// oxlint-disable-next-line no-restricted-properties -- Inspect the bounded raw receipt before the maintained parser can coerce expiry fields.\nconst decodeReceipt = Schema.decodeUnknownSync(receiptSchema);\n\nconst encodeRevocation = Schema.encodeSync(\n Schema.fromJsonString(Schema.Struct({ access_token: token })),\n);\n\nconst terminalReceipt = Schema.Struct({\n error: Schema.NonEmptyString.check(Schema.isMaxLength(128)),\n error_description: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(4096))),\n error_uri: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(2048))),\n});\n\n// oxlint-disable-next-line no-restricted-properties -- Fully validate the raw terminal receipt before classifying a provider rejection.\nconst decodeTerminalReceipt = Schema.decodeUnknownSync(terminalReceipt);\n\nconst successKeys = [\n \"access_token\",\n \"token_type\",\n \"scope\",\n \"expires_in\",\n \"refresh_token\",\n \"refresh_token_expires_in\",\n \"id_token\",\n];\n\nconst compatibility: ConnectedCompatibility = Object.freeze<ConnectedCompatibility>({\n inspectReceipt: ({ body, status, contentType }, input) => {\n if (contentType?.split(\";\", 1)[0]?.trim().toLowerCase() !== \"application/json\")\n throw unavailable();\n if (!Predicate.isObject(body)) throw unavailable();\n if (Object.hasOwn(body, \"error\")) {\n if (successKeys.some((key) => Object.hasOwn(body, key))) throw unavailable();\n const terminal = decodeTerminalReceipt(body);\n\n if (\n (status === 200 || status === 400) &&\n terminal.error ===\n (input.operation === \"authorization_code\" ? \"bad_verification_code\" : \"bad_refresh_token\")\n ) {\n throw new DefiniteTokenRejection();\n }\n throw unavailable();\n }\n if (\n status !== 200 ||\n [\"error_description\", \"error_uri\", \"id_token\"].some((key) => Object.hasOwn(body, key))\n )\n throw unavailable();\n const receipt = decodeReceipt(body);\n\n scopes(receipt.scope, input.scopes);\n if (\n input.refreshRequired &&\n (receipt.refresh_token === undefined ||\n receipt.expires_in === undefined ||\n receipt.refresh_token_expires_in === undefined)\n )\n throw unavailable();\n },\n authorizationScopes: (permissions, refresh) =>\n refresh ? [...permissions, \"offline_access\"] : permissions,\n decodeScopes: scopes,\n includeRefreshScope: false,\n});\n\nconst revocationLayer = (\n options: Pick<GitHubOAuthAppConnectedProtocolOptions, \"fetch\" | \"timeoutSeconds\">,\n) => {\n const fetch: CustomFetch =\n options.fetch ??\n ((url, init) =>\n globalThis.fetch(url, {\n ...init,\n body: init.body instanceof Uint8Array ? new Uint8Array(init.body) : init.body,\n }));\n\n const timeoutSeconds = options.timeoutSeconds;\n\n return Layer.succeed(\n ProviderRevocation,\n ProviderRevocation.of({\n revoke: Effect.fn(\"GitHubOAuthApp.revoke\")(function* (input) {\n yield* Effect.tryPromise({\n try: async (effectSignal) => {\n if (\n input.authentication.method !== \"client_secret_post\" ||\n input.context.configuration.profile.clientRegistrationId !== input.clientId ||\n input.context.identity.provider !== gitHubOAuthAppProviderKey ||\n input.context.identity.issuer !== issuer\n )\n throw unavailable();\n const url = `https://api.github.com/applications/${encodeURIComponent(input.clientId)}/grant`;\n\n const signal = AbortSignal.any([\n effectSignal,\n AbortSignal.timeout(Math.ceil(timeoutSeconds * 1000)),\n ]);\n\n const transport = boundedFetch(fetch, signal, new Set([url]));\n\n const response = await transport(url, {\n method: \"DELETE\",\n redirect: \"manual\",\n headers: {\n ...headers,\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${Encoding.encodeBase64(`${input.clientId}:${Redacted.value(input.authentication.secret)}`)}`,\n },\n body: encodeRevocation({ access_token: Redacted.value(input.material.accessToken) }),\n signal,\n });\n\n signal.throwIfAborted();\n if (response.status !== 204) throw unavailable();\n },\n catch: unavailable,\n });\n }),\n }),\n );\n};\n\n/** A GitHub.com OAuth App generation for the same provider list as generic OIDC.\n * Retains GitHub receipt/error rules and requests read:user, with no repository access.\n * Construction performs no I/O; invalid configuration throws the typed configuration error. */\nexport const gitHubOAuthAppProvider = (\n registration: GitHubOAuthAppGeneration,\n): OpenIdClientOAuthProvider => {\n let saved: GitHubOAuthAppGeneration;\n\n try {\n saved = snapshotOAuthSync(generation, registration);\n } catch {\n throw invalid();\n }\n\n return {\n ...provider(saved),\n scopes: [\"read:user\"],\n [tokenCompatibility]: compatibility,\n };\n};\n\nexport const makeGitHubOAuthAppProtocol = Effect.fn(\"makeGitHubOAuthAppProtocol\")(function* (\n options: GitHubOAuthAppProtocolOptions,\n) {\n const saved = yield* capture(generations, options.registrations, options);\n\n if (saved.registrations.filter((item) => item.issuance === \"active\").length !== 1)\n return yield* invalid();\n\n return yield* makeOpenIdClientOAuthProtocol({\n ...saved,\n providers: saved.registrations.map(gitHubOAuthAppProvider),\n });\n});\n\nexport const makeGitHubOAuthAppConnectedProtocol = Effect.fn(\"makeGitHubOAuthAppConnectedProtocol\")(\n function* (options: GitHubOAuthAppConnectedProtocolOptions) {\n const saved = yield* capture(connectedGenerations, options.registrations, options);\n\n if (saved.registrations.filter((item) => item.issuance === \"active\").length !== 1)\n return yield* invalid();\n for (const registration of saved.registrations) {\n for (const profile of registration.profiles) {\n if (\n profile.provider !== gitHubOAuthAppProviderKey ||\n profile.clientRegistrationId !== registration.clientId ||\n profile.resources.length !== 0 ||\n profile.scopes.some((scope) => scope === \"offline_access\" || !isCell(scope)) ||\n (profile.retention === \"access-only\"\n ? profile.refresh !== \"unsupported\" ||\n profile.maximumRefreshLifetimeMillis !== undefined\n : profile.refresh !== \"rotating\" || profile.maximumRefreshLifetimeMillis === undefined)\n )\n return yield* invalid();\n }\n }\n\n return yield* makeConnectedProtocolWithCompatibility(\n {\n ...saved,\n providers: saved.registrations.map((item) => ({\n ...provider(item),\n profiles: item.profiles,\n clientRegistrationId: item.clientId,\n resourceIndicators: \"unsupported\",\n refreshExpiry: { field: \"refresh_token_expires_in\", zero: \"expired\" },\n revocation: { mode: \"provider-cohort\" },\n })),\n },\n compatibility,\n ).pipe(Effect.provide(revocationLayer(saved)));\n },\n);\n\nexport const gitHubOAuthAppProtocolLayer = (options: GitHubOAuthAppProtocolOptions) =>\n Layer.effect(OAuthProtocol, makeGitHubOAuthAppProtocol(options));\n\nexport const gitHubOAuthAppConnectedProtocolLayer = (\n options: GitHubOAuthAppConnectedProtocolOptions,\n) => Layer.effect(OAuthConnectedProtocol, makeGitHubOAuthAppConnectedProtocol(options));\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"protocol.mjs","names":[],"sources":["../../../src/oauth/github/protocol.ts"],"sourcesContent":["import { Effect, Encoding, Layer, Predicate, Redacted, Schema } from \"effect\";\nimport type { CustomFetch } from \"openid-client\";\n\nimport { OAuthConnectedProfile } from \"../connectedModels\";\nimport { OAuthConnectedProtocol } from \"../OAuthConnectedProtocol\";\nimport { OAuthProtocol } from \"../OAuthProtocol\";\nimport {\n DefiniteTokenRejection,\n tokenCompatibility,\n type ConnectedCompatibility,\n} from \"../openid-client/compatibility\";\nimport { makeConnectedProtocolWithCompatibility } from \"../openid-client/connected/protocol\";\nimport {\n OpenIdClientConfigurationError,\n type OpenIdClientOAuthProvider,\n} from \"../openid-client/models\";\nimport { makeOpenIdClientOAuthProtocol } from \"../openid-client/protocol\";\nimport { ProviderRevocation } from \"../openid-client/ProviderRevocation\";\nimport { boundedFetch } from \"../openid-client/transport\";\nimport { OAuthUnavailable } from \"../signInErrors\";\nimport { OAuthCallbackId, OAuthGeneration, OAuthIssuer, OAuthRedirectUri } from \"../signInModels\";\nimport { snapshotOAuthSync } from \"../signInSnapshot\";\nimport { decodeGitHubIdentity, gitHubOAuthAppProviderKey } from \"./identity\";\nimport type {\n GitHubOAuthAppConnectedProtocolOptions,\n GitHubOAuthAppGeneration,\n GitHubOAuthAppProtocolOptions,\n} from \"./models\";\n\nconst unavailable = () => OAuthUnavailable.make({});\nconst invalid = () => OpenIdClientConfigurationError.make({ reason: \"provider\" });\n// GitHub's OAuth authorization server issuer, including its RFC 9207 callback value.\nconst issuer = OAuthIssuer.make(\"https://github.com/login/oauth\");\n\nconst headers = Object.freeze({\n Accept: \"application/vnd.github+json\",\n \"User-Agent\": \"effect-auth-github-oauth-app\",\n \"X-GitHub-Api-Version\": \"2026-03-10\",\n});\n\nconst generation = Schema.Struct({\n configurationGeneration: OAuthGeneration,\n issuance: Schema.Literals([\"active\", \"retired\"]),\n clientId: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9._-]{1,256}$/)),\n clientSecret: Schema.RedactedFromValue(Schema.NonEmptyString.check(Schema.isMaxLength(4096))),\n callbacks: Schema.Array(\n Schema.Struct({ callbackId: OAuthCallbackId, redirectUri: OAuthRedirectUri }),\n ).check(Schema.isMinLength(1), Schema.isMaxLength(16)),\n});\n\nconst generations = Schema.Array(generation).check(Schema.isMinLength(1), Schema.isMaxLength(64));\n\nconst connectedGenerations = Schema.Array(\n Schema.Struct({\n ...generation.fields,\n profiles: Schema.Array(OAuthConnectedProfile).check(\n Schema.isMinLength(1),\n Schema.isMaxLength(64),\n ),\n }),\n).check(Schema.isMinLength(1), Schema.isMaxLength(64));\n\nconst timeout = Schema.Finite.check(Schema.isBetween({ minimum: 1, maximum: 30 }));\nconst isTimeout = Schema.is(timeout);\n\nconst capture = <S extends Schema.Codec<unknown, unknown, never, never>>(\n schema: S,\n registrations: S[\"Type\"],\n options: {\n readonly timeoutSeconds: number;\n readonly fetch?: GitHubOAuthAppProtocolOptions[\"fetch\"];\n },\n) =>\n Effect.try({\n try: () => {\n const result = snapshotOAuthSync(schema, registrations);\n const fetch = options.fetch;\n const timeoutSeconds = options.timeoutSeconds;\n\n if (!isTimeout(timeoutSeconds) || (fetch !== undefined && !Predicate.isFunction(fetch)))\n throw invalid();\n\n return { registrations: result, timeoutSeconds, ...(fetch === undefined ? {} : { fetch }) };\n },\n catch: invalid,\n });\n\nconst provider = (\n registration: GitHubOAuthAppGeneration,\n): Omit<OpenIdClientOAuthProvider, \"scopes\"> => ({\n provider: gitHubOAuthAppProviderKey,\n configurationGeneration: registration.configurationGeneration,\n issuance: registration.issuance,\n issuer,\n protocol: \"oauth\",\n responseIssuerMode: \"required\",\n clientId: registration.clientId,\n authentication: { method: \"client_secret_post\", secret: registration.clientSecret },\n callbacks: registration.callbacks,\n authorizationEndpoint: \"https://github.com/login/oauth/authorize\",\n tokenEndpoint: \"https://github.com/login/oauth/access_token\",\n pkceS256: true,\n identitySource: {\n url: \"https://api.github.com/user\",\n headers,\n decodeIdentity: decodeGitHubIdentity,\n },\n});\n\nconst csvCell = Schema.String.check(Schema.isPattern(/^[A-Za-z0-9_:-]{1,256}$/));\nconst isCell = Schema.is(csvCell);\n\n/** GitHub's receipt is comma-delimited, unlike the generic OAuth scope string. */\nconst scopes = (\n receipt: string | undefined,\n expected: ReadonlyArray<string>,\n): ReadonlyArray<string> => {\n if (receipt === undefined || receipt.length > 16447) throw unavailable();\n\n const result =\n receipt === \"\" ? [] : receipt.split(\",\").map((cell) => cell.replace(/^[ \\t]+|[ \\t]+$/g, \"\"));\n\n if (\n result.length > 64 ||\n result.some((cell) => !isCell(cell)) ||\n new Set(result).size !== result.length ||\n result.length !== expected.length ||\n result.some((cell) => !expected.includes(cell))\n )\n throw unavailable();\n\n return result;\n};\n\nconst token = Schema.NonEmptyString.check(Schema.isMaxLength(16384));\nconst expiry = Schema.Finite.check(Schema.isGreaterThan(0));\n\nconst receiptSchema = Schema.Struct({\n access_token: token,\n token_type: Schema.String.check(Schema.isPattern(/^[Bb][Ee][Aa][Rr][Ee][Rr]$/)),\n scope: Schema.String.check(Schema.isMaxLength(16447)),\n expires_in: Schema.optionalKey(expiry),\n refresh_token: Schema.optionalKey(token),\n refresh_token_expires_in: Schema.optionalKey(expiry),\n});\n\n// oxlint-disable-next-line no-restricted-properties -- Inspect the bounded raw receipt before the maintained parser can coerce expiry fields.\nconst decodeReceipt = Schema.decodeUnknownSync(receiptSchema);\n\nconst encodeRevocation = Schema.encodeSync(\n Schema.fromJsonString(Schema.Struct({ access_token: token })),\n);\n\nconst terminalReceipt = Schema.Struct({\n error: Schema.NonEmptyString.check(Schema.isMaxLength(128)),\n error_description: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(4096))),\n error_uri: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(2048))),\n});\n\n// oxlint-disable-next-line no-restricted-properties -- Fully validate the raw terminal receipt before classifying a provider rejection.\nconst decodeTerminalReceipt = Schema.decodeUnknownSync(terminalReceipt);\n\nconst successKeys = [\n \"access_token\",\n \"token_type\",\n \"scope\",\n \"expires_in\",\n \"refresh_token\",\n \"refresh_token_expires_in\",\n \"id_token\",\n];\n\nconst compatibility: ConnectedCompatibility = Object.freeze<ConnectedCompatibility>({\n inspectReceipt: ({ body, status, contentType }, input) => {\n if (contentType?.split(\";\", 1)[0]?.trim().toLowerCase() !== \"application/json\")\n throw unavailable();\n if (!Predicate.isObject(body)) throw unavailable();\n if (Object.hasOwn(body, \"error\")) {\n if (successKeys.some((key) => Object.hasOwn(body, key))) throw unavailable();\n const terminal = decodeTerminalReceipt(body);\n\n if (\n (status === 200 || status === 400) &&\n terminal.error ===\n (input.operation === \"authorization_code\" ? \"bad_verification_code\" : \"bad_refresh_token\")\n ) {\n throw new DefiniteTokenRejection();\n }\n throw unavailable();\n }\n if (\n status !== 200 ||\n [\"error_description\", \"error_uri\", \"id_token\"].some((key) => Object.hasOwn(body, key))\n )\n throw unavailable();\n const receipt = decodeReceipt(body);\n\n scopes(receipt.scope, input.scopes);\n if (\n input.refreshRequired &&\n (receipt.refresh_token === undefined ||\n receipt.expires_in === undefined ||\n receipt.refresh_token_expires_in === undefined)\n )\n throw unavailable();\n },\n authorizationScopes: (permissions, refresh) =>\n refresh ? [...permissions, \"offline_access\"] : permissions,\n decodeScopes: scopes,\n includeRefreshScope: false,\n});\n\nconst revocationLayer = (\n options: Pick<GitHubOAuthAppConnectedProtocolOptions, \"fetch\" | \"timeoutSeconds\">,\n) => {\n const fetch: CustomFetch =\n options.fetch ??\n ((url, init) =>\n globalThis.fetch(url, {\n ...init,\n body: init.body instanceof Uint8Array ? new Uint8Array(init.body) : init.body,\n }));\n\n const timeoutSeconds = options.timeoutSeconds;\n\n return Layer.succeed(\n ProviderRevocation,\n ProviderRevocation.of({\n revoke: Effect.fn(\"GitHubOAuthApp.revoke\")(function* (input) {\n yield* Effect.tryPromise({\n try: async (effectSignal) => {\n if (\n input.authentication.method !== \"client_secret_post\" ||\n input.context.configuration.profile.clientRegistrationId !== input.clientId ||\n input.context.identity.provider !== gitHubOAuthAppProviderKey ||\n input.context.identity.issuer !== issuer\n )\n throw unavailable();\n const url = `https://api.github.com/applications/${encodeURIComponent(input.clientId)}/grant`;\n\n const signal = AbortSignal.any([\n effectSignal,\n AbortSignal.timeout(Math.ceil(timeoutSeconds * 1000)),\n ]);\n\n const transport = boundedFetch(fetch, signal, new Set([url]));\n\n const response = await transport(url, {\n method: \"DELETE\",\n redirect: \"manual\",\n headers: {\n ...headers,\n \"Content-Type\": \"application/json\",\n Authorization: `Basic ${Encoding.encodeBase64(`${input.clientId}:${Redacted.value(input.authentication.secret)}`)}`,\n },\n body: encodeRevocation({ access_token: Redacted.value(input.material.accessToken) }),\n signal,\n });\n\n signal.throwIfAborted();\n if (response.status !== 204) throw unavailable();\n },\n catch: unavailable,\n });\n }),\n }),\n );\n};\n\n/** A GitHub.com OAuth App generation for the same provider list as generic OIDC.\n * Retains GitHub receipt/error rules and requests read:user, with no repository access.\n * Construction performs no I/O; invalid configuration throws the typed configuration error. */\nexport const gitHubOAuthAppProvider = (\n registration: GitHubOAuthAppGeneration,\n): OpenIdClientOAuthProvider => {\n let saved: GitHubOAuthAppGeneration;\n\n try {\n saved = snapshotOAuthSync(generation, registration);\n } catch {\n throw invalid();\n }\n\n return {\n ...provider(saved),\n scopes: [\"read:user\"],\n [tokenCompatibility]: compatibility,\n };\n};\n\nexport const makeGitHubOAuthAppProtocol = Effect.fn(\"makeGitHubOAuthAppProtocol\")(function* (\n options: GitHubOAuthAppProtocolOptions,\n) {\n const saved = yield* capture(generations, options.registrations, options);\n\n if (saved.registrations.filter((item) => item.issuance === \"active\").length !== 1)\n return yield* invalid();\n\n return yield* makeOpenIdClientOAuthProtocol({\n ...saved,\n providers: saved.registrations.map(gitHubOAuthAppProvider),\n });\n});\n\nexport const makeGitHubOAuthAppConnectedProtocol = Effect.fn(\"makeGitHubOAuthAppConnectedProtocol\")(\n function* (options: GitHubOAuthAppConnectedProtocolOptions) {\n const saved = yield* capture(connectedGenerations, options.registrations, options);\n\n if (saved.registrations.filter((item) => item.issuance === \"active\").length !== 1)\n return yield* invalid();\n for (const registration of saved.registrations) {\n for (const profile of registration.profiles) {\n if (\n profile.provider !== gitHubOAuthAppProviderKey ||\n profile.clientRegistrationId !== registration.clientId ||\n profile.resources.length !== 0 ||\n profile.scopes.some((scope) => scope === \"offline_access\" || !isCell(scope)) ||\n (profile.retention === \"access-only\"\n ? profile.refresh !== \"unsupported\" ||\n profile.maximumRefreshLifetimeMillis !== undefined\n : profile.refresh !== \"rotating\" || profile.maximumRefreshLifetimeMillis === undefined)\n )\n return yield* invalid();\n }\n }\n\n return yield* makeConnectedProtocolWithCompatibility(\n {\n ...saved,\n providers: saved.registrations.map((item) => ({\n ...provider(item),\n profiles: item.profiles,\n clientRegistrationId: item.clientId,\n resourceIndicators: \"unsupported\",\n refreshExpiry: { field: \"refresh_token_expires_in\", zero: \"expired\" },\n revocation: { mode: \"provider-cohort\" },\n })),\n },\n compatibility,\n ).pipe(Effect.provide(revocationLayer(saved)));\n },\n);\n\nexport const gitHubOAuthAppProtocolLayer = (options: GitHubOAuthAppProtocolOptions) =>\n Layer.effect(OAuthProtocol, makeGitHubOAuthAppProtocol(options));\n\nexport const gitHubOAuthAppConnectedProtocolLayer = (\n options: GitHubOAuthAppConnectedProtocolOptions,\n) => Layer.effect(OAuthConnectedProtocol, makeGitHubOAuthAppConnectedProtocol(options));\n"],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ import { OAuthConnectedProtocol } from "../../OAuthConnectedProtocol.mjs";
|
|
|
8
8
|
import { DefiniteTokenRejection } from "../compatibility.mjs";
|
|
9
9
|
import { boundedFetch } from "../transport.mjs";
|
|
10
10
|
import { clientAuthentication } from "../configuration.mjs";
|
|
11
|
+
import { decodeOidcProfile } from "../profile.mjs";
|
|
11
12
|
import { ProviderRevocation } from "../ProviderRevocation.mjs";
|
|
12
13
|
import { installConnectedConfigurations, sameConnectedProfile } from "./configuration.mjs";
|
|
13
14
|
import { Cause, DateTime, Effect, Layer, Redacted, Schema } from "effect";
|
|
@@ -162,12 +163,14 @@ const makeConnectedProtocolWithCompatibility = Effect.fn("makeOpenIdClientConnec
|
|
|
162
163
|
const now = DateTime.toEpochMillis(yield* DateTime.now) / 1e3;
|
|
163
164
|
const audience = typeof claims.aud === "string" ? claims.aud : claims.aud[0];
|
|
164
165
|
if (claims.iss !== provider.issuer || audience !== provider.clientId || claims.azp !== void 0 && claims.azp !== provider.clientId || claims.exp <= now || claims.iat > now || claims.nbf !== void 0 && claims.nbf > now || claims.auth_time !== void 0 && claims.auth_time > now || (previous ? claims.sub !== previous.identity.subject || claims.nonce !== void 0 && claims.nonce !== Redacted.value(originalNonce) || claims.auth_time !== void 0 && claims.auth_time !== previous.continuation.authTime : claims.nonce !== Redacted.value(originalNonce) || provider.maxAgeSeconds !== void 0 && (claims.auth_time === void 0 || claims.auth_time + provider.maxAgeSeconds < Math.floor(now)))) return yield* unavailable();
|
|
166
|
+
const profile = yield* decodeOidcProfile(raw).pipe(Effect.mapError(unavailable));
|
|
165
167
|
return {
|
|
166
168
|
identity: {
|
|
167
169
|
provider: provider.provider,
|
|
168
170
|
issuer: provider.issuer,
|
|
169
171
|
subject: claims.sub
|
|
170
172
|
},
|
|
173
|
+
...profile === void 0 ? {} : { profile },
|
|
171
174
|
continuation: previous?.continuation ?? {
|
|
172
175
|
_tag: "Oidc",
|
|
173
176
|
clientId: provider.clientId,
|