@yielded/auth 0.1.0-beta.1 → 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/DrizzleLibsql.d.mts +8 -8
- package/dist/DrizzleMysql2.d.mts +6 -6
- package/dist/DrizzlePglite.d.mts +6 -6
- package/dist/DrizzleSqliteDo.d.mts +8 -8
- package/dist/DrizzleSqliteNode.d.mts +6 -6
- package/dist/GitHub.d.mts +2 -2
- package/dist/GitHub.mjs +2 -2
- package/dist/OpenIdClientConnected.d.mts +1 -1
- package/dist/oauth/github/protocol.d.mts +7 -3
- package/dist/oauth/github/protocol.mjs +22 -9
- package/dist/oauth/github/protocol.mjs.map +1 -1
- package/dist/oauth/openid-client/compatibility.d.mts +22 -1
- package/dist/oauth/openid-client/compatibility.mjs +6 -1
- package/dist/oauth/openid-client/compatibility.mjs.map +1 -1
- package/dist/oauth/openid-client/configuration.mjs +2 -0
- package/dist/oauth/openid-client/configuration.mjs.map +1 -1
- package/dist/oauth/openid-client/connected/protocol.d.mts +1 -1
- package/dist/oauth/openid-client/models.d.mts +3 -0
- package/dist/oauth/openid-client/models.mjs.map +1 -1
- package/dist/oauth/openid-client/protocol.d.mts +0 -1
- package/dist/oauth/openid-client/protocol.mjs +7 -7
- package/dist/oauth/openid-client/protocol.mjs.map +1 -1
- package/package.json +1 -1
- package/src/GitHub.ts +1 -0
- package/src/oauth/github/protocol.ts +27 -8
- package/src/oauth/openid-client/compatibility.ts +13 -0
- package/src/oauth/openid-client/configuration.ts +2 -0
- package/src/oauth/openid-client/models.ts +3 -0
- package/src/oauth/openid-client/protocol.ts +6 -22
package/README.md
CHANGED
|
@@ -14,5 +14,5 @@ caller’s Scope; credentials stay outside public results and telemetry.
|
|
|
14
14
|
Optional database, platform, browser, and OAuth adapters have separate exports.
|
|
15
15
|
The root import does not load their peer dependencies. Effect is supplied by the host.
|
|
16
16
|
|
|
17
|
-
See the [authentication guide](https://github.com/
|
|
18
|
-
and [consumer examples](https://github.com/
|
|
17
|
+
See the [authentication guide](https://github.com/yielded-dev/auth/blob/main/docs/guide/authentication.md)
|
|
18
|
+
and [consumer examples](https://github.com/yielded-dev/auth/tree/main/examples/auth).
|
package/dist/DrizzleLibsql.d.mts
CHANGED
|
@@ -699,11 +699,9 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
699
699
|
readonly invalidation: SessionInvalidationWindow;
|
|
700
700
|
readonly nowMillis: number;
|
|
701
701
|
}, prepare: PrepareOAuthCommit<{
|
|
702
|
-
readonly _tag: "Ambiguous";
|
|
703
|
-
} | {
|
|
704
702
|
readonly _tag: "Rejected";
|
|
705
703
|
} | {
|
|
706
|
-
readonly _tag: "
|
|
704
|
+
readonly _tag: "Ambiguous";
|
|
707
705
|
} | {
|
|
708
706
|
readonly _tag: "Cancelled";
|
|
709
707
|
} | {
|
|
@@ -727,6 +725,8 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
727
725
|
};
|
|
728
726
|
};
|
|
729
727
|
readonly changed: boolean;
|
|
728
|
+
} | {
|
|
729
|
+
readonly _tag: "Conflict";
|
|
730
730
|
}, A>) => Effect.Effect<PreparedCommit<A>, OAuthUnavailable>;
|
|
731
731
|
readonly inspectUnlink: (input: {
|
|
732
732
|
readonly moduleId: string & import("effect/Brand").Brand<"effect-auth/OAuthModuleId">;
|
|
@@ -1281,14 +1281,14 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
1281
1281
|
};
|
|
1282
1282
|
}) => Effect.Effect<{
|
|
1283
1283
|
readonly _tag: "Rejected";
|
|
1284
|
+
} | {
|
|
1285
|
+
readonly _tag: "Conflict";
|
|
1284
1286
|
} | {
|
|
1285
1287
|
readonly _tag: "Target";
|
|
1286
1288
|
readonly cohortGeneration: string & import("effect/Brand").Brand<"effect-auth/SecurityRevision">;
|
|
1287
1289
|
} | {
|
|
1288
1290
|
readonly _tag: "Quarantine";
|
|
1289
1291
|
readonly cohortGeneration: string & import("effect/Brand").Brand<"effect-auth/SecurityRevision">;
|
|
1290
|
-
} | {
|
|
1291
|
-
readonly _tag: "Conflict";
|
|
1292
1292
|
}, OAuthUnavailable>;
|
|
1293
1293
|
readonly settle: <A>(input: {
|
|
1294
1294
|
readonly claim: OAuthConnectedClaim;
|
|
@@ -1296,13 +1296,13 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
1296
1296
|
readonly authorization: OAuthConnectedActionAuthorization;
|
|
1297
1297
|
readonly nowMillis: number;
|
|
1298
1298
|
}, prepare: PrepareOAuthCommit<{
|
|
1299
|
-
readonly _tag: "Ambiguous";
|
|
1300
|
-
} | {
|
|
1301
1299
|
readonly _tag: "Rejected";
|
|
1302
1300
|
} | {
|
|
1303
|
-
readonly _tag: "
|
|
1301
|
+
readonly _tag: "Ambiguous";
|
|
1304
1302
|
} | {
|
|
1305
1303
|
readonly _tag: "Cancelled";
|
|
1304
|
+
} | {
|
|
1305
|
+
readonly _tag: "Conflict";
|
|
1306
1306
|
} | {
|
|
1307
1307
|
readonly _tag: "Connected";
|
|
1308
1308
|
readonly grant: {
|
package/dist/DrizzleMysql2.d.mts
CHANGED
|
@@ -221,12 +221,12 @@ declare const makeOAuthAccountsServices: <S extends AnyMySqlTable<{
|
|
|
221
221
|
readonly nowMillis: number;
|
|
222
222
|
}, prepare: PrepareOAuthCommit<{
|
|
223
223
|
readonly _tag: "Rejected";
|
|
224
|
+
} | {
|
|
225
|
+
readonly _tag: "Ambiguous";
|
|
224
226
|
} | {
|
|
225
227
|
readonly _tag: "Conflict";
|
|
226
228
|
} | {
|
|
227
229
|
readonly _tag: "Cancelled";
|
|
228
|
-
} | {
|
|
229
|
-
readonly _tag: "Ambiguous";
|
|
230
230
|
} | {
|
|
231
231
|
readonly _tag: "Linked";
|
|
232
232
|
readonly credential: {
|
|
@@ -592,6 +592,8 @@ declare const makeOAuthAccountsServices: <S extends AnyMySqlTable<{
|
|
|
592
592
|
readonly flow: OAuthConnectedPendingFlow;
|
|
593
593
|
readonly authorization: OAuthConnectedActionAuthorization;
|
|
594
594
|
}, prepare: PrepareOAuthCommit<{
|
|
595
|
+
readonly _tag: "Rejected";
|
|
596
|
+
} | {
|
|
595
597
|
readonly _tag: "Issued";
|
|
596
598
|
readonly flow: {
|
|
597
599
|
readonly context: {
|
|
@@ -683,8 +685,6 @@ declare const makeOAuthAccountsServices: <S extends AnyMySqlTable<{
|
|
|
683
685
|
};
|
|
684
686
|
readonly retentionUntilMillis: number;
|
|
685
687
|
};
|
|
686
|
-
} | {
|
|
687
|
-
readonly _tag: "Rejected";
|
|
688
688
|
}, A>) => import("effect/Effect").Effect<PreparedCommit<A>, OAuthUnavailable, never>;
|
|
689
689
|
readonly preflight: (input: OAuthConnectedAccess) => import("effect/Effect").Effect<OAuthConnectedPendingFlow | undefined, OAuthUnavailable>;
|
|
690
690
|
readonly claim: <A>(input: {
|
|
@@ -818,12 +818,12 @@ declare const makeOAuthAccountsServices: <S extends AnyMySqlTable<{
|
|
|
818
818
|
readonly nowMillis: number;
|
|
819
819
|
}, prepare: PrepareOAuthCommit<{
|
|
820
820
|
readonly _tag: "Rejected";
|
|
821
|
+
} | {
|
|
822
|
+
readonly _tag: "Ambiguous";
|
|
821
823
|
} | {
|
|
822
824
|
readonly _tag: "Conflict";
|
|
823
825
|
} | {
|
|
824
826
|
readonly _tag: "Cancelled";
|
|
825
|
-
} | {
|
|
826
|
-
readonly _tag: "Ambiguous";
|
|
827
827
|
} | {
|
|
828
828
|
readonly _tag: "Connected";
|
|
829
829
|
readonly grant: {
|
package/dist/DrizzlePglite.d.mts
CHANGED
|
@@ -220,12 +220,12 @@ declare const makeOAuthAccountsServices: <S extends AnyPgTable<{
|
|
|
220
220
|
readonly nowMillis: number;
|
|
221
221
|
}, prepare: PrepareOAuthCommit<{
|
|
222
222
|
readonly _tag: "Rejected";
|
|
223
|
+
} | {
|
|
224
|
+
readonly _tag: "Ambiguous";
|
|
223
225
|
} | {
|
|
224
226
|
readonly _tag: "Conflict";
|
|
225
227
|
} | {
|
|
226
228
|
readonly _tag: "Cancelled";
|
|
227
|
-
} | {
|
|
228
|
-
readonly _tag: "Ambiguous";
|
|
229
229
|
} | {
|
|
230
230
|
readonly _tag: "Linked";
|
|
231
231
|
readonly credential: {
|
|
@@ -591,6 +591,8 @@ declare const makeOAuthAccountsServices: <S extends AnyPgTable<{
|
|
|
591
591
|
readonly flow: OAuthConnectedPendingFlow;
|
|
592
592
|
readonly authorization: OAuthConnectedActionAuthorization;
|
|
593
593
|
}, prepare: PrepareOAuthCommit<{
|
|
594
|
+
readonly _tag: "Rejected";
|
|
595
|
+
} | {
|
|
594
596
|
readonly _tag: "Issued";
|
|
595
597
|
readonly flow: {
|
|
596
598
|
readonly context: {
|
|
@@ -682,8 +684,6 @@ declare const makeOAuthAccountsServices: <S extends AnyPgTable<{
|
|
|
682
684
|
};
|
|
683
685
|
readonly retentionUntilMillis: number;
|
|
684
686
|
};
|
|
685
|
-
} | {
|
|
686
|
-
readonly _tag: "Rejected";
|
|
687
687
|
}, A>) => import("effect/Effect").Effect<PreparedCommit<A>, OAuthUnavailable, never>;
|
|
688
688
|
readonly preflight: (input: OAuthConnectedAccess) => import("effect/Effect").Effect<OAuthConnectedPendingFlow | undefined, OAuthUnavailable>;
|
|
689
689
|
readonly claim: <A>(input: {
|
|
@@ -817,12 +817,12 @@ declare const makeOAuthAccountsServices: <S extends AnyPgTable<{
|
|
|
817
817
|
readonly nowMillis: number;
|
|
818
818
|
}, prepare: PrepareOAuthCommit<{
|
|
819
819
|
readonly _tag: "Rejected";
|
|
820
|
+
} | {
|
|
821
|
+
readonly _tag: "Ambiguous";
|
|
820
822
|
} | {
|
|
821
823
|
readonly _tag: "Conflict";
|
|
822
824
|
} | {
|
|
823
825
|
readonly _tag: "Cancelled";
|
|
824
|
-
} | {
|
|
825
|
-
readonly _tag: "Ambiguous";
|
|
826
826
|
} | {
|
|
827
827
|
readonly _tag: "Connected";
|
|
828
828
|
readonly grant: {
|
|
@@ -754,11 +754,9 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
754
754
|
readonly invalidation: SessionInvalidationWindow;
|
|
755
755
|
readonly nowMillis: number;
|
|
756
756
|
}, prepare: PrepareOAuthCommit<{
|
|
757
|
-
readonly _tag: "Ambiguous";
|
|
758
|
-
} | {
|
|
759
757
|
readonly _tag: "Rejected";
|
|
760
758
|
} | {
|
|
761
|
-
readonly _tag: "
|
|
759
|
+
readonly _tag: "Ambiguous";
|
|
762
760
|
} | {
|
|
763
761
|
readonly _tag: "Cancelled";
|
|
764
762
|
} | {
|
|
@@ -782,6 +780,8 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
782
780
|
};
|
|
783
781
|
};
|
|
784
782
|
readonly changed: boolean;
|
|
783
|
+
} | {
|
|
784
|
+
readonly _tag: "Conflict";
|
|
785
785
|
}, A>) => Effect.Effect<PreparedCommit<A>, OAuthUnavailable>;
|
|
786
786
|
readonly inspectUnlink: (input: {
|
|
787
787
|
readonly moduleId: string & import("effect/Brand").Brand<"effect-auth/OAuthModuleId">;
|
|
@@ -1336,14 +1336,14 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
1336
1336
|
};
|
|
1337
1337
|
}) => Effect.Effect<{
|
|
1338
1338
|
readonly _tag: "Rejected";
|
|
1339
|
+
} | {
|
|
1340
|
+
readonly _tag: "Conflict";
|
|
1339
1341
|
} | {
|
|
1340
1342
|
readonly _tag: "Target";
|
|
1341
1343
|
readonly cohortGeneration: string & import("effect/Brand").Brand<"effect-auth/SecurityRevision">;
|
|
1342
1344
|
} | {
|
|
1343
1345
|
readonly _tag: "Quarantine";
|
|
1344
1346
|
readonly cohortGeneration: string & import("effect/Brand").Brand<"effect-auth/SecurityRevision">;
|
|
1345
|
-
} | {
|
|
1346
|
-
readonly _tag: "Conflict";
|
|
1347
1347
|
}, OAuthUnavailable>;
|
|
1348
1348
|
readonly settle: <A>(input: {
|
|
1349
1349
|
readonly claim: OAuthConnectedClaim;
|
|
@@ -1351,13 +1351,13 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
1351
1351
|
readonly authorization: OAuthConnectedActionAuthorization;
|
|
1352
1352
|
readonly nowMillis: number;
|
|
1353
1353
|
}, prepare: PrepareOAuthCommit<{
|
|
1354
|
-
readonly _tag: "Ambiguous";
|
|
1355
|
-
} | {
|
|
1356
1354
|
readonly _tag: "Rejected";
|
|
1357
1355
|
} | {
|
|
1358
|
-
readonly _tag: "
|
|
1356
|
+
readonly _tag: "Ambiguous";
|
|
1359
1357
|
} | {
|
|
1360
1358
|
readonly _tag: "Cancelled";
|
|
1359
|
+
} | {
|
|
1360
|
+
readonly _tag: "Conflict";
|
|
1361
1361
|
} | {
|
|
1362
1362
|
readonly _tag: "Connected";
|
|
1363
1363
|
readonly grant: {
|
|
@@ -699,12 +699,12 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
699
699
|
readonly nowMillis: number;
|
|
700
700
|
}, prepare: PrepareOAuthCommit<{
|
|
701
701
|
readonly _tag: "Rejected";
|
|
702
|
+
} | {
|
|
703
|
+
readonly _tag: "Ambiguous";
|
|
702
704
|
} | {
|
|
703
705
|
readonly _tag: "Conflict";
|
|
704
706
|
} | {
|
|
705
707
|
readonly _tag: "Cancelled";
|
|
706
|
-
} | {
|
|
707
|
-
readonly _tag: "Ambiguous";
|
|
708
708
|
} | {
|
|
709
709
|
readonly _tag: "Linked";
|
|
710
710
|
readonly credential: {
|
|
@@ -1070,6 +1070,8 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
1070
1070
|
readonly flow: OAuthConnectedPendingFlow;
|
|
1071
1071
|
readonly authorization: OAuthConnectedActionAuthorization;
|
|
1072
1072
|
}, prepare: PrepareOAuthCommit<{
|
|
1073
|
+
readonly _tag: "Rejected";
|
|
1074
|
+
} | {
|
|
1073
1075
|
readonly _tag: "Issued";
|
|
1074
1076
|
readonly flow: {
|
|
1075
1077
|
readonly context: {
|
|
@@ -1161,8 +1163,6 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
1161
1163
|
};
|
|
1162
1164
|
readonly retentionUntilMillis: number;
|
|
1163
1165
|
};
|
|
1164
|
-
} | {
|
|
1165
|
-
readonly _tag: "Rejected";
|
|
1166
1166
|
}, A>) => import("effect/Effect").Effect<PreparedCommit<A>, OAuthUnavailable, never>;
|
|
1167
1167
|
readonly preflight: (input: OAuthConnectedAccess) => import("effect/Effect").Effect<OAuthConnectedPendingFlow | undefined, OAuthUnavailable>;
|
|
1168
1168
|
readonly claim: <A>(input: {
|
|
@@ -1296,12 +1296,12 @@ declare const makeOAuthAccountsServices: <S extends AnySQLiteTable<{
|
|
|
1296
1296
|
readonly nowMillis: number;
|
|
1297
1297
|
}, prepare: PrepareOAuthCommit<{
|
|
1298
1298
|
readonly _tag: "Rejected";
|
|
1299
|
+
} | {
|
|
1300
|
+
readonly _tag: "Ambiguous";
|
|
1299
1301
|
} | {
|
|
1300
1302
|
readonly _tag: "Conflict";
|
|
1301
1303
|
} | {
|
|
1302
1304
|
readonly _tag: "Cancelled";
|
|
1303
|
-
} | {
|
|
1304
|
-
readonly _tag: "Ambiguous";
|
|
1305
1305
|
} | {
|
|
1306
1306
|
readonly _tag: "Connected";
|
|
1307
1307
|
readonly grant: {
|
package/dist/GitHub.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OpenIdClientConfigurationError } from "./oauth/openid-client/models.mjs";
|
|
2
2
|
import { GitHubOAuthAppConnectedProtocolOptions, GitHubOAuthAppGeneration, GitHubOAuthAppProtocolOptions } from "./oauth/github/models.mjs";
|
|
3
|
-
import { gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol } from "./oauth/github/protocol.mjs";
|
|
3
|
+
import { gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, gitHubOAuthAppProvider, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol } from "./oauth/github/protocol.mjs";
|
|
4
4
|
import { gitHubOAuthAppProviderKey } from "./oauth/github/identity.mjs";
|
|
5
|
-
export { type GitHubOAuthAppConnectedProtocolOptions, type GitHubOAuthAppGeneration, type GitHubOAuthAppProtocolOptions, OpenIdClientConfigurationError, gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, gitHubOAuthAppProviderKey, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol };
|
|
5
|
+
export { type GitHubOAuthAppConnectedProtocolOptions, type GitHubOAuthAppGeneration, type GitHubOAuthAppProtocolOptions, OpenIdClientConfigurationError, gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, gitHubOAuthAppProvider, gitHubOAuthAppProviderKey, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol };
|
package/dist/GitHub.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { OpenIdClientConfigurationError } from "./oauth/openid-client/models.mjs";
|
|
2
2
|
import { gitHubOAuthAppProviderKey } from "./oauth/github/identity.mjs";
|
|
3
|
-
import { gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol } from "./oauth/github/protocol.mjs";
|
|
4
|
-
export { OpenIdClientConfigurationError, gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, gitHubOAuthAppProviderKey, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol };
|
|
3
|
+
import { gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, gitHubOAuthAppProvider, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol } from "./oauth/github/protocol.mjs";
|
|
4
|
+
export { OpenIdClientConfigurationError, gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, gitHubOAuthAppProvider, gitHubOAuthAppProviderKey, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OpenIdClientAuthentication, OpenIdClientConfigurationError, PlainOAuthIdentity } from "./oauth/openid-client/models.mjs";
|
|
2
1
|
import { OpenIdClientConnectedOAuthProvider, OpenIdClientConnectedOidcProvider, OpenIdClientConnectedProtocolOptions, OpenIdClientConnectedRefreshExpiry, OpenIdClientConnectedRevocation } from "./oauth/openid-client/connected/models.mjs";
|
|
2
|
+
import { OpenIdClientAuthentication, OpenIdClientConfigurationError, PlainOAuthIdentity } from "./oauth/openid-client/models.mjs";
|
|
3
3
|
import { makeOpenIdClientConnectedProtocol, openIdClientConnectedProtocolLayer } from "./oauth/openid-client/connected/protocol.mjs";
|
|
4
4
|
export { type OpenIdClientAuthentication, OpenIdClientConfigurationError, type OpenIdClientConnectedOAuthProvider, type OpenIdClientConnectedOidcProvider, type OpenIdClientConnectedProtocolOptions, type OpenIdClientConnectedRefreshExpiry, type OpenIdClientConnectedRevocation, type PlainOAuthIdentity, makeOpenIdClientConnectedProtocol, openIdClientConnectedProtocolLayer };
|
|
@@ -6,10 +6,14 @@ import { OAuthCallbackId, OAuthCodeResponse, OAuthProtocolConfiguration, OAuthPr
|
|
|
6
6
|
import { OAuthConnectedConfiguration, OAuthConnectedGrantResponse, OAuthConnectedProfile, OAuthConnectedTokenContext, OAuthConnectedTokenMaterial } from "../connectedModels.mjs";
|
|
7
7
|
import { OAuthConnectedProtocol } from "../OAuthConnectedProtocol.mjs";
|
|
8
8
|
import { OAuthProtocol } from "../OAuthProtocol.mjs";
|
|
9
|
-
import { OpenIdClientConfigurationError } from "../openid-client/models.mjs";
|
|
10
|
-
import { GitHubOAuthAppConnectedProtocolOptions, GitHubOAuthAppProtocolOptions } from "./models.mjs";
|
|
9
|
+
import { OpenIdClientConfigurationError, OpenIdClientOAuthProvider } from "../openid-client/models.mjs";
|
|
10
|
+
import { GitHubOAuthAppConnectedProtocolOptions, GitHubOAuthAppGeneration, GitHubOAuthAppProtocolOptions } from "./models.mjs";
|
|
11
11
|
import { Effect, Layer } from "effect";
|
|
12
12
|
//#region src/oauth/github/protocol.d.ts
|
|
13
|
+
/** A GitHub.com OAuth App generation for the same provider list as generic OIDC.
|
|
14
|
+
* Retains GitHub receipt/error rules and requests read:user, with no repository access.
|
|
15
|
+
* Construction performs no I/O; invalid configuration throws the typed configuration error. */
|
|
16
|
+
declare const gitHubOAuthAppProvider: (registration: GitHubOAuthAppGeneration) => OpenIdClientOAuthProvider;
|
|
13
17
|
declare const makeGitHubOAuthAppProtocol: (options: GitHubOAuthAppProtocolOptions) => Effect.Effect<{
|
|
14
18
|
readonly prepareAuthorization: (input: {
|
|
15
19
|
readonly provider: OAuthProviderKey;
|
|
@@ -50,5 +54,5 @@ declare const makeGitHubOAuthAppConnectedProtocol: (options: GitHubOAuthAppConne
|
|
|
50
54
|
declare const gitHubOAuthAppProtocolLayer: (options: GitHubOAuthAppProtocolOptions) => Layer.Layer<OAuthProtocol, OAuthUnavailable | OpenIdClientConfigurationError, never>;
|
|
51
55
|
declare const gitHubOAuthAppConnectedProtocolLayer: (options: GitHubOAuthAppConnectedProtocolOptions) => Layer.Layer<OAuthConnectedProtocol, OAuthUnavailable | OpenIdClientConfigurationError, never>;
|
|
52
56
|
//#endregion
|
|
53
|
-
export { gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol };
|
|
57
|
+
export { gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, gitHubOAuthAppProvider, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol };
|
|
54
58
|
//# sourceMappingURL=protocol.d.mts.map
|
|
@@ -5,9 +5,9 @@ import { OAuthConnectedProfile } from "../connectedModels.mjs";
|
|
|
5
5
|
import { OAuthConnectedProtocol } from "../OAuthConnectedProtocol.mjs";
|
|
6
6
|
import { OAuthProtocol } from "../OAuthProtocol.mjs";
|
|
7
7
|
import { OpenIdClientConfigurationError } from "../openid-client/models.mjs";
|
|
8
|
-
import { DefiniteTokenRejection } from "../openid-client/compatibility.mjs";
|
|
8
|
+
import { DefiniteTokenRejection, tokenCompatibility } from "../openid-client/compatibility.mjs";
|
|
9
9
|
import { boundedFetch } from "../openid-client/transport.mjs";
|
|
10
|
-
import {
|
|
10
|
+
import { makeOpenIdClientOAuthProtocol } from "../openid-client/protocol.mjs";
|
|
11
11
|
import { ProviderRevocation } from "../openid-client/ProviderRevocation.mjs";
|
|
12
12
|
import { makeConnectedProtocolWithCompatibility } from "../openid-client/connected/protocol.mjs";
|
|
13
13
|
import { decodeGitHubIdentity, gitHubOAuthAppProviderKey } from "./identity.mjs";
|
|
@@ -166,16 +166,29 @@ const revocationLayer = (options) => {
|
|
|
166
166
|
});
|
|
167
167
|
}) }));
|
|
168
168
|
};
|
|
169
|
+
/** A GitHub.com OAuth App generation for the same provider list as generic OIDC.
|
|
170
|
+
* Retains GitHub receipt/error rules and requests read:user, with no repository access.
|
|
171
|
+
* Construction performs no I/O; invalid configuration throws the typed configuration error. */
|
|
172
|
+
const gitHubOAuthAppProvider = (registration) => {
|
|
173
|
+
let saved;
|
|
174
|
+
try {
|
|
175
|
+
saved = snapshotOAuthSync(generation, registration);
|
|
176
|
+
} catch {
|
|
177
|
+
throw invalid();
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
...provider(saved),
|
|
181
|
+
scopes: ["read:user"],
|
|
182
|
+
[tokenCompatibility]: compatibility
|
|
183
|
+
};
|
|
184
|
+
};
|
|
169
185
|
const makeGitHubOAuthAppProtocol = Effect.fn("makeGitHubOAuthAppProtocol")(function* (options) {
|
|
170
186
|
const saved = yield* capture(generations, options.registrations, options);
|
|
171
187
|
if (saved.registrations.filter((item) => item.issuance === "active").length !== 1) return yield* invalid();
|
|
172
|
-
return yield*
|
|
188
|
+
return yield* makeOpenIdClientOAuthProtocol({
|
|
173
189
|
...saved,
|
|
174
|
-
providers: saved.registrations.map(
|
|
175
|
-
|
|
176
|
-
scopes: ["read:user"]
|
|
177
|
-
}))
|
|
178
|
-
}, compatibility);
|
|
190
|
+
providers: saved.registrations.map(gitHubOAuthAppProvider)
|
|
191
|
+
});
|
|
179
192
|
});
|
|
180
193
|
const makeGitHubOAuthAppConnectedProtocol = Effect.fn("makeGitHubOAuthAppConnectedProtocol")(function* (options) {
|
|
181
194
|
const saved = yield* capture(connectedGenerations, options.registrations, options);
|
|
@@ -199,6 +212,6 @@ const makeGitHubOAuthAppConnectedProtocol = Effect.fn("makeGitHubOAuthAppConnect
|
|
|
199
212
|
const gitHubOAuthAppProtocolLayer = (options) => Layer.effect(OAuthProtocol, makeGitHubOAuthAppProtocol(options));
|
|
200
213
|
const gitHubOAuthAppConnectedProtocolLayer = (options) => Layer.effect(OAuthConnectedProtocol, makeGitHubOAuthAppConnectedProtocol(options));
|
|
201
214
|
//#endregion
|
|
202
|
-
export { gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol };
|
|
215
|
+
export { gitHubOAuthAppConnectedProtocolLayer, gitHubOAuthAppProtocolLayer, gitHubOAuthAppProvider, makeGitHubOAuthAppConnectedProtocol, makeGitHubOAuthAppProtocol };
|
|
203
216
|
|
|
204
217
|
//# sourceMappingURL=protocol.mjs.map
|
|
@@ -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 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 { makeOAuthProtocolWithCompatibility } 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\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* makeOAuthProtocolWithCompatibility(\n {\n ...saved,\n providers: saved.registrations.map((item) => ({ ...provider(item), scopes: [\"read:user\"] })),\n },\n compatibility,\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\" });\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":";;;;;;;;;;;;;;;AA6BA,MAAM,oBAAoB,iBAAiB,KAAK,CAAC,CAAC;AAClD,MAAM,gBAAgB,+BAA+B,KAAK,EAAE,QAAQ,WAAW,CAAC;AAChF,MAAM,SAAS,YAAY,KAAK,oBAAoB;AAEpD,MAAM,UAAU,OAAO,OAAO;CAC5B,QAAQ;CACR,cAAc;CACd,wBAAwB;AAC1B,CAAC;AAED,MAAM,aAAa,OAAO,OAAO;CAC/B,yBAAyB;CACzB,UAAU,OAAO,SAAS,CAAC,UAAU,SAAS,CAAC;CAC/C,UAAU,OAAO,OAAO,MAAM,OAAO,UAAU,yBAAyB,CAAC;CACzE,cAAc,OAAO,kBAAkB,OAAO,eAAe,MAAM,OAAO,YAAY,IAAI,CAAC,CAAC;CAC5F,WAAW,OAAO,MAChB,OAAO,OAAO;EAAE,YAAY;EAAiB,aAAa;CAAiB,CAAC,CAC9E,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,GAAG,OAAO,YAAY,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,cAAc,OAAO,MAAM,UAAU,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,GAAG,OAAO,YAAY,EAAE,CAAC;AAEhG,MAAM,uBAAuB,OAAO,MAClC,OAAO,OAAO;CACZ,GAAG,WAAW;CACd,UAAU,OAAO,MAAM,qBAAqB,CAAC,CAAC,MAC5C,OAAO,YAAY,CAAC,GACpB,OAAO,YAAY,EAAE,CACvB;AACF,CAAC,CACH,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,GAAG,OAAO,YAAY,EAAE,CAAC;AAErD,MAAM,UAAU,OAAO,OAAO,MAAM,OAAO,UAAU;CAAE,SAAS;CAAG,SAAS;AAAG,CAAC,CAAC;AACjF,MAAM,YAAY,OAAO,GAAG,OAAO;AAEnC,MAAM,WACJ,QACA,eACA,YAKA,OAAO,IAAI;CACT,WAAW;EACT,MAAM,SAAS,kBAAkB,QAAQ,aAAa;EACtD,MAAM,QAAQ,QAAQ;EACtB,MAAM,iBAAiB,QAAQ;EAE/B,IAAI,CAAC,UAAU,cAAc,KAAM,UAAU,KAAA,KAAa,CAAC,UAAU,WAAW,KAAK,GACnF,MAAM,QAAQ;EAEhB,OAAO;GAAE,eAAe;GAAQ;GAAgB,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;EAAG;CAC5F;CACA,OAAO;AACT,CAAC;AAEH,MAAM,YACJ,kBAC+C;CAC/C,UAAU;CACV,yBAAyB,aAAa;CACtC,UAAU,aAAa;CACvB;CACA,UAAU;CACV,oBAAoB;CACpB,UAAU,aAAa;CACvB,gBAAgB;EAAE,QAAQ;EAAsB,QAAQ,aAAa;CAAa;CAClF,WAAW,aAAa;CACxB,uBAAuB;CACvB,eAAe;CACf,UAAU;CACV,gBAAgB;EACd,KAAK;EACL;EACA,gBAAgB;CAClB;AACF;AAEA,MAAM,UAAU,OAAO,OAAO,MAAM,OAAO,UAAU,yBAAyB,CAAC;AAC/E,MAAM,SAAS,OAAO,GAAG,OAAO;;AAGhC,MAAM,UACJ,SACA,aAC0B;CAC1B,IAAI,YAAY,KAAA,KAAa,QAAQ,SAAS,OAAO,MAAM,YAAY;CAEvE,MAAM,SACJ,YAAY,KAAK,CAAC,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,KAAK,SAAS,KAAK,QAAQ,oBAAoB,EAAE,CAAC;CAE7F,IACE,OAAO,SAAS,MAChB,OAAO,MAAM,SAAS,CAAC,OAAO,IAAI,CAAC,KACnC,IAAI,IAAI,MAAM,CAAC,CAAC,SAAS,OAAO,UAChC,OAAO,WAAW,SAAS,UAC3B,OAAO,MAAM,SAAS,CAAC,SAAS,SAAS,IAAI,CAAC,GAE9C,MAAM,YAAY;CAEpB,OAAO;AACT;AAEA,MAAM,QAAQ,OAAO,eAAe,MAAM,OAAO,YAAY,KAAK,CAAC;AACnE,MAAM,SAAS,OAAO,OAAO,MAAM,OAAO,cAAc,CAAC,CAAC;AAE1D,MAAM,gBAAgB,OAAO,OAAO;CAClC,cAAc;CACd,YAAY,OAAO,OAAO,MAAM,OAAO,UAAU,4BAA4B,CAAC;CAC9E,OAAO,OAAO,OAAO,MAAM,OAAO,YAAY,KAAK,CAAC;CACpD,YAAY,OAAO,YAAY,MAAM;CACrC,eAAe,OAAO,YAAY,KAAK;CACvC,0BAA0B,OAAO,YAAY,MAAM;AACrD,CAAC;AAGD,MAAM,gBAAgB,OAAO,kBAAkB,aAAa;AAE5D,MAAM,mBAAmB,OAAO,WAC9B,OAAO,eAAe,OAAO,OAAO,EAAE,cAAc,MAAM,CAAC,CAAC,CAC9D;AAEA,MAAM,kBAAkB,OAAO,OAAO;CACpC,OAAO,OAAO,eAAe,MAAM,OAAO,YAAY,GAAG,CAAC;CAC1D,mBAAmB,OAAO,YAAY,OAAO,OAAO,MAAM,OAAO,YAAY,IAAI,CAAC,CAAC;CACnF,WAAW,OAAO,YAAY,OAAO,OAAO,MAAM,OAAO,YAAY,IAAI,CAAC,CAAC;AAC7E,CAAC;AAGD,MAAM,wBAAwB,OAAO,kBAAkB,eAAe;AAEtE,MAAM,cAAc;CAClB;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,gBAAwC,OAAO,OAA+B;CAClF,iBAAiB,EAAE,MAAM,QAAQ,eAAe,UAAU;EACxD,IAAI,aAAa,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,YAAY,MAAM,oBAC1D,MAAM,YAAY;EACpB,IAAI,CAAC,UAAU,SAAS,IAAI,GAAG,MAAM,YAAY;EACjD,IAAI,OAAO,OAAO,MAAM,OAAO,GAAG;GAChC,IAAI,YAAY,MAAM,QAAQ,OAAO,OAAO,MAAM,GAAG,CAAC,GAAG,MAAM,YAAY;GAC3E,MAAM,WAAW,sBAAsB,IAAI;GAE3C,KACG,WAAW,OAAO,WAAW,QAC9B,SAAS,WACN,MAAM,cAAc,uBAAuB,0BAA0B,sBAExE,MAAM,IAAI,uBAAuB;GAEnC,MAAM,YAAY;EACpB;EACA,IACE,WAAW,OACX;GAAC;GAAqB;GAAa;EAAU,CAAC,CAAC,MAAM,QAAQ,OAAO,OAAO,MAAM,GAAG,CAAC,GAErF,MAAM,YAAY;EACpB,MAAM,UAAU,cAAc,IAAI;EAElC,OAAO,QAAQ,OAAO,MAAM,MAAM;EAClC,IACE,MAAM,oBACL,QAAQ,kBAAkB,KAAA,KACzB,QAAQ,eAAe,KAAA,KACvB,QAAQ,6BAA6B,KAAA,IAEvC,MAAM,YAAY;CACtB;CACA,sBAAsB,aAAa,YACjC,UAAU,CAAC,GAAG,aAAa,gBAAgB,IAAI;CACjD,cAAc;CACd,qBAAqB;AACvB,CAAC;AAED,MAAM,mBACJ,YACG;CACH,MAAM,QACJ,QAAQ,WACN,KAAK,SACL,WAAW,MAAM,KAAK;EACpB,GAAG;EACH,MAAM,KAAK,gBAAgB,aAAa,IAAI,WAAW,KAAK,IAAI,IAAI,KAAK;CAC3E,CAAC;CAEL,MAAM,iBAAiB,QAAQ;CAE/B,OAAO,MAAM,QACX,oBACA,mBAAmB,GAAG,EACpB,QAAQ,OAAO,GAAG,uBAAuB,CAAC,CAAC,WAAW,OAAO;EAC3D,OAAO,OAAO,WAAW;GACvB,KAAK,OAAO,iBAAiB;IAC3B,IACE,MAAM,eAAe,WAAW,wBAChC,MAAM,QAAQ,cAAc,QAAQ,yBAAyB,MAAM,YACnE,MAAM,QAAQ,SAAS,aAAa,6BACpC,MAAM,QAAQ,SAAS,WAAW,QAElC,MAAM,YAAY;IACpB,MAAM,MAAM,uCAAuC,mBAAmB,MAAM,QAAQ,EAAE;IAEtF,MAAM,SAAS,YAAY,IAAI,CAC7B,cACA,YAAY,QAAQ,KAAK,KAAK,iBAAiB,GAAI,CAAC,CACtD,CAAC;IAID,MAAM,WAAW,MAFC,aAAa,OAAO,wBAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,CAE5B,CAAC,CAAC,KAAK;KACpC,QAAQ;KACR,UAAU;KACV,SAAS;MACP,GAAG;MACH,gBAAgB;MAChB,eAAe,SAAS,SAAS,aAAa,GAAG,MAAM,SAAS,GAAG,SAAS,MAAM,MAAM,eAAe,MAAM,GAAG;KAClH;KACA,MAAM,iBAAiB,EAAE,cAAc,SAAS,MAAM,MAAM,SAAS,WAAW,EAAE,CAAC;KACnF;IACF,CAAC;IAED,OAAO,eAAe;IACtB,IAAI,SAAS,WAAW,KAAK,MAAM,YAAY;GACjD;GACA,OAAO;EACT,CAAC;CACH,CAAC,EACH,CAAC,CACH;AACF;;;;AAKA,MAAa,0BACX,iBAC8B;CAC9B,IAAI;CAEJ,IAAI;EACF,QAAQ,kBAAkB,YAAY,YAAY;CACpD,QAAQ;EACN,MAAM,QAAQ;CAChB;CAEA,OAAO;EACL,GAAG,SAAS,KAAK;EACjB,QAAQ,CAAC,WAAW;GACnB,qBAAqB;CACxB;AACF;AAEA,MAAa,6BAA6B,OAAO,GAAG,4BAA4B,CAAC,CAAC,WAChF,SACA;CACA,MAAM,QAAQ,OAAO,QAAQ,aAAa,QAAQ,eAAe,OAAO;CAExE,IAAI,MAAM,cAAc,QAAQ,SAAS,KAAK,aAAa,QAAQ,CAAC,CAAC,WAAW,GAC9E,OAAO,OAAO,QAAQ;CAExB,OAAO,OAAO,8BAA8B;EAC1C,GAAG;EACH,WAAW,MAAM,cAAc,IAAI,sBAAsB;CAC3D,CAAC;AACH,CAAC;AAED,MAAa,sCAAsC,OAAO,GAAG,qCAAqC,CAAC,CACjG,WAAW,SAAiD;CAC1D,MAAM,QAAQ,OAAO,QAAQ,sBAAsB,QAAQ,eAAe,OAAO;CAEjF,IAAI,MAAM,cAAc,QAAQ,SAAS,KAAK,aAAa,QAAQ,CAAC,CAAC,WAAW,GAC9E,OAAO,OAAO,QAAQ;CACxB,KAAK,MAAM,gBAAgB,MAAM,eAC/B,KAAK,MAAM,WAAW,aAAa,UACjC,IACE,QAAQ,aAAa,6BACrB,QAAQ,yBAAyB,aAAa,YAC9C,QAAQ,UAAU,WAAW,KAC7B,QAAQ,OAAO,MAAM,UAAU,UAAU,oBAAoB,CAAC,OAAO,KAAK,CAAC,MAC1E,QAAQ,cAAc,gBACnB,QAAQ,YAAY,iBACpB,QAAQ,iCAAiC,KAAA,IACzC,QAAQ,YAAY,cAAc,QAAQ,iCAAiC,KAAA,IAE/E,OAAO,OAAO,QAAQ;CAI5B,OAAO,OAAO,uCACZ;EACE,GAAG;EACH,WAAW,MAAM,cAAc,KAAK,UAAU;GAC5C,GAAG,SAAS,IAAI;GAChB,UAAU,KAAK;GACf,sBAAsB,KAAK;GAC3B,oBAAoB;GACpB,eAAe;IAAE,OAAO;IAA4B,MAAM;GAAU;GACpE,YAAY,EAAE,MAAM,kBAAkB;EACxC,EAAE;CACJ,GACA,aACF,CAAC,CAAC,KAAK,OAAO,QAAQ,gBAAgB,KAAK,CAAC,CAAC;AAC/C,CACF;AAEA,MAAa,+BAA+B,YAC1C,MAAM,OAAO,eAAe,2BAA2B,OAAO,CAAC;AAEjE,MAAa,wCACX,YACG,MAAM,OAAO,wBAAwB,oCAAoC,OAAO,CAAC"}
|
|
@@ -1 +1,22 @@
|
|
|
1
|
-
import "./connected/models.mjs";
|
|
1
|
+
import "./connected/models.mjs";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
//#region src/oauth/openid-client/compatibility.d.ts
|
|
4
|
+
/** Pure private provider rules, never part of the generic public options. */
|
|
5
|
+
interface TokenCompatibility {
|
|
6
|
+
readonly inspectReceipt: (receipt: {
|
|
7
|
+
readonly body: unknown;
|
|
8
|
+
readonly status: number;
|
|
9
|
+
readonly contentType: string | null;
|
|
10
|
+
}, input: {
|
|
11
|
+
readonly scopes: ReadonlyArray<string>;
|
|
12
|
+
readonly refreshRequired: boolean;
|
|
13
|
+
readonly operation: "authorization_code" | "refresh_token";
|
|
14
|
+
}) => void;
|
|
15
|
+
}
|
|
16
|
+
/** First-party rules travel with the exact provider generation. The symbol stays
|
|
17
|
+
* private so generic provider options do not expose grant-bearing hooks. */
|
|
18
|
+
declare const tokenCompatibility: unique symbol;
|
|
19
|
+
declare const TokenCompatibility: Schema.declare<TokenCompatibility, TokenCompatibility>;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { TokenCompatibility, tokenCompatibility };
|
|
22
|
+
//# sourceMappingURL=compatibility.d.mts.map
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { Predicate, Schema } from "effect";
|
|
1
2
|
//#region src/oauth/openid-client/compatibility.ts
|
|
3
|
+
/** First-party rules travel with the exact provider generation. The symbol stays
|
|
4
|
+
* private so generic provider options do not expose grant-bearing hooks. */
|
|
5
|
+
const tokenCompatibility = Symbol("effect-auth/OpenIdClient/tokenCompatibility");
|
|
6
|
+
const TokenCompatibility = Schema.declare((input) => Predicate.isObject(input) && "inspectReceipt" in input && Predicate.isFunction(input.inspectReceipt));
|
|
2
7
|
var DefiniteTokenRejection = class extends Error {};
|
|
3
8
|
//#endregion
|
|
4
|
-
export { DefiniteTokenRejection };
|
|
9
|
+
export { DefiniteTokenRejection, TokenCompatibility, tokenCompatibility };
|
|
5
10
|
|
|
6
11
|
//# sourceMappingURL=compatibility.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compatibility.mjs","names":[],"sources":["../../../src/oauth/openid-client/compatibility.ts"],"sourcesContent":["import type {\n OpenIdClientConnectedOAuthProvider,\n OpenIdClientConnectedProtocolOptions,\n} from \"./connected/models\";\n\n/** Pure private provider rules, never part of the generic public options. */\nexport interface TokenCompatibility {\n readonly inspectReceipt: (\n receipt: {\n readonly body: unknown;\n readonly status: number;\n readonly contentType: string | null;\n },\n input: {\n readonly scopes: ReadonlyArray<string>;\n readonly refreshRequired: boolean;\n readonly operation: \"authorization_code\" | \"refresh_token\";\n },\n ) => void;\n}\n\nexport class DefiniteTokenRejection extends Error {}\n\nexport interface ConnectedCompatibility extends TokenCompatibility {\n readonly authorizationScopes: (\n scopes: ReadonlyArray<string>,\n refresh: boolean,\n ) => ReadonlyArray<string>;\n readonly decodeScopes: (\n receipt: string | undefined,\n expected: ReadonlyArray<string>,\n ) => ReadonlyArray<string>;\n readonly includeRefreshScope: boolean;\n}\n\nexport type ProviderConnectedOAuth<R> = Omit<\n OpenIdClientConnectedOAuthProvider<R>,\n \"revocation\"\n> & {\n readonly revocation: { readonly mode: \"provider-cohort\" };\n};\n\nexport type ConnectedOptions<R> = Omit<OpenIdClientConnectedProtocolOptions<R>, \"providers\"> & {\n readonly providers: ReadonlyArray<\n OpenIdClientConnectedProtocolOptions<R>[\"providers\"][number] | ProviderConnectedOAuth<R>\n >;\n};\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"compatibility.mjs","names":[],"sources":["../../../src/oauth/openid-client/compatibility.ts"],"sourcesContent":["import { Predicate, Schema } from \"effect\";\n\nimport type {\n OpenIdClientConnectedOAuthProvider,\n OpenIdClientConnectedProtocolOptions,\n} from \"./connected/models\";\n\n/** Pure private provider rules, never part of the generic public options. */\nexport interface TokenCompatibility {\n readonly inspectReceipt: (\n receipt: {\n readonly body: unknown;\n readonly status: number;\n readonly contentType: string | null;\n },\n input: {\n readonly scopes: ReadonlyArray<string>;\n readonly refreshRequired: boolean;\n readonly operation: \"authorization_code\" | \"refresh_token\";\n },\n ) => void;\n}\n\n/** First-party rules travel with the exact provider generation. The symbol stays\n * private so generic provider options do not expose grant-bearing hooks. */\nexport const tokenCompatibility = Symbol(\"effect-auth/OpenIdClient/tokenCompatibility\");\n\nexport const TokenCompatibility = Schema.declare<TokenCompatibility>(\n (input): input is TokenCompatibility =>\n Predicate.isObject(input) &&\n \"inspectReceipt\" in input &&\n Predicate.isFunction(input.inspectReceipt),\n);\n\nexport class DefiniteTokenRejection extends Error {}\n\nexport interface ConnectedCompatibility extends TokenCompatibility {\n readonly authorizationScopes: (\n scopes: ReadonlyArray<string>,\n refresh: boolean,\n ) => ReadonlyArray<string>;\n readonly decodeScopes: (\n receipt: string | undefined,\n expected: ReadonlyArray<string>,\n ) => ReadonlyArray<string>;\n readonly includeRefreshScope: boolean;\n}\n\nexport type ProviderConnectedOAuth<R> = Omit<\n OpenIdClientConnectedOAuthProvider<R>,\n \"revocation\"\n> & {\n readonly revocation: { readonly mode: \"provider-cohort\" };\n};\n\nexport type ConnectedOptions<R> = Omit<OpenIdClientConnectedProtocolOptions<R>, \"providers\"> & {\n readonly providers: ReadonlyArray<\n OpenIdClientConnectedProtocolOptions<R>[\"providers\"][number] | ProviderConnectedOAuth<R>\n >;\n};\n"],"mappings":";;;;AAyBA,MAAa,qBAAqB,OAAO,6CAA6C;AAEtF,MAAa,qBAAqB,OAAO,SACtC,UACC,UAAU,SAAS,KAAK,KACxB,oBAAoB,SACpB,UAAU,WAAW,MAAM,cAAc,CAC7C;AAEA,IAAa,yBAAb,cAA4C,MAAM,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { OAuthAuthorizationUrl, OAuthCallbackId, OAuthGeneration, OAuthIssuer, O
|
|
|
3
3
|
import { OAuthUnavailable } from "../signInErrors.mjs";
|
|
4
4
|
import { freezeOAuth } from "../signInSnapshot.mjs";
|
|
5
5
|
import { OpenIdClientConfigurationError } from "./models.mjs";
|
|
6
|
+
import { TokenCompatibility, tokenCompatibility } from "./compatibility.mjs";
|
|
6
7
|
import { boundedFetch } from "./transport.mjs";
|
|
7
8
|
import { Effect, Predicate, Redacted, Schema } from "effect";
|
|
8
9
|
import * as client from "openid-client";
|
|
@@ -52,6 +53,7 @@ const optionsSchema = () => Schema.toType(Schema.Struct({
|
|
|
52
53
|
}), Schema.Struct({
|
|
53
54
|
...common,
|
|
54
55
|
protocol: Schema.Literal("oauth"),
|
|
56
|
+
[tokenCompatibility]: Schema.optionalKey(TokenCompatibility),
|
|
55
57
|
authorizationEndpoint: boundedString(2048),
|
|
56
58
|
tokenEndpoint: boundedString(2048),
|
|
57
59
|
pkceS256: Schema.Literal(true),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configuration.mjs","names":[],"sources":["../../../src/oauth/openid-client/configuration.ts"],"sourcesContent":["import { Effect, Predicate, Redacted, Schema } from \"effect\";\nimport * as client from \"openid-client\";\n\nimport { OAuthProviderKey } from \"../schema\";\nimport { OAuthUnavailable } from \"../signInErrors\";\nimport {\n OAuthAuthorizationUrl,\n OAuthCallbackId,\n OAuthGeneration,\n OAuthIssuer,\n OAuthRedirectUri,\n} from \"../signInModels\";\nimport { freezeOAuth } from \"../signInSnapshot\";\nimport {\n OpenIdClientConfigurationError,\n type OpenIdClientAuthentication,\n type OpenIdClientOAuthProvider,\n type OpenIdClientOAuthProtocolOptions,\n type OpenIdClientOidcProvider,\n} from \"./models\";\nimport { boundedFetch } from \"./transport\";\n\nconst boundedString = (maximum: number) =>\n Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(maximum));\n\nconst fields = Schema.Record(\n Schema.String.check(Schema.isPattern(/^[A-Za-z][A-Za-z0-9._~-]{0,63}$/)),\n Schema.String.check(Schema.isMaxLength(2048)),\n).check(Schema.makeFilter((record) => Object.keys(record).length <= 16));\n\nconst secret = Schema.RedactedFromValue(boundedString(4096));\n\nconst authentication = Schema.Union([\n Schema.Struct({ method: Schema.Literal(\"client_secret_basic\"), secret }),\n Schema.Struct({ method: Schema.Literal(\"client_secret_post\"), secret }),\n Schema.Struct({ method: Schema.Literal(\"none\"), publicClient: Schema.Literal(true) }),\n]);\n\nconst common = {\n provider: OAuthProviderKey,\n configurationGeneration: OAuthGeneration,\n issuance: Schema.Literals([\"active\", \"retired\"]),\n issuer: OAuthIssuer,\n responseIssuerMode: Schema.Literals([\"required\", \"unsupported\"]),\n clientId: boundedString(1024),\n authentication,\n callbacks: Schema.Array(\n Schema.Struct({ callbackId: OAuthCallbackId, redirectUri: OAuthRedirectUri }),\n ).check(Schema.isMinLength(1), Schema.isMaxLength(16)),\n scopes: Schema.Array(\n Schema.String.check(Schema.isPattern(/^[\\x21\\x23-\\x5b\\x5d-\\x7e]{1,128}$/)),\n ).check(Schema.isMaxLength(32)),\n authorizationParameters: Schema.optionalKey(fields),\n tokenParameters: Schema.optionalKey(fields),\n};\n\nconst optionsSchema = <R>() =>\n Schema.toType(\n Schema.Struct({\n providers: Schema.Array(\n Schema.Union([\n Schema.Struct({\n ...common,\n protocol: Schema.Literal(\"oidc\"),\n idTokenSignedResponseAlg: Schema.Literal(\"RS256\"),\n maxAgeSeconds: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 86400 })),\n ),\n }),\n Schema.Struct({\n ...common,\n protocol: Schema.Literal(\"oauth\"),\n authorizationEndpoint: boundedString(2048),\n tokenEndpoint: boundedString(2048),\n pkceS256: Schema.Literal(true),\n identitySource: Schema.Struct({\n url: boundedString(2048),\n headers: Schema.optionalKey(fields),\n // A configured function is trusted application code; its result has a separate schema boundary.\n decodeIdentity: Schema.declare<\n OpenIdClientOAuthProvider<R>[\"identitySource\"][\"decodeIdentity\"]\n >(\n (\n input,\n ): input is OpenIdClientOAuthProvider<R>[\"identitySource\"][\"decodeIdentity\"] =>\n Predicate.isFunction(input),\n ),\n }),\n }),\n ]),\n ).check(Schema.isMinLength(1), Schema.isMaxLength(64)),\n timeoutSeconds: Schema.Finite.check(Schema.isBetween({ minimum: 1, maximum: 30 })),\n fetch: Schema.optionalKey(\n Schema.declare<client.CustomFetch>((input): input is client.CustomFetch =>\n Predicate.isFunction(input),\n ),\n ),\n }),\n );\n\nconst reserved = new Set([\n \"client_id\",\n \"client_secret\",\n \"client_assertion\",\n \"client_assertion_type\",\n \"redirect_uri\",\n \"response_type\",\n \"response_mode\",\n \"state\",\n \"code\",\n \"code_verifier\",\n \"code_challenge\",\n \"code_challenge_method\",\n \"nonce\",\n \"scope\",\n \"iss\",\n \"grant_type\",\n \"max_age\",\n \"request\",\n \"request_uri\",\n \"authorization_details\",\n \"id_token_hint\",\n \"login_hint\",\n \"login_hint_token\",\n \"subject_token\",\n \"subject_token_type\",\n \"actor_token\",\n \"actor_token_type\",\n \"requested_token_type\",\n]);\n\nconst forbiddenHeaders = new Set([\n \"authorization\",\n \"proxy-authorization\",\n \"cookie\",\n \"host\",\n \"content-length\",\n \"content-type\",\n \"transfer-encoding\",\n \"connection\",\n \"upgrade\",\n \"trailer\",\n \"te\",\n]);\n\nconst configError = (reason: OpenIdClientConfigurationError[\"reason\"]) =>\n OpenIdClientConfigurationError.make({ reason });\n\nexport const endpoint = (value: string): URL => {\n const url = new URL(value);\n\n if (\n url.protocol !== \"https:\" ||\n url.username !== \"\" ||\n url.password !== \"\" ||\n value.includes(\"#\") ||\n // oxlint-disable-next-line no-control-regex -- Reject ambiguous protocol URL control characters.\n /[\\s\\\\\\u0000-\\u001f\\u007f]/u.test(value)\n )\n throw configError(\"metadata\");\n\n return url;\n};\n\nconst checkParameters = (parameters: Readonly<Record<string, string>> | undefined) => {\n for (const key of Object.keys(parameters ?? {})) {\n if (reserved.has(key.toLowerCase())) throw configError(\"parameters\");\n }\n};\n\nexport const clientAuthentication = (\n authentication: OpenIdClientAuthentication,\n): client.ClientAuth => {\n switch (authentication.method) {\n case \"client_secret_basic\":\n return client.ClientSecretBasic(Redacted.value(authentication.secret));\n case \"client_secret_post\":\n return client.ClientSecretPost(Redacted.value(authentication.secret));\n case \"none\":\n return client.None();\n }\n};\n\nexport type Provider<R> = OpenIdClientOidcProvider | OpenIdClientOAuthProvider<R>;\n\nexport interface InstalledProvider<R> {\n readonly provider: Provider<R>;\n readonly metadata: client.ServerMetadata;\n readonly allowedUrls: ReadonlySet<string>;\n}\n\nexport const makeAuthorizationParameters = (\n configuration: {\n readonly protocol: \"oauth\" | \"oidc\";\n readonly authorizationParameters?: Readonly<Record<string, string>>;\n readonly scopes: ReadonlyArray<string>;\n readonly maxAgeSeconds?: number;\n },\n redirectUri: string,\n generated: { readonly state: string; readonly challenge: string; readonly nonce?: string },\n): Record<string, string> => ({\n ...configuration.authorizationParameters,\n response_type: \"code\",\n response_mode: \"query\",\n redirect_uri: redirectUri,\n scope: configuration.scopes.join(\" \"),\n state: generated.state,\n code_challenge: generated.challenge,\n code_challenge_method: \"S256\",\n ...(generated.nonce === undefined ? {} : { nonce: generated.nonce }),\n ...(configuration.protocol === \"oidc\" && configuration.maxAgeSeconds !== undefined\n ? { max_age: String(configuration.maxAgeSeconds) }\n : {}),\n});\n\nconst metadataSchema = Schema.Struct({\n issuer: OAuthIssuer,\n authorization_endpoint: boundedString(2048),\n token_endpoint: boundedString(2048),\n jwks_uri: Schema.optionalKey(boundedString(2048)),\n code_challenge_methods_supported: Schema.optionalKey(Schema.Array(boundedString(64))),\n response_types_supported: Schema.optionalKey(Schema.Array(boundedString(64))),\n id_token_signing_alg_values_supported: Schema.optionalKey(Schema.Array(boundedString(64))),\n token_endpoint_auth_methods_supported: Schema.optionalKey(Schema.Array(boundedString(64))),\n authorization_response_iss_parameter_supported: Schema.optionalKey(Schema.Boolean),\n});\n\nexport const installConfigurations = Effect.fn(\"OpenIdClient.installConfigurations\")(function* <R>(\n input: OpenIdClientOAuthProtocolOptions<R>,\n) {\n const options = yield* Schema.decodeEffect(optionsSchema<R>())(input).pipe(\n Effect.mapError(() => configError(\"provider\")),\n );\n\n // Detach secrets as well as arrays and records before retaining configuration.\n const providers = options.providers.map((provider): Provider<R> => {\n const detached = {\n callbacks: provider.callbacks.map((callback) => ({ ...callback })),\n scopes: [...provider.scopes],\n ...(provider.authorizationParameters === undefined\n ? {}\n : { authorizationParameters: { ...provider.authorizationParameters } }),\n ...(provider.tokenParameters === undefined\n ? {}\n : { tokenParameters: { ...provider.tokenParameters } }),\n authentication:\n provider.authentication.method === \"none\"\n ? { ...provider.authentication }\n : {\n ...provider.authentication,\n secret: Redacted.make(Redacted.value(provider.authentication.secret)),\n },\n };\n\n return provider.protocol === \"oidc\"\n ? { ...provider, ...detached }\n : {\n ...provider,\n ...detached,\n identitySource: {\n ...provider.identitySource,\n ...(provider.identitySource.headers === undefined\n ? {}\n : { headers: { ...provider.identitySource.headers } }),\n },\n };\n });\n\n const fetch: client.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 yield* Effect.try({\n try: () => {\n const generations = new Set<string>();\n const active = new Set<string>();\n const names = new Set<string>();\n\n for (const provider of providers) {\n const generation = `${provider.provider.length}:${provider.provider}:${provider.configurationGeneration}`;\n\n if (generations.has(generation)) throw configError(\"generation\");\n generations.add(generation);\n names.add(provider.provider);\n if (provider.issuance === \"active\") {\n if (active.has(provider.provider)) throw configError(\"generation\");\n active.add(provider.provider);\n }\n const issuer = endpoint(provider.issuer);\n\n if (provider.issuer.includes(\"?\") || issuer.pathname.includes(\"/.well-known/\"))\n throw configError(\"issuer\");\n if (new Set(provider.scopes).size !== provider.scopes.length)\n throw configError(\"parameters\");\n if ((provider.protocol === \"oidc\") !== provider.scopes.includes(\"openid\"))\n throw configError(\"parameters\");\n checkParameters(provider.authorizationParameters);\n checkParameters(provider.tokenParameters);\n const callbacks = new Set<string>();\n\n for (const callback of provider.callbacks) {\n const url = endpoint(callback.redirectUri);\n\n if (\n url.href !== callback.redirectUri ||\n callback.redirectUri.includes(\"?\") ||\n callbacks.has(callback.callbackId)\n )\n throw configError(\"callback\");\n callbacks.add(callback.callbackId);\n for (const other of providers) {\n if (provider.issuer === other.issuer) continue;\n if (\n provider.responseIssuerMode === \"required\" &&\n other.responseIssuerMode === \"required\"\n )\n continue;\n if (other.callbacks.some((candidate) => candidate.redirectUri === callback.redirectUri))\n throw configError(\"callback\");\n }\n }\n if (provider.protocol === \"oauth\") {\n endpoint(provider.identitySource.url);\n for (const key of Object.keys(provider.identitySource.headers ?? {})) {\n if (forbiddenHeaders.has(key.toLowerCase())) throw configError(\"identity-source\");\n }\n new Headers(provider.identitySource.headers);\n }\n freezeOAuth(provider);\n }\n if (active.size !== names.size) throw configError(\"generation\");\n },\n catch: (error) =>\n Schema.is(OpenIdClientConfigurationError)(error) ? error : configError(\"provider\"),\n });\n const installed: InstalledProvider<R>[] = [];\n\n for (const provider of providers) {\n let raw: client.ServerMetadata;\n\n if (provider.protocol === \"oidc\") {\n const discoveryUrl = new URL(provider.issuer);\n\n discoveryUrl.pathname = `${discoveryUrl.pathname.replace(/\\/$/u, \"\")}/.well-known/openid-configuration`;\n\n const configuration = yield* Effect.tryPromise({\n try: (signal) =>\n client.discovery(\n new URL(provider.issuer),\n provider.clientId,\n {\n id_token_signed_response_alg: provider.idTokenSignedResponseAlg,\n [client.clockSkew]: 0,\n [client.clockTolerance]: 0,\n },\n clientAuthentication(provider.authentication),\n {\n timeout: options.timeoutSeconds,\n execute: [client.enableNonRepudiationChecks],\n [client.customFetch]: boundedFetch(fetch, signal, new Set([discoveryUrl.href])),\n },\n ),\n catch: () => OAuthUnavailable.make({}),\n });\n\n raw = configuration.serverMetadata();\n } else {\n raw = {\n issuer: provider.issuer,\n authorization_endpoint: provider.authorizationEndpoint,\n token_endpoint: provider.tokenEndpoint,\n authorization_response_iss_parameter_supported: provider.responseIssuerMode === \"required\",\n };\n }\n\n // oxlint-disable-next-line no-restricted-properties -- Discovered foreign metadata is not yet validated for this adapter profile.\n const metadata = yield* Schema.decodeUnknownEffect(metadataSchema)(raw).pipe(\n Effect.mapError(() => configError(\"metadata\")),\n );\n\n const allowedUrls = yield* Effect.try({\n try: () => {\n if (metadata.issuer !== provider.issuer) throw configError(\"issuer\");\n if (\n (metadata.authorization_response_iss_parameter_supported === true) !==\n (provider.responseIssuerMode === \"required\")\n )\n throw configError(\"metadata\");\n const auth = endpoint(metadata.authorization_endpoint);\n\n for (const key of auth.searchParams.keys()) {\n if (reserved.has(key.toLowerCase())) throw configError(\"parameters\");\n }\n const token = endpoint(metadata.token_endpoint);\n\n const supportedAuthentication =\n metadata.token_endpoint_auth_methods_supported ??\n (provider.protocol === \"oidc\" ? [\"client_secret_basic\"] : undefined);\n\n if (\n supportedAuthentication !== undefined &&\n !supportedAuthentication.includes(provider.authentication.method)\n )\n throw configError(\"authentication\");\n const urls = new Set([token.href]);\n\n if (provider.protocol === \"oidc\") {\n if (\n !metadata.code_challenge_methods_supported?.includes(\"S256\") ||\n !metadata.response_types_supported?.includes(\"code\") ||\n !metadata.id_token_signing_alg_values_supported?.includes(\"RS256\") ||\n metadata.jwks_uri === undefined\n )\n throw configError(\"metadata\");\n urls.add(endpoint(metadata.jwks_uri).href);\n } else {\n urls.add(endpoint(provider.identitySource.url).href);\n }\n freezeOAuth(metadata);\n\n return urls;\n },\n catch: (error) =>\n Schema.is(OpenIdClientConfigurationError)(error) ? error : configError(\"metadata\"),\n });\n\n const serverMetadata: client.ServerMetadata = {\n ...metadata,\n code_challenge_methods_supported: metadata.code_challenge_methods_supported?.slice(),\n response_types_supported: metadata.response_types_supported?.slice(),\n id_token_signing_alg_values_supported:\n metadata.id_token_signing_alg_values_supported?.slice(),\n token_endpoint_auth_methods_supported:\n metadata.token_endpoint_auth_methods_supported?.slice(),\n };\n\n // The SDK encodes each generated 32-byte state/challenge/nonce in 43 URL-safe characters.\n const placeholder = \"a\".repeat(43);\n\n const authorization = yield* Effect.try({\n try: () => new client.Configuration(serverMetadata, provider.clientId),\n catch: () => configError(\"parameters\"),\n });\n\n for (const callback of provider.callbacks) {\n const url = yield* Effect.try({\n try: () =>\n client.buildAuthorizationUrl(\n authorization,\n makeAuthorizationParameters(provider, callback.redirectUri, {\n state: placeholder,\n challenge: placeholder,\n ...(provider.protocol === \"oidc\" ? { nonce: placeholder } : {}),\n }),\n ),\n catch: () => configError(\"parameters\"),\n });\n\n yield* Schema.decodeEffect(OAuthAuthorizationUrl)(url.href).pipe(\n Effect.mapError(() => configError(\"parameters\")),\n );\n }\n freezeOAuth(serverMetadata);\n installed.push({ provider, metadata: serverMetadata, allowedUrls });\n }\n\n return { installed, fetch, timeoutSeconds: options.timeoutSeconds };\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"configuration.mjs","names":[],"sources":["../../../src/oauth/openid-client/configuration.ts"],"sourcesContent":["import { Effect, Predicate, Redacted, Schema } from \"effect\";\nimport * as client from \"openid-client\";\n\nimport { OAuthProviderKey } from \"../schema\";\nimport { OAuthUnavailable } from \"../signInErrors\";\nimport {\n OAuthAuthorizationUrl,\n OAuthCallbackId,\n OAuthGeneration,\n OAuthIssuer,\n OAuthRedirectUri,\n} from \"../signInModels\";\nimport { freezeOAuth } from \"../signInSnapshot\";\nimport { TokenCompatibility, tokenCompatibility } from \"./compatibility\";\nimport {\n OpenIdClientConfigurationError,\n type OpenIdClientAuthentication,\n type OpenIdClientOAuthProvider,\n type OpenIdClientOAuthProtocolOptions,\n type OpenIdClientOidcProvider,\n} from \"./models\";\nimport { boundedFetch } from \"./transport\";\n\nconst boundedString = (maximum: number) =>\n Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(maximum));\n\nconst fields = Schema.Record(\n Schema.String.check(Schema.isPattern(/^[A-Za-z][A-Za-z0-9._~-]{0,63}$/)),\n Schema.String.check(Schema.isMaxLength(2048)),\n).check(Schema.makeFilter((record) => Object.keys(record).length <= 16));\n\nconst secret = Schema.RedactedFromValue(boundedString(4096));\n\nconst authentication = Schema.Union([\n Schema.Struct({ method: Schema.Literal(\"client_secret_basic\"), secret }),\n Schema.Struct({ method: Schema.Literal(\"client_secret_post\"), secret }),\n Schema.Struct({ method: Schema.Literal(\"none\"), publicClient: Schema.Literal(true) }),\n]);\n\nconst common = {\n provider: OAuthProviderKey,\n configurationGeneration: OAuthGeneration,\n issuance: Schema.Literals([\"active\", \"retired\"]),\n issuer: OAuthIssuer,\n responseIssuerMode: Schema.Literals([\"required\", \"unsupported\"]),\n clientId: boundedString(1024),\n authentication,\n callbacks: Schema.Array(\n Schema.Struct({ callbackId: OAuthCallbackId, redirectUri: OAuthRedirectUri }),\n ).check(Schema.isMinLength(1), Schema.isMaxLength(16)),\n scopes: Schema.Array(\n Schema.String.check(Schema.isPattern(/^[\\x21\\x23-\\x5b\\x5d-\\x7e]{1,128}$/)),\n ).check(Schema.isMaxLength(32)),\n authorizationParameters: Schema.optionalKey(fields),\n tokenParameters: Schema.optionalKey(fields),\n};\n\nconst optionsSchema = <R>() =>\n Schema.toType(\n Schema.Struct({\n providers: Schema.Array(\n Schema.Union([\n Schema.Struct({\n ...common,\n protocol: Schema.Literal(\"oidc\"),\n idTokenSignedResponseAlg: Schema.Literal(\"RS256\"),\n maxAgeSeconds: Schema.optionalKey(\n Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 86400 })),\n ),\n }),\n Schema.Struct({\n ...common,\n protocol: Schema.Literal(\"oauth\"),\n [tokenCompatibility]: Schema.optionalKey(TokenCompatibility),\n authorizationEndpoint: boundedString(2048),\n tokenEndpoint: boundedString(2048),\n pkceS256: Schema.Literal(true),\n identitySource: Schema.Struct({\n url: boundedString(2048),\n headers: Schema.optionalKey(fields),\n // A configured function is trusted application code; its result has a separate schema boundary.\n decodeIdentity: Schema.declare<\n OpenIdClientOAuthProvider<R>[\"identitySource\"][\"decodeIdentity\"]\n >(\n (\n input,\n ): input is OpenIdClientOAuthProvider<R>[\"identitySource\"][\"decodeIdentity\"] =>\n Predicate.isFunction(input),\n ),\n }),\n }),\n ]),\n ).check(Schema.isMinLength(1), Schema.isMaxLength(64)),\n timeoutSeconds: Schema.Finite.check(Schema.isBetween({ minimum: 1, maximum: 30 })),\n fetch: Schema.optionalKey(\n Schema.declare<client.CustomFetch>((input): input is client.CustomFetch =>\n Predicate.isFunction(input),\n ),\n ),\n }),\n );\n\nconst reserved = new Set([\n \"client_id\",\n \"client_secret\",\n \"client_assertion\",\n \"client_assertion_type\",\n \"redirect_uri\",\n \"response_type\",\n \"response_mode\",\n \"state\",\n \"code\",\n \"code_verifier\",\n \"code_challenge\",\n \"code_challenge_method\",\n \"nonce\",\n \"scope\",\n \"iss\",\n \"grant_type\",\n \"max_age\",\n \"request\",\n \"request_uri\",\n \"authorization_details\",\n \"id_token_hint\",\n \"login_hint\",\n \"login_hint_token\",\n \"subject_token\",\n \"subject_token_type\",\n \"actor_token\",\n \"actor_token_type\",\n \"requested_token_type\",\n]);\n\nconst forbiddenHeaders = new Set([\n \"authorization\",\n \"proxy-authorization\",\n \"cookie\",\n \"host\",\n \"content-length\",\n \"content-type\",\n \"transfer-encoding\",\n \"connection\",\n \"upgrade\",\n \"trailer\",\n \"te\",\n]);\n\nconst configError = (reason: OpenIdClientConfigurationError[\"reason\"]) =>\n OpenIdClientConfigurationError.make({ reason });\n\nexport const endpoint = (value: string): URL => {\n const url = new URL(value);\n\n if (\n url.protocol !== \"https:\" ||\n url.username !== \"\" ||\n url.password !== \"\" ||\n value.includes(\"#\") ||\n // oxlint-disable-next-line no-control-regex -- Reject ambiguous protocol URL control characters.\n /[\\s\\\\\\u0000-\\u001f\\u007f]/u.test(value)\n )\n throw configError(\"metadata\");\n\n return url;\n};\n\nconst checkParameters = (parameters: Readonly<Record<string, string>> | undefined) => {\n for (const key of Object.keys(parameters ?? {})) {\n if (reserved.has(key.toLowerCase())) throw configError(\"parameters\");\n }\n};\n\nexport const clientAuthentication = (\n authentication: OpenIdClientAuthentication,\n): client.ClientAuth => {\n switch (authentication.method) {\n case \"client_secret_basic\":\n return client.ClientSecretBasic(Redacted.value(authentication.secret));\n case \"client_secret_post\":\n return client.ClientSecretPost(Redacted.value(authentication.secret));\n case \"none\":\n return client.None();\n }\n};\n\nexport type Provider<R> = OpenIdClientOidcProvider | OpenIdClientOAuthProvider<R>;\n\nexport interface InstalledProvider<R> {\n readonly provider: Provider<R>;\n readonly metadata: client.ServerMetadata;\n readonly allowedUrls: ReadonlySet<string>;\n}\n\nexport const makeAuthorizationParameters = (\n configuration: {\n readonly protocol: \"oauth\" | \"oidc\";\n readonly authorizationParameters?: Readonly<Record<string, string>>;\n readonly scopes: ReadonlyArray<string>;\n readonly maxAgeSeconds?: number;\n },\n redirectUri: string,\n generated: { readonly state: string; readonly challenge: string; readonly nonce?: string },\n): Record<string, string> => ({\n ...configuration.authorizationParameters,\n response_type: \"code\",\n response_mode: \"query\",\n redirect_uri: redirectUri,\n scope: configuration.scopes.join(\" \"),\n state: generated.state,\n code_challenge: generated.challenge,\n code_challenge_method: \"S256\",\n ...(generated.nonce === undefined ? {} : { nonce: generated.nonce }),\n ...(configuration.protocol === \"oidc\" && configuration.maxAgeSeconds !== undefined\n ? { max_age: String(configuration.maxAgeSeconds) }\n : {}),\n});\n\nconst metadataSchema = Schema.Struct({\n issuer: OAuthIssuer,\n authorization_endpoint: boundedString(2048),\n token_endpoint: boundedString(2048),\n jwks_uri: Schema.optionalKey(boundedString(2048)),\n code_challenge_methods_supported: Schema.optionalKey(Schema.Array(boundedString(64))),\n response_types_supported: Schema.optionalKey(Schema.Array(boundedString(64))),\n id_token_signing_alg_values_supported: Schema.optionalKey(Schema.Array(boundedString(64))),\n token_endpoint_auth_methods_supported: Schema.optionalKey(Schema.Array(boundedString(64))),\n authorization_response_iss_parameter_supported: Schema.optionalKey(Schema.Boolean),\n});\n\nexport const installConfigurations = Effect.fn(\"OpenIdClient.installConfigurations\")(function* <R>(\n input: OpenIdClientOAuthProtocolOptions<R>,\n) {\n const options = yield* Schema.decodeEffect(optionsSchema<R>())(input).pipe(\n Effect.mapError(() => configError(\"provider\")),\n );\n\n // Detach secrets as well as arrays and records before retaining configuration.\n const providers = options.providers.map((provider): Provider<R> => {\n const detached = {\n callbacks: provider.callbacks.map((callback) => ({ ...callback })),\n scopes: [...provider.scopes],\n ...(provider.authorizationParameters === undefined\n ? {}\n : { authorizationParameters: { ...provider.authorizationParameters } }),\n ...(provider.tokenParameters === undefined\n ? {}\n : { tokenParameters: { ...provider.tokenParameters } }),\n authentication:\n provider.authentication.method === \"none\"\n ? { ...provider.authentication }\n : {\n ...provider.authentication,\n secret: Redacted.make(Redacted.value(provider.authentication.secret)),\n },\n };\n\n return provider.protocol === \"oidc\"\n ? { ...provider, ...detached }\n : {\n ...provider,\n ...detached,\n identitySource: {\n ...provider.identitySource,\n ...(provider.identitySource.headers === undefined\n ? {}\n : { headers: { ...provider.identitySource.headers } }),\n },\n };\n });\n\n const fetch: client.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 yield* Effect.try({\n try: () => {\n const generations = new Set<string>();\n const active = new Set<string>();\n const names = new Set<string>();\n\n for (const provider of providers) {\n const generation = `${provider.provider.length}:${provider.provider}:${provider.configurationGeneration}`;\n\n if (generations.has(generation)) throw configError(\"generation\");\n generations.add(generation);\n names.add(provider.provider);\n if (provider.issuance === \"active\") {\n if (active.has(provider.provider)) throw configError(\"generation\");\n active.add(provider.provider);\n }\n const issuer = endpoint(provider.issuer);\n\n if (provider.issuer.includes(\"?\") || issuer.pathname.includes(\"/.well-known/\"))\n throw configError(\"issuer\");\n if (new Set(provider.scopes).size !== provider.scopes.length)\n throw configError(\"parameters\");\n if ((provider.protocol === \"oidc\") !== provider.scopes.includes(\"openid\"))\n throw configError(\"parameters\");\n checkParameters(provider.authorizationParameters);\n checkParameters(provider.tokenParameters);\n const callbacks = new Set<string>();\n\n for (const callback of provider.callbacks) {\n const url = endpoint(callback.redirectUri);\n\n if (\n url.href !== callback.redirectUri ||\n callback.redirectUri.includes(\"?\") ||\n callbacks.has(callback.callbackId)\n )\n throw configError(\"callback\");\n callbacks.add(callback.callbackId);\n for (const other of providers) {\n if (provider.issuer === other.issuer) continue;\n if (\n provider.responseIssuerMode === \"required\" &&\n other.responseIssuerMode === \"required\"\n )\n continue;\n if (other.callbacks.some((candidate) => candidate.redirectUri === callback.redirectUri))\n throw configError(\"callback\");\n }\n }\n if (provider.protocol === \"oauth\") {\n endpoint(provider.identitySource.url);\n for (const key of Object.keys(provider.identitySource.headers ?? {})) {\n if (forbiddenHeaders.has(key.toLowerCase())) throw configError(\"identity-source\");\n }\n new Headers(provider.identitySource.headers);\n }\n freezeOAuth(provider);\n }\n if (active.size !== names.size) throw configError(\"generation\");\n },\n catch: (error) =>\n Schema.is(OpenIdClientConfigurationError)(error) ? error : configError(\"provider\"),\n });\n const installed: InstalledProvider<R>[] = [];\n\n for (const provider of providers) {\n let raw: client.ServerMetadata;\n\n if (provider.protocol === \"oidc\") {\n const discoveryUrl = new URL(provider.issuer);\n\n discoveryUrl.pathname = `${discoveryUrl.pathname.replace(/\\/$/u, \"\")}/.well-known/openid-configuration`;\n\n const configuration = yield* Effect.tryPromise({\n try: (signal) =>\n client.discovery(\n new URL(provider.issuer),\n provider.clientId,\n {\n id_token_signed_response_alg: provider.idTokenSignedResponseAlg,\n [client.clockSkew]: 0,\n [client.clockTolerance]: 0,\n },\n clientAuthentication(provider.authentication),\n {\n timeout: options.timeoutSeconds,\n execute: [client.enableNonRepudiationChecks],\n [client.customFetch]: boundedFetch(fetch, signal, new Set([discoveryUrl.href])),\n },\n ),\n catch: () => OAuthUnavailable.make({}),\n });\n\n raw = configuration.serverMetadata();\n } else {\n raw = {\n issuer: provider.issuer,\n authorization_endpoint: provider.authorizationEndpoint,\n token_endpoint: provider.tokenEndpoint,\n authorization_response_iss_parameter_supported: provider.responseIssuerMode === \"required\",\n };\n }\n\n // oxlint-disable-next-line no-restricted-properties -- Discovered foreign metadata is not yet validated for this adapter profile.\n const metadata = yield* Schema.decodeUnknownEffect(metadataSchema)(raw).pipe(\n Effect.mapError(() => configError(\"metadata\")),\n );\n\n const allowedUrls = yield* Effect.try({\n try: () => {\n if (metadata.issuer !== provider.issuer) throw configError(\"issuer\");\n if (\n (metadata.authorization_response_iss_parameter_supported === true) !==\n (provider.responseIssuerMode === \"required\")\n )\n throw configError(\"metadata\");\n const auth = endpoint(metadata.authorization_endpoint);\n\n for (const key of auth.searchParams.keys()) {\n if (reserved.has(key.toLowerCase())) throw configError(\"parameters\");\n }\n const token = endpoint(metadata.token_endpoint);\n\n const supportedAuthentication =\n metadata.token_endpoint_auth_methods_supported ??\n (provider.protocol === \"oidc\" ? [\"client_secret_basic\"] : undefined);\n\n if (\n supportedAuthentication !== undefined &&\n !supportedAuthentication.includes(provider.authentication.method)\n )\n throw configError(\"authentication\");\n const urls = new Set([token.href]);\n\n if (provider.protocol === \"oidc\") {\n if (\n !metadata.code_challenge_methods_supported?.includes(\"S256\") ||\n !metadata.response_types_supported?.includes(\"code\") ||\n !metadata.id_token_signing_alg_values_supported?.includes(\"RS256\") ||\n metadata.jwks_uri === undefined\n )\n throw configError(\"metadata\");\n urls.add(endpoint(metadata.jwks_uri).href);\n } else {\n urls.add(endpoint(provider.identitySource.url).href);\n }\n freezeOAuth(metadata);\n\n return urls;\n },\n catch: (error) =>\n Schema.is(OpenIdClientConfigurationError)(error) ? error : configError(\"metadata\"),\n });\n\n const serverMetadata: client.ServerMetadata = {\n ...metadata,\n code_challenge_methods_supported: metadata.code_challenge_methods_supported?.slice(),\n response_types_supported: metadata.response_types_supported?.slice(),\n id_token_signing_alg_values_supported:\n metadata.id_token_signing_alg_values_supported?.slice(),\n token_endpoint_auth_methods_supported:\n metadata.token_endpoint_auth_methods_supported?.slice(),\n };\n\n // The SDK encodes each generated 32-byte state/challenge/nonce in 43 URL-safe characters.\n const placeholder = \"a\".repeat(43);\n\n const authorization = yield* Effect.try({\n try: () => new client.Configuration(serverMetadata, provider.clientId),\n catch: () => configError(\"parameters\"),\n });\n\n for (const callback of provider.callbacks) {\n const url = yield* Effect.try({\n try: () =>\n client.buildAuthorizationUrl(\n authorization,\n makeAuthorizationParameters(provider, callback.redirectUri, {\n state: placeholder,\n challenge: placeholder,\n ...(provider.protocol === \"oidc\" ? { nonce: placeholder } : {}),\n }),\n ),\n catch: () => configError(\"parameters\"),\n });\n\n yield* Schema.decodeEffect(OAuthAuthorizationUrl)(url.href).pipe(\n Effect.mapError(() => configError(\"parameters\")),\n );\n }\n freezeOAuth(serverMetadata);\n installed.push({ provider, metadata: serverMetadata, allowedUrls });\n }\n\n return { installed, fetch, timeoutSeconds: options.timeoutSeconds };\n});\n"],"mappings":"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"}
|
|
@@ -3,9 +3,9 @@ import { OAuthUnavailable } from "../../signInErrors.mjs";
|
|
|
3
3
|
import "../../signInModels.mjs";
|
|
4
4
|
import "../../connectedModels.mjs";
|
|
5
5
|
import { OAuthConnectedProtocol } from "../../OAuthConnectedProtocol.mjs";
|
|
6
|
-
import { OpenIdClientConfigurationError } from "../models.mjs";
|
|
7
6
|
import { OpenIdClientConnectedProtocolOptions } from "./models.mjs";
|
|
8
7
|
import "../compatibility.mjs";
|
|
8
|
+
import { OpenIdClientConfigurationError } from "../models.mjs";
|
|
9
9
|
import "../ProviderRevocation.mjs";
|
|
10
10
|
import { DateTime, Effect, Layer } from "effect";
|
|
11
11
|
//#region src/oauth/openid-client/connected/protocol.d.ts
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OAuthProtocolRejected } from "../signInErrors.mjs";
|
|
2
2
|
import { OAuthProtocolConfiguration, OAuthVerifiedExternalIdentity } from "../signInModels.mjs";
|
|
3
|
+
import { TokenCompatibility, tokenCompatibility } from "./compatibility.mjs";
|
|
3
4
|
import { Effect, Redacted, Schema } from "effect";
|
|
4
5
|
import { CustomFetch } from "openid-client";
|
|
5
6
|
//#region src/oauth/openid-client/models.d.ts
|
|
@@ -44,6 +45,8 @@ interface OpenIdClientOidcProvider extends ProviderGeneration {
|
|
|
44
45
|
readonly maxAgeSeconds?: number;
|
|
45
46
|
}
|
|
46
47
|
interface OpenIdClientOAuthProvider<R = never> extends ProviderGeneration {
|
|
48
|
+
/** @internal First-party provider behavior, retained by the configuration codec. */
|
|
49
|
+
readonly [tokenCompatibility]?: TokenCompatibility;
|
|
47
50
|
readonly protocol: "oauth";
|
|
48
51
|
readonly authorizationEndpoint: string;
|
|
49
52
|
readonly tokenEndpoint: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.mjs","names":[],"sources":["../../../src/oauth/openid-client/models.ts"],"sourcesContent":["import { type Effect, type Redacted, Schema } from \"effect\";\nimport type { CustomFetch } from \"openid-client\";\n\nimport type { OAuthProtocolRejected } from \"../signInErrors\";\nimport type { OAuthProtocolConfiguration, OAuthVerifiedExternalIdentity } from \"../signInModels\";\n\nexport class OpenIdClientConfigurationError extends Schema.TaggedError<OpenIdClientConfigurationError>()(\n \"OpenIdClientConfigurationError\",\n {\n reason: Schema.Literals([\n \"provider\",\n \"generation\",\n \"issuer\",\n \"callback\",\n \"authentication\",\n \"parameters\",\n \"metadata\",\n \"identity-source\",\n ]),\n },\n) {}\n\nexport type OpenIdClientAuthentication =\n | { readonly method: \"client_secret_basic\"; readonly secret: Redacted.Redacted<string> }\n | { readonly method: \"client_secret_post\"; readonly secret: Redacted.Redacted<string> }\n | { readonly method: \"none\"; readonly publicClient: true };\n\nexport interface PlainOAuthIdentity {\n readonly subject: string;\n readonly profile?: OAuthVerifiedExternalIdentity[\"profile\"];\n}\n\ninterface ProviderGeneration {\n readonly provider: OAuthProtocolConfiguration[\"provider\"];\n readonly configurationGeneration: OAuthProtocolConfiguration[\"configurationGeneration\"];\n readonly issuance: \"active\" | \"retired\";\n /** Preserve this exact issuer identifier, including an optional trailing slash. */\n readonly issuer: OAuthProtocolConfiguration[\"issuer\"];\n readonly responseIssuerMode: OAuthProtocolConfiguration[\"responseIssuerMode\"];\n readonly clientId: string;\n readonly authentication: OpenIdClientAuthentication;\n readonly callbacks: ReadonlyArray<{\n readonly callbackId: OAuthProtocolConfiguration[\"callbackId\"];\n readonly redirectUri: OAuthProtocolConfiguration[\"redirectUri\"];\n }>;\n readonly scopes: ReadonlyArray<string>;\n readonly authorizationParameters?: Readonly<Record<string, string>>;\n readonly tokenParameters?: Readonly<Record<string, string>>;\n}\n\nexport interface OpenIdClientOidcProvider extends ProviderGeneration {\n readonly protocol: \"oidc\";\n readonly idTokenSignedResponseAlg: \"RS256\";\n readonly maxAgeSeconds?: number;\n}\n\nexport interface OpenIdClientOAuthProvider<R = never> extends ProviderGeneration {\n readonly protocol: \"oauth\";\n readonly authorizationEndpoint: string;\n readonly tokenEndpoint: string;\n readonly pkceS256: true;\n readonly identitySource: {\n readonly url: string;\n readonly headers?: Readonly<Record<string, string>>;\n /** Receives only the freshly fetched authenticated identity body, never a grant. */\n readonly decodeIdentity: (\n body: unknown,\n ) => Effect.Effect<PlainOAuthIdentity, OAuthProtocolRejected, R>;\n };\n}\n\nexport interface OpenIdClientOAuthProtocolOptions<R = never> {\n readonly providers: ReadonlyArray<OpenIdClientOidcProvider | OpenIdClientOAuthProvider<R>>;\n /** Per-request deadline; the method separately limits the complete exchange. */\n readonly timeoutSeconds: number;\n /** Trusted server transport. Must honor abort and must not retry or log credentials. */\n readonly fetch?: CustomFetch;\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"models.mjs","names":[],"sources":["../../../src/oauth/openid-client/models.ts"],"sourcesContent":["import { type Effect, type Redacted, Schema } from \"effect\";\nimport type { CustomFetch } from \"openid-client\";\n\nimport type { OAuthProtocolRejected } from \"../signInErrors\";\nimport type { OAuthProtocolConfiguration, OAuthVerifiedExternalIdentity } from \"../signInModels\";\nimport type { TokenCompatibility, tokenCompatibility } from \"./compatibility\";\n\nexport class OpenIdClientConfigurationError extends Schema.TaggedError<OpenIdClientConfigurationError>()(\n \"OpenIdClientConfigurationError\",\n {\n reason: Schema.Literals([\n \"provider\",\n \"generation\",\n \"issuer\",\n \"callback\",\n \"authentication\",\n \"parameters\",\n \"metadata\",\n \"identity-source\",\n ]),\n },\n) {}\n\nexport type OpenIdClientAuthentication =\n | { readonly method: \"client_secret_basic\"; readonly secret: Redacted.Redacted<string> }\n | { readonly method: \"client_secret_post\"; readonly secret: Redacted.Redacted<string> }\n | { readonly method: \"none\"; readonly publicClient: true };\n\nexport interface PlainOAuthIdentity {\n readonly subject: string;\n readonly profile?: OAuthVerifiedExternalIdentity[\"profile\"];\n}\n\ninterface ProviderGeneration {\n readonly provider: OAuthProtocolConfiguration[\"provider\"];\n readonly configurationGeneration: OAuthProtocolConfiguration[\"configurationGeneration\"];\n readonly issuance: \"active\" | \"retired\";\n /** Preserve this exact issuer identifier, including an optional trailing slash. */\n readonly issuer: OAuthProtocolConfiguration[\"issuer\"];\n readonly responseIssuerMode: OAuthProtocolConfiguration[\"responseIssuerMode\"];\n readonly clientId: string;\n readonly authentication: OpenIdClientAuthentication;\n readonly callbacks: ReadonlyArray<{\n readonly callbackId: OAuthProtocolConfiguration[\"callbackId\"];\n readonly redirectUri: OAuthProtocolConfiguration[\"redirectUri\"];\n }>;\n readonly scopes: ReadonlyArray<string>;\n readonly authorizationParameters?: Readonly<Record<string, string>>;\n readonly tokenParameters?: Readonly<Record<string, string>>;\n}\n\nexport interface OpenIdClientOidcProvider extends ProviderGeneration {\n readonly protocol: \"oidc\";\n readonly idTokenSignedResponseAlg: \"RS256\";\n readonly maxAgeSeconds?: number;\n}\n\nexport interface OpenIdClientOAuthProvider<R = never> extends ProviderGeneration {\n /** @internal First-party provider behavior, retained by the configuration codec. */\n readonly [tokenCompatibility]?: TokenCompatibility;\n readonly protocol: \"oauth\";\n readonly authorizationEndpoint: string;\n readonly tokenEndpoint: string;\n readonly pkceS256: true;\n readonly identitySource: {\n readonly url: string;\n readonly headers?: Readonly<Record<string, string>>;\n /** Receives only the freshly fetched authenticated identity body, never a grant. */\n readonly decodeIdentity: (\n body: unknown,\n ) => Effect.Effect<PlainOAuthIdentity, OAuthProtocolRejected, R>;\n };\n}\n\nexport interface OpenIdClientOAuthProtocolOptions<R = never> {\n readonly providers: ReadonlyArray<OpenIdClientOidcProvider | OpenIdClientOAuthProvider<R>>;\n /** Per-request deadline; the method separately limits the complete exchange. */\n readonly timeoutSeconds: number;\n /** Trusted server transport. Must honor abort and must not retry or log credentials. */\n readonly fetch?: CustomFetch;\n}\n"],"mappings":";;AAOA,IAAa,iCAAb,cAAoD,OAAO,YAA4C,CAAC,CACtG,kCACA,EACE,QAAQ,OAAO,SAAS;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,EACH,CACF,CAAC,CAAC,CAAC"}
|
|
@@ -5,7 +5,6 @@ import { OAuthProtocolRejected, OAuthRejected, OAuthUnavailable } from "../signI
|
|
|
5
5
|
import { OAuthCallbackId, OAuthCodeResponse, OAuthProtocolConfiguration, OAuthProtocolPreparation, OAuthTransactionSecrets, OAuthVerifiedExternalIdentity } from "../signInModels.mjs";
|
|
6
6
|
import { OAuthProtocol } from "../OAuthProtocol.mjs";
|
|
7
7
|
import { OpenIdClientConfigurationError, OpenIdClientOAuthProtocolOptions } from "./models.mjs";
|
|
8
|
-
import "./compatibility.mjs";
|
|
9
8
|
import { DateTime, Effect, Layer } from "effect";
|
|
10
9
|
//#region src/oauth/openid-client/protocol.d.ts
|
|
11
10
|
declare const makeOpenIdClientOAuthProtocol: <R = never>(options: OpenIdClientOAuthProtocolOptions<R>) => Effect.Effect<{
|
|
@@ -5,7 +5,7 @@ import { OAuthCallbackId, OAuthCodeResponse, OAuthDisplayProfile, OAuthProtocolC
|
|
|
5
5
|
import { OAuthProtocolRejected, OAuthRejected, OAuthUnavailable } from "../signInErrors.mjs";
|
|
6
6
|
import { snapshotOAuth } from "../signInSnapshot.mjs";
|
|
7
7
|
import { OAuthProtocol } from "../OAuthProtocol.mjs";
|
|
8
|
-
import { DefiniteTokenRejection } from "./compatibility.mjs";
|
|
8
|
+
import { DefiniteTokenRejection, tokenCompatibility } from "./compatibility.mjs";
|
|
9
9
|
import { boundedFetch } from "./transport.mjs";
|
|
10
10
|
import { clientAuthentication, installConfigurations, makeAuthorizationParameters } from "./configuration.mjs";
|
|
11
11
|
import { Cause, DateTime, Effect, Layer, Redacted, Schema } from "effect";
|
|
@@ -55,8 +55,9 @@ const grantError = (error) => {
|
|
|
55
55
|
if (error instanceof client.ResponseBodyError && error.status === 400 && error.error === "invalid_grant") return rejected();
|
|
56
56
|
return unavailable();
|
|
57
57
|
};
|
|
58
|
-
const privateConfiguration = (entry, timeout, fetch, signal
|
|
58
|
+
const privateConfiguration = (entry, timeout, fetch, signal) => {
|
|
59
59
|
const provider = entry.provider;
|
|
60
|
+
const compatibility = provider.protocol === "oauth" ? provider[tokenCompatibility] : void 0;
|
|
60
61
|
const configuration = new client.Configuration(entry.metadata, provider.clientId, {
|
|
61
62
|
[client.clockSkew]: 0,
|
|
62
63
|
[client.clockTolerance]: 0,
|
|
@@ -85,7 +86,7 @@ const privateConfiguration = (entry, timeout, fetch, signal, compatibility) => {
|
|
|
85
86
|
if (provider.protocol === "oidc") client.enableNonRepudiationChecks(configuration);
|
|
86
87
|
return configuration;
|
|
87
88
|
};
|
|
88
|
-
const
|
|
89
|
+
const makeOpenIdClientOAuthProtocol = Effect.fn("makeOpenIdClientOAuthProtocol")(function* (options) {
|
|
89
90
|
const context = yield* Effect.context();
|
|
90
91
|
const { installed, fetch, timeoutSeconds } = yield* installConfigurations(options);
|
|
91
92
|
const prepareAuthorization = Effect.fn("OpenIdClient.prepareAuthorization")(function* (input) {
|
|
@@ -96,7 +97,7 @@ const makeOAuthProtocolWithCompatibility = Effect.fn("makeOpenIdClientOAuthProto
|
|
|
96
97
|
if (entry === void 0 || provider === void 0 || callback === void 0) return yield* OAuthRejected.make({});
|
|
97
98
|
const result = yield* Effect.tryPromise({
|
|
98
99
|
try: async (signal) => {
|
|
99
|
-
const configuration = privateConfiguration(entry, timeoutSeconds, fetch, signal
|
|
100
|
+
const configuration = privateConfiguration(entry, timeoutSeconds, fetch, signal);
|
|
100
101
|
const state = client.randomState();
|
|
101
102
|
const verifier = client.randomPKCECodeVerifier();
|
|
102
103
|
const nonce = provider.protocol === "oidc" ? client.randomNonce() : void 0;
|
|
@@ -143,7 +144,7 @@ const makeOAuthProtocolWithCompatibility = Effect.fn("makeOpenIdClientOAuthProto
|
|
|
143
144
|
if (startedAt < 0 || startedAt > DateTime.toEpochMillis(yield* DateTime.now)) return yield* rejected();
|
|
144
145
|
const exchanged = yield* Effect.tryPromise({
|
|
145
146
|
try: async (signal) => {
|
|
146
|
-
const configuration = privateConfiguration(entry, timeoutSeconds, fetch, signal
|
|
147
|
+
const configuration = privateConfiguration(entry, timeoutSeconds, fetch, signal);
|
|
147
148
|
const currentUrl = new URL(saved.redirectUri);
|
|
148
149
|
currentUrl.searchParams.set("code", Redacted.value(request.response.code));
|
|
149
150
|
currentUrl.searchParams.set("state", Redacted.value(request.response.state));
|
|
@@ -210,9 +211,8 @@ const makeOAuthProtocolWithCompatibility = Effect.fn("makeOpenIdClientOAuthProto
|
|
|
210
211
|
exchangeVerifiedIdentity: (input) => unavailableOnDefect(exchangeVerifiedIdentity(input))
|
|
211
212
|
});
|
|
212
213
|
}, unavailableOnDefect);
|
|
213
|
-
const makeOpenIdClientOAuthProtocol = (options) => makeOAuthProtocolWithCompatibility(options);
|
|
214
214
|
const openIdClientOAuthProtocolLayer = (options) => Layer.effect(OAuthProtocol, makeOpenIdClientOAuthProtocol(options));
|
|
215
215
|
//#endregion
|
|
216
|
-
export {
|
|
216
|
+
export { makeOpenIdClientOAuthProtocol, openIdClientOAuthProtocolLayer };
|
|
217
217
|
|
|
218
218
|
//# sourceMappingURL=protocol.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.mjs","names":[],"sources":["../../../src/oauth/openid-client/protocol.ts"],"sourcesContent":["import { Cause, DateTime, Effect, Layer, Redacted, Schema } from \"effect\";\nimport * as client from \"openid-client\";\n\nimport { reportAuthFailure } from \"../../internal/diagnostics\";\nimport { RequestBindingFlowId } from \"../../operations/requestBinding\";\nimport { OAuthProtocol } from \"../OAuthProtocol\";\nimport { OAuthProviderKey } from \"../schema\";\nimport { OAuthProtocolRejected, OAuthRejected, OAuthUnavailable } from \"../signInErrors\";\nimport {\n OAuthCallbackId,\n OAuthCodeResponse,\n OAuthDisplayProfile,\n OAuthProtocolConfiguration,\n OAuthProtocolPreparation,\n OAuthTransactionSecrets,\n OAuthVerifiedExternalIdentity,\n} from \"../signInModels\";\nimport { snapshotOAuth } from \"../signInSnapshot\";\nimport { DefiniteTokenRejection, type TokenCompatibility } from \"./compatibility\";\nimport {\n clientAuthentication,\n installConfigurations,\n makeAuthorizationParameters,\n type InstalledProvider,\n} from \"./configuration\";\nimport {\n type OpenIdClientConfigurationError,\n type OpenIdClientOAuthProtocolOptions,\n} from \"./models\";\nimport { boundedFetch } from \"./transport\";\n\nconst beginInput = Schema.Struct({\n provider: OAuthProviderKey,\n callbackId: OAuthCallbackId,\n flowId: RequestBindingFlowId,\n});\n\nconst exchangeInput = Schema.toType(\n Schema.Struct({\n configuration: OAuthProtocolConfiguration,\n response: OAuthCodeResponse,\n secrets: OAuthTransactionSecrets,\n verificationStartedAt: Schema.DateTimeUtcFromMillis,\n }),\n);\n\nconst numericDate = Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 8640000000000 }));\n\nconst claimsSchema = Schema.Struct({\n iss: Schema.String,\n sub: OAuthVerifiedExternalIdentity.fields.identity.fields.subject,\n aud: Schema.Union([\n Schema.String,\n Schema.Array(Schema.String).check(Schema.isMinLength(1), Schema.isMaxLength(1)),\n ]),\n azp: Schema.optionalKey(Schema.String),\n exp: numericDate,\n iat: numericDate,\n nbf: Schema.optionalKey(numericDate),\n auth_time: Schema.optionalKey(numericDate),\n});\n\nconst plainIdentitySchema = Schema.Struct({\n subject: OAuthVerifiedExternalIdentity.fields.identity.fields.subject,\n profile: Schema.optionalKey(OAuthDisplayProfile),\n});\n\nconst unavailable = () => OAuthUnavailable.make({});\nconst rejected = () => OAuthProtocolRejected.make({});\n\nconst unavailableOnDefect = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n effect.pipe(\n Effect.tapCause((cause) =>\n Cause.hasDies(cause) ? reportAuthFailure(\"oauth-protocol\", cause) : Effect.void,\n ),\n Effect.catchCause((cause): Effect.Effect<never, E | OAuthUnavailable> => {\n if (Cause.hasInterrupts(cause)) return Effect.interrupt;\n if (Cause.hasDies(cause)) return Effect.fail(unavailable());\n\n return Effect.failCause(cause);\n }),\n );\n\n/** Only precise claim errors and a fully parsed invalid_grant are definite.\n * INVALID_RESPONSE also covers signature/key/transport faults; keep it ambiguous. */\nconst grantError = (error: unknown) => {\n if (\n error instanceof DefiniteTokenRejection ||\n (error instanceof client.ClientError && error.cause instanceof DefiniteTokenRejection)\n )\n return rejected();\n if (\n error instanceof client.ClientError &&\n (error.code === \"OAUTH_JWT_CLAIM_COMPARISON_FAILED\" ||\n error.code === \"OAUTH_JWT_TIMESTAMP_CHECK_FAILED\")\n )\n return rejected();\n if (\n error instanceof client.ResponseBodyError &&\n error.status === 400 &&\n error.error === \"invalid_grant\"\n )\n return rejected();\n\n return unavailable();\n};\n\nconst privateConfiguration = <R>(\n entry: InstalledProvider<R>,\n timeout: number,\n fetch: client.CustomFetch,\n signal: AbortSignal,\n compatibility?: TokenCompatibility,\n) => {\n const provider = entry.provider;\n\n const configuration = new client.Configuration(\n entry.metadata,\n provider.clientId,\n {\n [client.clockSkew]: 0,\n [client.clockTolerance]: 0,\n ...(provider.protocol === \"oidc\"\n ? { id_token_signed_response_alg: provider.idTokenSignedResponseAlg }\n : {}),\n },\n clientAuthentication(provider.authentication),\n );\n\n configuration.timeout = timeout;\n const transport = boundedFetch(fetch, signal, entry.allowedUrls);\n\n configuration[client.customFetch] =\n compatibility === undefined\n ? transport\n : async (url, options) => {\n const response = await transport(url, options);\n\n if (url === new URL(entry.metadata.token_endpoint!).href) {\n const body: unknown = await response.clone().json();\n\n signal.throwIfAborted();\n compatibility.inspectReceipt(\n { body, status: response.status, contentType: response.headers.get(\"content-type\") },\n {\n scopes: provider.scopes,\n refreshRequired: false,\n operation: \"authorization_code\",\n },\n );\n signal.throwIfAborted();\n }\n\n return response;\n };\n if (provider.protocol === \"oidc\") client.enableNonRepudiationChecks(configuration);\n\n return configuration;\n};\n\nexport const makeOAuthProtocolWithCompatibility = Effect.fn(\"makeOpenIdClientOAuthProtocol\")(\n function* <R = never>(\n options: OpenIdClientOAuthProtocolOptions<R>,\n compatibility?: TokenCompatibility,\n ): Effect.fn.Return<\n OAuthProtocol[\"Service\"],\n OpenIdClientConfigurationError | OAuthUnavailable,\n R\n > {\n const context = yield* Effect.context<R>();\n const { installed, fetch, timeoutSeconds } = yield* installConfigurations(options);\n\n const prepareAuthorization: OAuthProtocol[\"Service\"][\"prepareAuthorization\"] = Effect.fn(\n \"OpenIdClient.prepareAuthorization\",\n )(function* (input) {\n const request = yield* Schema.decodeEffect(beginInput)(input).pipe(\n Effect.mapError(() => OAuthRejected.make({})),\n );\n\n const entry = installed.find(\n ({ provider }) => provider.issuance === \"active\" && provider.provider === request.provider,\n );\n\n const provider = entry?.provider;\n\n const callback = provider?.callbacks.find(\n (candidate) => candidate.callbackId === request.callbackId,\n );\n\n if (entry === undefined || provider === undefined || callback === undefined)\n return yield* OAuthRejected.make({});\n\n const result = yield* Effect.tryPromise({\n try: async (signal) => {\n const configuration = privateConfiguration(\n entry,\n timeoutSeconds,\n fetch,\n signal,\n compatibility,\n );\n\n const state = client.randomState();\n const verifier = client.randomPKCECodeVerifier();\n const nonce = provider.protocol === \"oidc\" ? client.randomNonce() : undefined;\n const challenge = await client.calculatePKCECodeChallenge(verifier);\n\n signal.throwIfAborted();\n\n const url = client.buildAuthorizationUrl(\n configuration,\n makeAuthorizationParameters(provider, callback.redirectUri, {\n state,\n challenge,\n ...(nonce === undefined ? {} : { nonce }),\n }),\n );\n\n return {\n configuration: {\n provider: provider.provider,\n protocol: provider.protocol,\n configurationGeneration: provider.configurationGeneration,\n issuer: provider.issuer,\n responseIssuerMode: provider.responseIssuerMode,\n callbackId: callback.callbackId,\n redirectUri: callback.redirectUri,\n },\n authorizationUrl: Redacted.make(url.href),\n secrets: {\n namespace: \"effect-auth/oauth-transaction-secrets/v1\" as const,\n state: Redacted.make(state),\n pkceVerifier: Redacted.make(verifier),\n ...(nonce === undefined ? {} : { oidcNonce: Redacted.make(nonce) }),\n },\n };\n },\n catch: unavailable,\n });\n\n return yield* snapshotOAuth(OAuthProtocolPreparation, result);\n });\n\n const exchangeVerifiedIdentity: OAuthProtocol[\"Service\"][\"exchangeVerifiedIdentity\"] =\n Effect.fn(\"OpenIdClient.exchangeVerifiedIdentity\")(function* (input) {\n const request = yield* snapshotOAuth(exchangeInput, input);\n const saved = request.configuration;\n\n const entry = installed.find(\n ({ provider }) =>\n provider.provider === saved.provider &&\n provider.configurationGeneration === saved.configurationGeneration,\n );\n\n if (entry === undefined) return yield* unavailable();\n const provider = entry.provider;\n\n const callback = provider.callbacks.find(\n (candidate) => candidate.callbackId === saved.callbackId,\n );\n\n if (\n provider.protocol !== saved.protocol ||\n provider.issuer !== saved.issuer ||\n provider.responseIssuerMode !== saved.responseIssuerMode ||\n callback?.redirectUri !== saved.redirectUri\n )\n return yield* unavailable();\n if (\n (provider.protocol === \"oidc\") !== (request.secrets.oidcNonce !== undefined) ||\n Redacted.value(request.response.state) !== Redacted.value(request.secrets.state) ||\n (provider.responseIssuerMode === \"required\"\n ? request.response.issuer !== provider.issuer\n : request.response.issuer !== undefined)\n )\n return yield* rejected();\n const startedAt = DateTime.toEpochMillis(request.verificationStartedAt);\n\n if (startedAt < 0 || startedAt > DateTime.toEpochMillis(yield* DateTime.now))\n return yield* rejected();\n\n const exchanged = yield* Effect.tryPromise({\n try: async (signal) => {\n const configuration = privateConfiguration(\n entry,\n timeoutSeconds,\n fetch,\n signal,\n compatibility,\n );\n\n const currentUrl = new URL(saved.redirectUri);\n\n currentUrl.searchParams.set(\"code\", Redacted.value(request.response.code));\n currentUrl.searchParams.set(\"state\", Redacted.value(request.response.state));\n if (request.response.issuer !== undefined)\n currentUrl.searchParams.set(\"iss\", request.response.issuer);\n\n const tokens = await client.authorizationCodeGrant(\n configuration,\n currentUrl,\n {\n pkceCodeVerifier: Redacted.value(request.secrets.pkceVerifier),\n expectedState: Redacted.value(request.secrets.state),\n ...(provider.protocol === \"oidc\"\n ? {\n expectedNonce: Redacted.value(request.secrets.oidcNonce!),\n idTokenExpected: true,\n ...(provider.maxAgeSeconds === undefined\n ? {}\n : { maxAge: provider.maxAgeSeconds }),\n }\n : {}),\n },\n provider.tokenParameters,\n );\n\n signal.throwIfAborted();\n if (provider.protocol === \"oidc\")\n return { protocol: \"oidc\" as const, claims: tokens.claims() };\n if (tokens.token_type !== \"bearer\") throw unavailable();\n\n const response = await client.fetchProtectedResource(\n configuration,\n tokens.access_token,\n new URL(provider.identitySource.url),\n \"GET\",\n undefined,\n new Headers(provider.identitySource.headers),\n );\n\n signal.throwIfAborted();\n if (\n response.status !== 200 ||\n response.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim().toLowerCase() !==\n \"application/json\"\n )\n throw unavailable();\n const body: unknown = await response.json();\n\n signal.throwIfAborted();\n\n return { protocol: \"oauth\" as const, body };\n },\n catch: grantError,\n });\n\n if (exchanged.protocol === \"oidc\") {\n // oxlint-disable-next-line no-restricted-properties -- Project validated foreign ID-token claims into the adapter's stricter bounded profile.\n const claims = yield* Schema.decodeUnknownEffect(claimsSchema)(exchanged.claims).pipe(\n Effect.mapError(rejected),\n );\n\n const now = DateTime.toEpochMillis(yield* DateTime.now) / 1000;\n const audience = typeof claims.aud === \"string\" ? claims.aud : claims.aud[0];\n\n if (\n provider.protocol !== \"oidc\" ||\n claims.iss !== provider.issuer ||\n audience !== provider.clientId ||\n (claims.azp !== undefined && claims.azp !== provider.clientId) ||\n claims.exp <= now ||\n claims.iat > now ||\n (claims.nbf !== undefined && claims.nbf > now) ||\n (claims.auth_time !== undefined && claims.auth_time > now) ||\n (provider.maxAgeSeconds !== undefined &&\n (claims.auth_time === undefined ||\n claims.auth_time + provider.maxAgeSeconds < Math.floor(now)))\n )\n return yield* rejected();\n\n return yield* snapshotOAuth(OAuthVerifiedExternalIdentity, {\n identity: { provider: provider.provider, issuer: provider.issuer, subject: claims.sub },\n ...(claims.auth_time === undefined\n ? {}\n : {\n upstreamAuthenticatedAt: DateTime.makeUnsafe(\n Math.min(startedAt, claims.auth_time * 1000),\n ),\n }),\n });\n }\n if (provider.protocol !== \"oauth\") return yield* unavailable();\n\n const decoded = yield* Effect.suspend(() =>\n provider.identitySource.decodeIdentity(exchanged.body),\n ).pipe(\n Effect.provideContext(context),\n Effect.catchCause(\n (cause): Effect.Effect<never, OAuthProtocolRejected | OAuthUnavailable> => {\n if (Cause.hasInterrupts(cause))\n return reportAuthFailure(\"oauth-identity\", cause).pipe(\n Effect.andThen(Effect.interrupt),\n );\n if (\n cause.reasons.length === 1 &&\n cause.reasons[0]?._tag === \"Fail\" &&\n Schema.is(OAuthProtocolRejected)(cause.reasons[0].error)\n )\n return Effect.fail(rejected());\n\n return reportAuthFailure(\"oauth-identity\", cause).pipe(\n Effect.andThen(Effect.fail(unavailable())),\n );\n },\n ),\n );\n\n const identity = yield* Schema.decodeEffect(plainIdentitySchema)(decoded).pipe(\n Effect.mapError(rejected),\n );\n\n return yield* snapshotOAuth(OAuthVerifiedExternalIdentity, {\n identity: {\n provider: provider.provider,\n issuer: provider.issuer,\n subject: identity.subject,\n },\n ...(identity.profile === undefined ? {} : { profile: identity.profile }),\n });\n });\n\n return OAuthProtocol.of({\n prepareAuthorization: (input) => unavailableOnDefect(prepareAuthorization(input)),\n exchangeVerifiedIdentity: (input) => unavailableOnDefect(exchangeVerifiedIdentity(input)),\n });\n },\n unavailableOnDefect,\n);\n\nexport const makeOpenIdClientOAuthProtocol = <R = never>(\n options: OpenIdClientOAuthProtocolOptions<R>,\n) => makeOAuthProtocolWithCompatibility(options);\n\nexport const openIdClientOAuthProtocolLayer = <R = never>(\n options: OpenIdClientOAuthProtocolOptions<R>,\n) => Layer.effect(OAuthProtocol, makeOpenIdClientOAuthProtocol(options));\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"protocol.mjs","names":[],"sources":["../../../src/oauth/openid-client/protocol.ts"],"sourcesContent":["import { Cause, DateTime, Effect, Layer, Redacted, Schema } from \"effect\";\nimport * as client from \"openid-client\";\n\nimport { reportAuthFailure } from \"../../internal/diagnostics\";\nimport { RequestBindingFlowId } from \"../../operations/requestBinding\";\nimport { OAuthProtocol } from \"../OAuthProtocol\";\nimport { OAuthProviderKey } from \"../schema\";\nimport { OAuthProtocolRejected, OAuthRejected, OAuthUnavailable } from \"../signInErrors\";\nimport {\n OAuthCallbackId,\n OAuthCodeResponse,\n OAuthDisplayProfile,\n OAuthProtocolConfiguration,\n OAuthProtocolPreparation,\n OAuthTransactionSecrets,\n OAuthVerifiedExternalIdentity,\n} from \"../signInModels\";\nimport { snapshotOAuth } from \"../signInSnapshot\";\nimport { DefiniteTokenRejection, tokenCompatibility } from \"./compatibility\";\nimport {\n clientAuthentication,\n installConfigurations,\n makeAuthorizationParameters,\n type InstalledProvider,\n} from \"./configuration\";\nimport {\n type OpenIdClientConfigurationError,\n type OpenIdClientOAuthProtocolOptions,\n} from \"./models\";\nimport { boundedFetch } from \"./transport\";\n\nconst beginInput = Schema.Struct({\n provider: OAuthProviderKey,\n callbackId: OAuthCallbackId,\n flowId: RequestBindingFlowId,\n});\n\nconst exchangeInput = Schema.toType(\n Schema.Struct({\n configuration: OAuthProtocolConfiguration,\n response: OAuthCodeResponse,\n secrets: OAuthTransactionSecrets,\n verificationStartedAt: Schema.DateTimeUtcFromMillis,\n }),\n);\n\nconst numericDate = Schema.Finite.check(Schema.isBetween({ minimum: 0, maximum: 8640000000000 }));\n\nconst claimsSchema = Schema.Struct({\n iss: Schema.String,\n sub: OAuthVerifiedExternalIdentity.fields.identity.fields.subject,\n aud: Schema.Union([\n Schema.String,\n Schema.Array(Schema.String).check(Schema.isMinLength(1), Schema.isMaxLength(1)),\n ]),\n azp: Schema.optionalKey(Schema.String),\n exp: numericDate,\n iat: numericDate,\n nbf: Schema.optionalKey(numericDate),\n auth_time: Schema.optionalKey(numericDate),\n});\n\nconst plainIdentitySchema = Schema.Struct({\n subject: OAuthVerifiedExternalIdentity.fields.identity.fields.subject,\n profile: Schema.optionalKey(OAuthDisplayProfile),\n});\n\nconst unavailable = () => OAuthUnavailable.make({});\nconst rejected = () => OAuthProtocolRejected.make({});\n\nconst unavailableOnDefect = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n effect.pipe(\n Effect.tapCause((cause) =>\n Cause.hasDies(cause) ? reportAuthFailure(\"oauth-protocol\", cause) : Effect.void,\n ),\n Effect.catchCause((cause): Effect.Effect<never, E | OAuthUnavailable> => {\n if (Cause.hasInterrupts(cause)) return Effect.interrupt;\n if (Cause.hasDies(cause)) return Effect.fail(unavailable());\n\n return Effect.failCause(cause);\n }),\n );\n\n/** Only precise claim errors and a fully parsed invalid_grant are definite.\n * INVALID_RESPONSE also covers signature/key/transport faults; keep it ambiguous. */\nconst grantError = (error: unknown) => {\n if (\n error instanceof DefiniteTokenRejection ||\n (error instanceof client.ClientError && error.cause instanceof DefiniteTokenRejection)\n )\n return rejected();\n if (\n error instanceof client.ClientError &&\n (error.code === \"OAUTH_JWT_CLAIM_COMPARISON_FAILED\" ||\n error.code === \"OAUTH_JWT_TIMESTAMP_CHECK_FAILED\")\n )\n return rejected();\n if (\n error instanceof client.ResponseBodyError &&\n error.status === 400 &&\n error.error === \"invalid_grant\"\n )\n return rejected();\n\n return unavailable();\n};\n\nconst privateConfiguration = <R>(\n entry: InstalledProvider<R>,\n timeout: number,\n fetch: client.CustomFetch,\n signal: AbortSignal,\n) => {\n const provider = entry.provider;\n const compatibility = provider.protocol === \"oauth\" ? provider[tokenCompatibility] : undefined;\n\n const configuration = new client.Configuration(\n entry.metadata,\n provider.clientId,\n {\n [client.clockSkew]: 0,\n [client.clockTolerance]: 0,\n ...(provider.protocol === \"oidc\"\n ? { id_token_signed_response_alg: provider.idTokenSignedResponseAlg }\n : {}),\n },\n clientAuthentication(provider.authentication),\n );\n\n configuration.timeout = timeout;\n const transport = boundedFetch(fetch, signal, entry.allowedUrls);\n\n configuration[client.customFetch] =\n compatibility === undefined\n ? transport\n : async (url, options) => {\n const response = await transport(url, options);\n\n if (url === new URL(entry.metadata.token_endpoint!).href) {\n const body: unknown = await response.clone().json();\n\n signal.throwIfAborted();\n compatibility.inspectReceipt(\n { body, status: response.status, contentType: response.headers.get(\"content-type\") },\n {\n scopes: provider.scopes,\n refreshRequired: false,\n operation: \"authorization_code\",\n },\n );\n signal.throwIfAborted();\n }\n\n return response;\n };\n if (provider.protocol === \"oidc\") client.enableNonRepudiationChecks(configuration);\n\n return configuration;\n};\n\nexport const makeOpenIdClientOAuthProtocol = Effect.fn(\"makeOpenIdClientOAuthProtocol\")(\n // Capture one provider table; each generation retains its own receipt rules.\n function* <R = never>(\n options: OpenIdClientOAuthProtocolOptions<R>,\n ): Effect.fn.Return<\n OAuthProtocol[\"Service\"],\n OpenIdClientConfigurationError | OAuthUnavailable,\n R\n > {\n const context = yield* Effect.context<R>();\n const { installed, fetch, timeoutSeconds } = yield* installConfigurations(options);\n\n const prepareAuthorization: OAuthProtocol[\"Service\"][\"prepareAuthorization\"] = Effect.fn(\n \"OpenIdClient.prepareAuthorization\",\n )(function* (input) {\n const request = yield* Schema.decodeEffect(beginInput)(input).pipe(\n Effect.mapError(() => OAuthRejected.make({})),\n );\n\n const entry = installed.find(\n ({ provider }) => provider.issuance === \"active\" && provider.provider === request.provider,\n );\n\n const provider = entry?.provider;\n\n const callback = provider?.callbacks.find(\n (candidate) => candidate.callbackId === request.callbackId,\n );\n\n if (entry === undefined || provider === undefined || callback === undefined)\n return yield* OAuthRejected.make({});\n\n const result = yield* Effect.tryPromise({\n try: async (signal) => {\n const configuration = privateConfiguration(entry, timeoutSeconds, fetch, signal);\n\n const state = client.randomState();\n const verifier = client.randomPKCECodeVerifier();\n const nonce = provider.protocol === \"oidc\" ? client.randomNonce() : undefined;\n const challenge = await client.calculatePKCECodeChallenge(verifier);\n\n signal.throwIfAborted();\n\n const url = client.buildAuthorizationUrl(\n configuration,\n makeAuthorizationParameters(provider, callback.redirectUri, {\n state,\n challenge,\n ...(nonce === undefined ? {} : { nonce }),\n }),\n );\n\n return {\n configuration: {\n provider: provider.provider,\n protocol: provider.protocol,\n configurationGeneration: provider.configurationGeneration,\n issuer: provider.issuer,\n responseIssuerMode: provider.responseIssuerMode,\n callbackId: callback.callbackId,\n redirectUri: callback.redirectUri,\n },\n authorizationUrl: Redacted.make(url.href),\n secrets: {\n namespace: \"effect-auth/oauth-transaction-secrets/v1\" as const,\n state: Redacted.make(state),\n pkceVerifier: Redacted.make(verifier),\n ...(nonce === undefined ? {} : { oidcNonce: Redacted.make(nonce) }),\n },\n };\n },\n catch: unavailable,\n });\n\n return yield* snapshotOAuth(OAuthProtocolPreparation, result);\n });\n\n const exchangeVerifiedIdentity: OAuthProtocol[\"Service\"][\"exchangeVerifiedIdentity\"] =\n Effect.fn(\"OpenIdClient.exchangeVerifiedIdentity\")(function* (input) {\n const request = yield* snapshotOAuth(exchangeInput, input);\n const saved = request.configuration;\n\n const entry = installed.find(\n ({ provider }) =>\n provider.provider === saved.provider &&\n provider.configurationGeneration === saved.configurationGeneration,\n );\n\n if (entry === undefined) return yield* unavailable();\n const provider = entry.provider;\n\n const callback = provider.callbacks.find(\n (candidate) => candidate.callbackId === saved.callbackId,\n );\n\n if (\n provider.protocol !== saved.protocol ||\n provider.issuer !== saved.issuer ||\n provider.responseIssuerMode !== saved.responseIssuerMode ||\n callback?.redirectUri !== saved.redirectUri\n )\n return yield* unavailable();\n if (\n (provider.protocol === \"oidc\") !== (request.secrets.oidcNonce !== undefined) ||\n Redacted.value(request.response.state) !== Redacted.value(request.secrets.state) ||\n (provider.responseIssuerMode === \"required\"\n ? request.response.issuer !== provider.issuer\n : request.response.issuer !== undefined)\n )\n return yield* rejected();\n const startedAt = DateTime.toEpochMillis(request.verificationStartedAt);\n\n if (startedAt < 0 || startedAt > DateTime.toEpochMillis(yield* DateTime.now))\n return yield* rejected();\n\n const exchanged = yield* Effect.tryPromise({\n try: async (signal) => {\n const configuration = privateConfiguration(entry, timeoutSeconds, fetch, signal);\n\n const currentUrl = new URL(saved.redirectUri);\n\n currentUrl.searchParams.set(\"code\", Redacted.value(request.response.code));\n currentUrl.searchParams.set(\"state\", Redacted.value(request.response.state));\n if (request.response.issuer !== undefined)\n currentUrl.searchParams.set(\"iss\", request.response.issuer);\n\n const tokens = await client.authorizationCodeGrant(\n configuration,\n currentUrl,\n {\n pkceCodeVerifier: Redacted.value(request.secrets.pkceVerifier),\n expectedState: Redacted.value(request.secrets.state),\n ...(provider.protocol === \"oidc\"\n ? {\n expectedNonce: Redacted.value(request.secrets.oidcNonce!),\n idTokenExpected: true,\n ...(provider.maxAgeSeconds === undefined\n ? {}\n : { maxAge: provider.maxAgeSeconds }),\n }\n : {}),\n },\n provider.tokenParameters,\n );\n\n signal.throwIfAborted();\n if (provider.protocol === \"oidc\")\n return { protocol: \"oidc\" as const, claims: tokens.claims() };\n if (tokens.token_type !== \"bearer\") throw unavailable();\n\n const response = await client.fetchProtectedResource(\n configuration,\n tokens.access_token,\n new URL(provider.identitySource.url),\n \"GET\",\n undefined,\n new Headers(provider.identitySource.headers),\n );\n\n signal.throwIfAborted();\n if (\n response.status !== 200 ||\n response.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim().toLowerCase() !==\n \"application/json\"\n )\n throw unavailable();\n const body: unknown = await response.json();\n\n signal.throwIfAborted();\n\n return { protocol: \"oauth\" as const, body };\n },\n catch: grantError,\n });\n\n if (exchanged.protocol === \"oidc\") {\n // oxlint-disable-next-line no-restricted-properties -- Project validated foreign ID-token claims into the adapter's stricter bounded profile.\n const claims = yield* Schema.decodeUnknownEffect(claimsSchema)(exchanged.claims).pipe(\n Effect.mapError(rejected),\n );\n\n const now = DateTime.toEpochMillis(yield* DateTime.now) / 1000;\n const audience = typeof claims.aud === \"string\" ? claims.aud : claims.aud[0];\n\n if (\n provider.protocol !== \"oidc\" ||\n claims.iss !== provider.issuer ||\n audience !== provider.clientId ||\n (claims.azp !== undefined && claims.azp !== provider.clientId) ||\n claims.exp <= now ||\n claims.iat > now ||\n (claims.nbf !== undefined && claims.nbf > now) ||\n (claims.auth_time !== undefined && claims.auth_time > now) ||\n (provider.maxAgeSeconds !== undefined &&\n (claims.auth_time === undefined ||\n claims.auth_time + provider.maxAgeSeconds < Math.floor(now)))\n )\n return yield* rejected();\n\n return yield* snapshotOAuth(OAuthVerifiedExternalIdentity, {\n identity: { provider: provider.provider, issuer: provider.issuer, subject: claims.sub },\n ...(claims.auth_time === undefined\n ? {}\n : {\n upstreamAuthenticatedAt: DateTime.makeUnsafe(\n Math.min(startedAt, claims.auth_time * 1000),\n ),\n }),\n });\n }\n if (provider.protocol !== \"oauth\") return yield* unavailable();\n\n const decoded = yield* Effect.suspend(() =>\n provider.identitySource.decodeIdentity(exchanged.body),\n ).pipe(\n Effect.provideContext(context),\n Effect.catchCause(\n (cause): Effect.Effect<never, OAuthProtocolRejected | OAuthUnavailable> => {\n if (Cause.hasInterrupts(cause))\n return reportAuthFailure(\"oauth-identity\", cause).pipe(\n Effect.andThen(Effect.interrupt),\n );\n if (\n cause.reasons.length === 1 &&\n cause.reasons[0]?._tag === \"Fail\" &&\n Schema.is(OAuthProtocolRejected)(cause.reasons[0].error)\n )\n return Effect.fail(rejected());\n\n return reportAuthFailure(\"oauth-identity\", cause).pipe(\n Effect.andThen(Effect.fail(unavailable())),\n );\n },\n ),\n );\n\n const identity = yield* Schema.decodeEffect(plainIdentitySchema)(decoded).pipe(\n Effect.mapError(rejected),\n );\n\n return yield* snapshotOAuth(OAuthVerifiedExternalIdentity, {\n identity: {\n provider: provider.provider,\n issuer: provider.issuer,\n subject: identity.subject,\n },\n ...(identity.profile === undefined ? {} : { profile: identity.profile }),\n });\n });\n\n return OAuthProtocol.of({\n prepareAuthorization: (input) => unavailableOnDefect(prepareAuthorization(input)),\n exchangeVerifiedIdentity: (input) => unavailableOnDefect(exchangeVerifiedIdentity(input)),\n });\n },\n unavailableOnDefect,\n);\n\nexport const openIdClientOAuthProtocolLayer = <R = never>(\n options: OpenIdClientOAuthProtocolOptions<R>,\n) => Layer.effect(OAuthProtocol, makeOpenIdClientOAuthProtocol(options));\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@yielded/auth","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@yielded/auth","version":"0.1.0-beta.3","dependencies":{"@noble/ciphers":"2.1.1","@noble/hashes":"2.3.0"},"devDependencies":{"@cloudflare/workers-types":"5.20260825.1","@effect/platform-bun":"4.0.0-rc.112","@effect/platform-node":"4.0.0-rc.112","@effect/sql-d1":"4.0.0-rc.112","@effect/sql-libsql":"4.0.0-rc.112","@effect/sql-mysql2":"4.0.0-rc.112","@effect/sql-pg":"4.0.0-rc.112","@effect/sql-pglite":"4.0.0-rc.112","@effect/sql-sqlite-bun":"4.0.0-rc.112","@effect/sql-sqlite-do":"4.0.0-rc.112","@effect/sql-sqlite-node":"4.0.0-rc.112","@effect/sql-sqlite-wasm":"4.0.0-rc.112","@effect/vitest":"4.0.0-rc.112","@simplewebauthn/browser":"14.0.0","@simplewebauthn/server":"14.0.1","drizzle-orm":"1.0.0-rc.5-ab785fc","effect":"4.0.0-rc.112","effect-cf":"0.40.0","openid-client":"6.8.8","tldts":"7.4.11","typescript":"7.0.2","vite-plus":"0.3.0"},"peerDependencies":{"@effect/sql-d1":">=4.0.0-rc.112","@effect/sql-libsql":">=4.0.0-rc.112","@effect/sql-mysql2":">=4.0.0-rc.112","@effect/sql-pg":">=4.0.0-rc.112","@effect/sql-pglite":">=4.0.0-rc.112","@effect/sql-sqlite-bun":">=4.0.0-rc.112","@effect/sql-sqlite-do":">=4.0.0-rc.112","@effect/sql-sqlite-node":">=4.0.0-rc.112","@effect/sql-sqlite-wasm":">=4.0.0-rc.112","@simplewebauthn/browser":">=14.0.0 <15","@simplewebauthn/server":">=14.0.1 <15","drizzle-orm":">=1.0.0-rc.5-ab785fc","effect":"^4.0.0-rc.112","effect-cf":"^0.40.0","openid-client":">=6.8.8 <7","tldts":">=7.4.11 <8"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./Auth":{"types":"./dist/Auth.d.mts","default":"./dist/Auth.mjs"},"./Drizzle":{"types":"./dist/Drizzle.d.mts","default":"./dist/Drizzle.mjs"},"./DrizzleD1":{"types":"./dist/DrizzleD1.d.mts","default":"./dist/DrizzleD1.mjs"},"./DrizzleLibsql":{"types":"./dist/DrizzleLibsql.d.mts","default":"./dist/DrizzleLibsql.mjs"},"./DrizzleMysql2":{"types":"./dist/DrizzleMysql2.d.mts","default":"./dist/DrizzleMysql2.mjs"},"./DrizzlePglite":{"types":"./dist/DrizzlePglite.d.mts","default":"./dist/DrizzlePglite.mjs"},"./DrizzlePostgres":{"types":"./dist/DrizzlePostgres.d.mts","default":"./dist/DrizzlePostgres.mjs"},"./DrizzleSqliteBun":{"types":"./dist/DrizzleSqliteBun.d.mts","default":"./dist/DrizzleSqliteBun.mjs"},"./DrizzleSqliteDo":{"types":"./dist/DrizzleSqliteDo.d.mts","default":"./dist/DrizzleSqliteDo.mjs"},"./DrizzleSqliteNode":{"types":"./dist/DrizzleSqliteNode.d.mts","default":"./dist/DrizzleSqliteNode.mjs"},"./DrizzleSqliteWasm":{"types":"./dist/DrizzleSqliteWasm.d.mts","default":"./dist/DrizzleSqliteWasm.mjs"},"./Cloudflare":{"types":"./dist/Cloudflare.d.mts","default":"./dist/Cloudflare.mjs"},"./Http":{"types":"./dist/Http.d.mts","default":"./dist/Http.mjs"},"./HttpServer":{"types":"./dist/HttpServer.d.mts","default":"./dist/HttpServer.mjs"},"./OperationHttp":{"types":"./dist/OperationHttp.d.mts","default":"./dist/OperationHttp.mjs"},"./OperationHttpClient":{"types":"./dist/OperationHttpClient.d.mts","default":"./dist/OperationHttpClient.mjs"},"./OperationHttpServer":{"types":"./dist/OperationHttpServer.d.mts","default":"./dist/OperationHttpServer.mjs"},"./Atom":{"types":"./dist/Atom.d.mts","default":"./dist/Atom.mjs"},"./Hooks":{"types":"./dist/Hooks.d.mts","default":"./dist/Hooks.mjs"},"./Identity":{"types":"./dist/Identity.d.mts","default":"./dist/Identity.mjs"},"./OAuth":{"types":"./dist/OAuth.d.mts","default":"./dist/OAuth.mjs"},"./Operations":{"types":"./dist/Operations.d.mts","default":"./dist/Operations.mjs"},"./Rpc":{"types":"./dist/Rpc.d.mts","default":"./dist/Rpc.mjs"},"./Schema":{"types":"./dist/Schema.d.mts","default":"./dist/Schema.mjs"},"./Testing":{"types":"./dist/Testing.d.mts","default":"./dist/Testing.mjs"},"./WebCrypto":{"types":"./dist/WebCrypto.d.mts","default":"./dist/WebCrypto.mjs"},"./Sessions":{"types":"./dist/Sessions.d.mts","default":"./dist/Sessions.mjs"},"./SessionContract":{"types":"./dist/SessionContract.d.mts","default":"./dist/SessionContract.mjs"},"./Proofs":{"types":"./dist/Proofs.d.mts","default":"./dist/Proofs.mjs"},"./Password":{"types":"./dist/Password.d.mts","default":"./dist/Password.mjs"},"./Email":{"types":"./dist/Email.d.mts","default":"./dist/Email.mjs"},"./OpenIdClient":{"types":"./dist/OpenIdClient.d.mts","default":"./dist/OpenIdClient.mjs"},"./OpenIdClientConnected":{"types":"./dist/OpenIdClientConnected.d.mts","default":"./dist/OpenIdClientConnected.mjs"},"./Passkey":{"types":"./dist/Passkey.d.mts","default":"./dist/Passkey.mjs"},"./PasskeyPassword":{"types":"./dist/PasskeyPassword.d.mts","default":"./dist/PasskeyPassword.mjs"},"./PasskeySimpleWebAuthn":{"types":"./dist/PasskeySimpleWebAuthn.d.mts","default":"./dist/PasskeySimpleWebAuthn.mjs"},"./PasskeyBrowser":{"types":"./dist/PasskeyBrowser.d.mts","default":"./dist/PasskeyBrowser.mjs"},"./GitHub":{"types":"./dist/GitHub.d.mts","default":"./dist/GitHub.mjs"},"./AuthSession":{"types":"./dist/AuthSession.d.mts","default":"./dist/AuthSession.mjs"},"./Errors":{"types":"./dist/Errors.d.mts","default":"./dist/Errors.mjs"},"./Workflows":{"types":"./dist/Workflows.d.mts","default":"./dist/Workflows.mjs"},"./PasswordHasher":{"types":"./dist/PasswordHasher.d.mts","default":"./dist/PasswordHasher.mjs"},"./EmailOtp":{"types":"./dist/EmailOtp.d.mts","default":"./dist/EmailOtp.mjs"},"./AuthStore":{"types":"./dist/AuthStore.d.mts","default":"./dist/AuthStore.mjs"},"./PasswordAuth":{"types":"./dist/PasswordAuth.d.mts","default":"./dist/PasswordAuth.mjs"},"./Policy":{"types":"./dist/Policy.d.mts","default":"./dist/Policy.mjs"},"./EmailOtpSender":{"types":"./dist/EmailOtpSender.d.mts","default":"./dist/EmailOtpSender.mjs"},"./AuthTokenCodec":{"types":"./dist/AuthTokenCodec.d.mts","default":"./dist/AuthTokenCodec.mjs"},"./IdentityResolver":{"types":"./dist/IdentityResolver.d.mts","default":"./dist/IdentityResolver.mjs"},"./PasswordCredentialStore":{"types":"./dist/PasswordCredentialStore.d.mts","default":"./dist/PasswordCredentialStore.mjs"},"./PhoneOtp":{"types":"./dist/PhoneOtp.d.mts","default":"./dist/PhoneOtp.mjs"},"./Totp":{"types":"./dist/Totp.d.mts","default":"./dist/Totp.mjs"},"./PasskeyContract":{"types":"./dist/PasskeyContract.d.mts","default":"./dist/PasskeyContract.mjs"},"./TotpContract":{"types":"./dist/TotpContract.d.mts","default":"./dist/TotpContract.mjs"},"./AuthContract":{"types":"./dist/AuthContract.d.mts","default":"./dist/AuthContract.mjs"},"./Client":{"types":"./dist/Client.d.mts","default":"./dist/Client.mjs"}},"description":"Composable authentication, sessions, and identity workflows for Effect.","keywords":["authentication","effect","oauth","passkeys","sessions","typescript"],"homepage":"https://yielded.dev/auth/","bugs":{"url":"https://github.com/yielded-dev/auth/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/yielded-dev/auth.git","directory":"packages/effect-auth"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests","e2e":"bun test/e2e/harness.ts","example:totp":"bun test/fixtures/totp-sqlite-bun.ts"},"peerDependenciesMeta":{"@effect/sql-d1":{"optional":true},"@effect/sql-libsql":{"optional":true},"@effect/sql-mysql2":{"optional":true},"@effect/sql-pg":{"optional":true},"@effect/sql-pglite":{"optional":true},"@effect/sql-sqlite-bun":{"optional":true},"@effect/sql-sqlite-do":{"optional":true},"@effect/sql-sqlite-node":{"optional":true},"@effect/sql-sqlite-wasm":{"optional":true},"@simplewebauthn/browser":{"optional":true},"@simplewebauthn/server":{"optional":true},"drizzle-orm":{"optional":true},"effect-cf":{"optional":true},"openid-client":{"optional":true},"tldts":{"optional":true}}}
|
package/src/GitHub.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { OpenIdClientConfigurationError } from "./oauth/openid-client/models";
|
|
|
9
9
|
export {
|
|
10
10
|
gitHubOAuthAppConnectedProtocolLayer,
|
|
11
11
|
gitHubOAuthAppProtocolLayer,
|
|
12
|
+
gitHubOAuthAppProvider,
|
|
12
13
|
makeGitHubOAuthAppConnectedProtocol,
|
|
13
14
|
makeGitHubOAuthAppProtocol,
|
|
14
15
|
} from "./oauth/github/protocol";
|
|
@@ -6,6 +6,7 @@ import { OAuthConnectedProtocol } from "../OAuthConnectedProtocol";
|
|
|
6
6
|
import { OAuthProtocol } from "../OAuthProtocol";
|
|
7
7
|
import {
|
|
8
8
|
DefiniteTokenRejection,
|
|
9
|
+
tokenCompatibility,
|
|
9
10
|
type ConnectedCompatibility,
|
|
10
11
|
} from "../openid-client/compatibility";
|
|
11
12
|
import { makeConnectedProtocolWithCompatibility } from "../openid-client/connected/protocol";
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
OpenIdClientConfigurationError,
|
|
14
15
|
type OpenIdClientOAuthProvider,
|
|
15
16
|
} from "../openid-client/models";
|
|
16
|
-
import {
|
|
17
|
+
import { makeOpenIdClientOAuthProtocol } from "../openid-client/protocol";
|
|
17
18
|
import { ProviderRevocation } from "../openid-client/ProviderRevocation";
|
|
18
19
|
import { boundedFetch } from "../openid-client/transport";
|
|
19
20
|
import { OAuthUnavailable } from "../signInErrors";
|
|
@@ -265,6 +266,27 @@ const revocationLayer = (
|
|
|
265
266
|
);
|
|
266
267
|
};
|
|
267
268
|
|
|
269
|
+
/** A GitHub.com OAuth App generation for the same provider list as generic OIDC.
|
|
270
|
+
* Retains GitHub receipt/error rules and requests read:user, with no repository access.
|
|
271
|
+
* Construction performs no I/O; invalid configuration throws the typed configuration error. */
|
|
272
|
+
export const gitHubOAuthAppProvider = (
|
|
273
|
+
registration: GitHubOAuthAppGeneration,
|
|
274
|
+
): OpenIdClientOAuthProvider => {
|
|
275
|
+
let saved: GitHubOAuthAppGeneration;
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
saved = snapshotOAuthSync(generation, registration);
|
|
279
|
+
} catch {
|
|
280
|
+
throw invalid();
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
...provider(saved),
|
|
285
|
+
scopes: ["read:user"],
|
|
286
|
+
[tokenCompatibility]: compatibility,
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
|
|
268
290
|
export const makeGitHubOAuthAppProtocol = Effect.fn("makeGitHubOAuthAppProtocol")(function* (
|
|
269
291
|
options: GitHubOAuthAppProtocolOptions,
|
|
270
292
|
) {
|
|
@@ -273,13 +295,10 @@ export const makeGitHubOAuthAppProtocol = Effect.fn("makeGitHubOAuthAppProtocol"
|
|
|
273
295
|
if (saved.registrations.filter((item) => item.issuance === "active").length !== 1)
|
|
274
296
|
return yield* invalid();
|
|
275
297
|
|
|
276
|
-
return yield*
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
},
|
|
281
|
-
compatibility,
|
|
282
|
-
);
|
|
298
|
+
return yield* makeOpenIdClientOAuthProtocol({
|
|
299
|
+
...saved,
|
|
300
|
+
providers: saved.registrations.map(gitHubOAuthAppProvider),
|
|
301
|
+
});
|
|
283
302
|
});
|
|
284
303
|
|
|
285
304
|
export const makeGitHubOAuthAppConnectedProtocol = Effect.fn("makeGitHubOAuthAppConnectedProtocol")(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Predicate, Schema } from "effect";
|
|
2
|
+
|
|
1
3
|
import type {
|
|
2
4
|
OpenIdClientConnectedOAuthProvider,
|
|
3
5
|
OpenIdClientConnectedProtocolOptions,
|
|
@@ -19,6 +21,17 @@ export interface TokenCompatibility {
|
|
|
19
21
|
) => void;
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
/** First-party rules travel with the exact provider generation. The symbol stays
|
|
25
|
+
* private so generic provider options do not expose grant-bearing hooks. */
|
|
26
|
+
export const tokenCompatibility = Symbol("effect-auth/OpenIdClient/tokenCompatibility");
|
|
27
|
+
|
|
28
|
+
export const TokenCompatibility = Schema.declare<TokenCompatibility>(
|
|
29
|
+
(input): input is TokenCompatibility =>
|
|
30
|
+
Predicate.isObject(input) &&
|
|
31
|
+
"inspectReceipt" in input &&
|
|
32
|
+
Predicate.isFunction(input.inspectReceipt),
|
|
33
|
+
);
|
|
34
|
+
|
|
22
35
|
export class DefiniteTokenRejection extends Error {}
|
|
23
36
|
|
|
24
37
|
export interface ConnectedCompatibility extends TokenCompatibility {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
OAuthRedirectUri,
|
|
12
12
|
} from "../signInModels";
|
|
13
13
|
import { freezeOAuth } from "../signInSnapshot";
|
|
14
|
+
import { TokenCompatibility, tokenCompatibility } from "./compatibility";
|
|
14
15
|
import {
|
|
15
16
|
OpenIdClientConfigurationError,
|
|
16
17
|
type OpenIdClientAuthentication,
|
|
@@ -70,6 +71,7 @@ const optionsSchema = <R>() =>
|
|
|
70
71
|
Schema.Struct({
|
|
71
72
|
...common,
|
|
72
73
|
protocol: Schema.Literal("oauth"),
|
|
74
|
+
[tokenCompatibility]: Schema.optionalKey(TokenCompatibility),
|
|
73
75
|
authorizationEndpoint: boundedString(2048),
|
|
74
76
|
tokenEndpoint: boundedString(2048),
|
|
75
77
|
pkceS256: Schema.Literal(true),
|
|
@@ -3,6 +3,7 @@ import type { CustomFetch } from "openid-client";
|
|
|
3
3
|
|
|
4
4
|
import type { OAuthProtocolRejected } from "../signInErrors";
|
|
5
5
|
import type { OAuthProtocolConfiguration, OAuthVerifiedExternalIdentity } from "../signInModels";
|
|
6
|
+
import type { TokenCompatibility, tokenCompatibility } from "./compatibility";
|
|
6
7
|
|
|
7
8
|
export class OpenIdClientConfigurationError extends Schema.TaggedError<OpenIdClientConfigurationError>()(
|
|
8
9
|
"OpenIdClientConfigurationError",
|
|
@@ -55,6 +56,8 @@ export interface OpenIdClientOidcProvider extends ProviderGeneration {
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
export interface OpenIdClientOAuthProvider<R = never> extends ProviderGeneration {
|
|
59
|
+
/** @internal First-party provider behavior, retained by the configuration codec. */
|
|
60
|
+
readonly [tokenCompatibility]?: TokenCompatibility;
|
|
58
61
|
readonly protocol: "oauth";
|
|
59
62
|
readonly authorizationEndpoint: string;
|
|
60
63
|
readonly tokenEndpoint: string;
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
OAuthVerifiedExternalIdentity,
|
|
17
17
|
} from "../signInModels";
|
|
18
18
|
import { snapshotOAuth } from "../signInSnapshot";
|
|
19
|
-
import { DefiniteTokenRejection,
|
|
19
|
+
import { DefiniteTokenRejection, tokenCompatibility } from "./compatibility";
|
|
20
20
|
import {
|
|
21
21
|
clientAuthentication,
|
|
22
22
|
installConfigurations,
|
|
@@ -110,9 +110,9 @@ const privateConfiguration = <R>(
|
|
|
110
110
|
timeout: number,
|
|
111
111
|
fetch: client.CustomFetch,
|
|
112
112
|
signal: AbortSignal,
|
|
113
|
-
compatibility?: TokenCompatibility,
|
|
114
113
|
) => {
|
|
115
114
|
const provider = entry.provider;
|
|
115
|
+
const compatibility = provider.protocol === "oauth" ? provider[tokenCompatibility] : undefined;
|
|
116
116
|
|
|
117
117
|
const configuration = new client.Configuration(
|
|
118
118
|
entry.metadata,
|
|
@@ -158,10 +158,10 @@ const privateConfiguration = <R>(
|
|
|
158
158
|
return configuration;
|
|
159
159
|
};
|
|
160
160
|
|
|
161
|
-
export const
|
|
161
|
+
export const makeOpenIdClientOAuthProtocol = Effect.fn("makeOpenIdClientOAuthProtocol")(
|
|
162
|
+
// Capture one provider table; each generation retains its own receipt rules.
|
|
162
163
|
function* <R = never>(
|
|
163
164
|
options: OpenIdClientOAuthProtocolOptions<R>,
|
|
164
|
-
compatibility?: TokenCompatibility,
|
|
165
165
|
): Effect.fn.Return<
|
|
166
166
|
OAuthProtocol["Service"],
|
|
167
167
|
OpenIdClientConfigurationError | OAuthUnavailable,
|
|
@@ -192,13 +192,7 @@ export const makeOAuthProtocolWithCompatibility = Effect.fn("makeOpenIdClientOAu
|
|
|
192
192
|
|
|
193
193
|
const result = yield* Effect.tryPromise({
|
|
194
194
|
try: async (signal) => {
|
|
195
|
-
const configuration = privateConfiguration(
|
|
196
|
-
entry,
|
|
197
|
-
timeoutSeconds,
|
|
198
|
-
fetch,
|
|
199
|
-
signal,
|
|
200
|
-
compatibility,
|
|
201
|
-
);
|
|
195
|
+
const configuration = privateConfiguration(entry, timeoutSeconds, fetch, signal);
|
|
202
196
|
|
|
203
197
|
const state = client.randomState();
|
|
204
198
|
const verifier = client.randomPKCECodeVerifier();
|
|
@@ -281,13 +275,7 @@ export const makeOAuthProtocolWithCompatibility = Effect.fn("makeOpenIdClientOAu
|
|
|
281
275
|
|
|
282
276
|
const exchanged = yield* Effect.tryPromise({
|
|
283
277
|
try: async (signal) => {
|
|
284
|
-
const configuration = privateConfiguration(
|
|
285
|
-
entry,
|
|
286
|
-
timeoutSeconds,
|
|
287
|
-
fetch,
|
|
288
|
-
signal,
|
|
289
|
-
compatibility,
|
|
290
|
-
);
|
|
278
|
+
const configuration = privateConfiguration(entry, timeoutSeconds, fetch, signal);
|
|
291
279
|
|
|
292
280
|
const currentUrl = new URL(saved.redirectUri);
|
|
293
281
|
|
|
@@ -428,10 +416,6 @@ export const makeOAuthProtocolWithCompatibility = Effect.fn("makeOpenIdClientOAu
|
|
|
428
416
|
unavailableOnDefect,
|
|
429
417
|
);
|
|
430
418
|
|
|
431
|
-
export const makeOpenIdClientOAuthProtocol = <R = never>(
|
|
432
|
-
options: OpenIdClientOAuthProtocolOptions<R>,
|
|
433
|
-
) => makeOAuthProtocolWithCompatibility(options);
|
|
434
|
-
|
|
435
419
|
export const openIdClientOAuthProtocolLayer = <R = never>(
|
|
436
420
|
options: OpenIdClientOAuthProtocolOptions<R>,
|
|
437
421
|
) => Layer.effect(OAuthProtocol, makeOpenIdClientOAuthProtocol(options));
|