oidc-spa 7.1.10 → 7.2.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend.js +235 -352
- package/backend.js.map +1 -1
- package/core/AuthResponse.js +12 -49
- package/core/AuthResponse.js.map +1 -1
- package/core/Oidc.d.ts +1 -2
- package/core/Oidc.js.map +1 -1
- package/core/OidcInitializationError.d.ts +0 -13
- package/core/OidcInitializationError.js +8 -318
- package/core/OidcInitializationError.js.map +1 -1
- package/core/OidcMetadata.js +1 -1
- package/core/OidcMetadata.js.map +1 -1
- package/core/StateData.d.ts +5 -5
- package/core/StateData.js +25 -25
- package/core/StateData.js.map +1 -1
- package/core/configId.js +1 -1
- package/core/configId.js.map +1 -1
- package/core/createOidc.d.ts +8 -0
- package/core/createOidc.js +1030 -1292
- package/core/createOidc.js.map +1 -1
- package/core/diagnostic.d.ts +14 -0
- package/core/diagnostic.js +214 -0
- package/core/diagnostic.js.map +1 -0
- package/core/evtIsUserActive.js +26 -27
- package/core/evtIsUserActive.js.map +1 -1
- package/core/handleOidcCallback.js +99 -154
- package/core/handleOidcCallback.js.map +1 -1
- package/core/iframeMessageProtection.d.ts +1 -1
- package/core/iframeMessageProtection.js +40 -106
- package/core/iframeMessageProtection.js.map +1 -1
- package/core/index.d.ts +1 -1
- package/core/index.js +3 -3
- package/core/index.js.map +1 -1
- package/core/initialLocationHref.js +1 -1
- package/core/initialLocationHref.js.map +1 -1
- package/core/isNewBrowserSession.js +8 -8
- package/core/isNewBrowserSession.js.map +1 -1
- package/core/loginOrGoToAuthServer.d.ts +1 -1
- package/core/loginOrGoToAuthServer.js +188 -310
- package/core/loginOrGoToAuthServer.js.map +1 -1
- package/core/loginPropagationToOtherTabs.js +15 -16
- package/core/loginPropagationToOtherTabs.js.map +1 -1
- package/core/loginSilent.d.ts +2 -3
- package/core/loginSilent.js +118 -214
- package/core/loginSilent.js.map +1 -1
- package/core/logoutPropagationToOtherTabs.js +15 -16
- package/core/logoutPropagationToOtherTabs.js.map +1 -1
- package/core/oidcClientTsUserToTokens.d.ts +1 -1
- package/core/oidcClientTsUserToTokens.js +75 -72
- package/core/oidcClientTsUserToTokens.js.map +1 -1
- package/core/ongoingLoginOrRefreshProcesses.js +23 -89
- package/core/ongoingLoginOrRefreshProcesses.js.map +1 -1
- package/core/persistedAuthState.js +13 -13
- package/core/persistedAuthState.js.map +1 -1
- package/entrypoint.js +9 -9
- package/entrypoint.js.map +1 -1
- package/esm/core/AuthResponse.d.ts +5 -0
- package/{src/core/AuthResponse.ts → esm/core/AuthResponse.js} +3 -9
- package/esm/core/AuthResponse.js.map +1 -0
- package/esm/core/Oidc.d.ts +126 -0
- package/esm/core/Oidc.js +2 -0
- package/esm/core/Oidc.js.map +1 -0
- package/esm/core/OidcInitializationError.d.ts +7 -0
- package/esm/core/OidcInitializationError.js +17 -0
- package/esm/core/OidcInitializationError.js.map +1 -0
- package/{src/core/OidcMetadata.ts → esm/core/OidcMetadata.d.ts} +0 -5
- package/esm/core/OidcMetadata.js +3 -0
- package/esm/core/OidcMetadata.js.map +1 -0
- package/esm/core/StateData.d.ts +42 -0
- package/esm/core/StateData.js +55 -0
- package/esm/core/StateData.js.map +1 -0
- package/esm/core/configId.d.ts +4 -0
- package/esm/core/configId.js +4 -0
- package/esm/core/configId.js.map +1 -0
- package/esm/core/createOidc.d.ts +132 -0
- package/{src/core/createOidc.ts → esm/core/createOidc.js} +282 -826
- package/esm/core/createOidc.js.map +1 -0
- package/esm/core/diagnostic.d.ts +14 -0
- package/{src/core/OidcInitializationError.ts → esm/core/diagnostic.js} +40 -117
- package/esm/core/diagnostic.js.map +1 -0
- package/esm/core/evtIsUserActive.d.ts +5 -0
- package/{src/core/evtIsUserActive.ts → esm/core/evtIsUserActive.js} +14 -46
- package/esm/core/evtIsUserActive.js.map +1 -0
- package/esm/core/handleOidcCallback.d.ts +13 -0
- package/{src/core/handleOidcCallback.ts → esm/core/handleOidcCallback.js} +56 -131
- package/esm/core/handleOidcCallback.js.map +1 -0
- package/esm/core/iframeMessageProtection.d.ts +20 -0
- package/{src/core/iframeMessageProtection.ts → esm/core/iframeMessageProtection.js} +14 -49
- package/esm/core/iframeMessageProtection.js.map +1 -0
- package/{src/core/index.ts → esm/core/index.d.ts} +1 -1
- package/esm/core/index.js +4 -0
- package/esm/core/index.js.map +1 -0
- package/esm/core/initialLocationHref.d.ts +1 -0
- package/{src/core/initialLocationHref.ts → esm/core/initialLocationHref.js} +1 -1
- package/esm/core/initialLocationHref.js.map +1 -0
- package/esm/core/isNewBrowserSession.d.ts +9 -0
- package/{src/core/isNewBrowserSession.ts → esm/core/isNewBrowserSession.js} +3 -15
- package/esm/core/isNewBrowserSession.js.map +1 -0
- package/esm/core/loginOrGoToAuthServer.d.ts +40 -0
- package/{src/core/loginOrGoToAuthServer.ts → esm/core/loginOrGoToAuthServer.js} +60 -168
- package/esm/core/loginOrGoToAuthServer.js.map +1 -0
- package/esm/core/loginPropagationToOtherTabs.d.ts +8 -0
- package/{src/core/loginPropagationToOtherTabs.ts → esm/core/loginPropagationToOtherTabs.js} +7 -25
- package/esm/core/loginPropagationToOtherTabs.js.map +1 -0
- package/esm/core/loginSilent.d.ts +28 -0
- package/esm/core/loginSilent.js +125 -0
- package/esm/core/loginSilent.js.map +1 -0
- package/esm/core/logoutPropagationToOtherTabs.d.ts +10 -0
- package/{src/core/logoutPropagationToOtherTabs.ts → esm/core/logoutPropagationToOtherTabs.js} +8 -28
- package/esm/core/logoutPropagationToOtherTabs.js.map +1 -0
- package/esm/core/oidcClientTsUserToTokens.d.ts +11 -0
- package/esm/core/oidcClientTsUserToTokens.js +155 -0
- package/esm/core/oidcClientTsUserToTokens.js.map +1 -0
- package/esm/core/ongoingLoginOrRefreshProcesses.d.ts +6 -0
- package/{src/core/ongoingLoginOrRefreshProcesses.ts → esm/core/ongoingLoginOrRefreshProcesses.js} +6 -24
- package/esm/core/ongoingLoginOrRefreshProcesses.js.map +1 -0
- package/esm/core/persistedAuthState.d.ts +28 -0
- package/esm/core/persistedAuthState.js +64 -0
- package/esm/core/persistedAuthState.js.map +1 -0
- package/esm/entrypoint.d.ts +7 -0
- package/{src/entrypoint.ts → esm/entrypoint.js} +3 -26
- package/esm/entrypoint.js.map +1 -0
- package/esm/index.d.ts +1 -0
- package/esm/index.js +2 -0
- package/esm/index.js.map +1 -0
- package/esm/keycloak/index.d.ts +3 -0
- package/esm/keycloak/index.js +3 -0
- package/esm/keycloak/index.js.map +1 -0
- package/esm/keycloak/isKeycloak.d.ts +3 -0
- package/esm/keycloak/isKeycloak.js +17 -0
- package/esm/keycloak/isKeycloak.js.map +1 -0
- package/esm/keycloak/keycloak-js/Keycloak.d.ts +284 -0
- package/esm/keycloak/keycloak-js/Keycloak.js +774 -0
- package/esm/keycloak/keycloak-js/Keycloak.js.map +1 -0
- package/esm/keycloak/keycloak-js/index.d.ts +2 -0
- package/esm/keycloak/keycloak-js/index.js +2 -0
- package/esm/keycloak/keycloak-js/index.js.map +1 -0
- package/esm/keycloak/keycloak-js/types.d.ts +361 -0
- package/esm/keycloak/keycloak-js/types.js +2 -0
- package/esm/keycloak/keycloak-js/types.js.map +1 -0
- package/esm/keycloak/keycloakIssuerUriParsed.d.ts +9 -0
- package/esm/keycloak/keycloakIssuerUriParsed.js +16 -0
- package/esm/keycloak/keycloakIssuerUriParsed.js.map +1 -0
- package/esm/keycloak/keycloakUtils.d.ts +37 -0
- package/esm/keycloak/keycloakUtils.js +44 -0
- package/esm/keycloak/keycloakUtils.js.map +1 -0
- package/esm/keycloak-js.d.ts +1 -0
- package/esm/keycloak-js.js +2 -0
- package/esm/keycloak-js.js.map +1 -0
- package/esm/mock/index.js +2 -0
- package/esm/mock/index.js.map +1 -0
- package/esm/mock/oidc.d.ts +19 -0
- package/{src/mock/oidc.ts → esm/mock/oidc.js} +28 -88
- package/esm/mock/oidc.js.map +1 -0
- package/esm/mock/react.d.ts +58 -0
- package/esm/mock/react.js +7 -0
- package/esm/mock/react.js.map +1 -0
- package/esm/react/index.js +2 -0
- package/esm/react/index.js.map +1 -0
- package/esm/react/react.d.ts +102 -0
- package/esm/react/react.js +221 -0
- package/esm/react/react.js.map +1 -0
- package/esm/tools/Deferred.d.ts +14 -0
- package/esm/tools/Deferred.js +23 -0
- package/esm/tools/Deferred.js.map +1 -0
- package/esm/tools/EphemeralSessionStorage.d.ts +12 -0
- package/{src/tools/EphemeralSessionStorage.ts → esm/tools/EphemeralSessionStorage.js} +30 -112
- package/esm/tools/EphemeralSessionStorage.js.map +1 -0
- package/esm/tools/Evt.d.ts +11 -0
- package/{src/tools/Evt.ts → esm/tools/Evt.js} +7 -25
- package/esm/tools/Evt.js.map +1 -0
- package/esm/tools/StatefulEvt.d.ts +12 -0
- package/esm/tools/StatefulEvt.js +21 -0
- package/esm/tools/StatefulEvt.js.map +1 -0
- package/esm/tools/ValueOrAsyncGetter.js +2 -0
- package/esm/tools/ValueOrAsyncGetter.js.map +1 -0
- package/esm/tools/asymmetricEncryption.d.ts +18 -0
- package/esm/tools/asymmetricEncryption.js +85 -0
- package/esm/tools/asymmetricEncryption.js.map +1 -0
- package/esm/tools/base64.d.ts +2 -0
- package/{src/tools/base64.ts → esm/tools/base64.js} +3 -3
- package/esm/tools/base64.js.map +1 -0
- package/esm/tools/createObjectThatThrowsIfAccessed.d.ts +8 -0
- package/{src/tools/createObjectThatThrowsIfAccessed.ts → esm/tools/createObjectThatThrowsIfAccessed.js} +7 -18
- package/esm/tools/createObjectThatThrowsIfAccessed.js.map +1 -0
- package/esm/tools/decodeJwt.d.ts +25 -0
- package/esm/tools/decodeJwt.js +60 -0
- package/esm/tools/decodeJwt.js.map +1 -0
- package/esm/tools/generateUrlSafeRandom.d.ts +3 -0
- package/{src/tools/generateUrlSafeRandom.ts → esm/tools/generateUrlSafeRandom.js} +5 -8
- package/esm/tools/generateUrlSafeRandom.js.map +1 -0
- package/esm/tools/getDownlinkAndRtt.d.ts +4 -0
- package/{src/tools/getDownlinkAndRtt.ts → esm/tools/getDownlinkAndRtt.js} +6 -10
- package/esm/tools/getDownlinkAndRtt.js.map +1 -0
- package/esm/tools/getIsOnline.d.ts +7 -0
- package/{src/tools/getIsOnline.ts → esm/tools/getIsOnline.js} +3 -9
- package/esm/tools/getIsOnline.js.map +1 -0
- package/esm/tools/getIsValidRemoteJson.d.ts +1 -0
- package/esm/tools/getIsValidRemoteJson.js +15 -0
- package/esm/tools/getIsValidRemoteJson.js.map +1 -0
- package/esm/tools/getPrUserInteraction.d.ts +4 -0
- package/{src/tools/getPrUserInteraction.ts → esm/tools/getPrUserInteraction.js} +2 -6
- package/esm/tools/getPrUserInteraction.js.map +1 -0
- package/esm/tools/getUserEnvironmentInfo.d.ts +1 -0
- package/esm/tools/getUserEnvironmentInfo.js +50 -0
- package/esm/tools/getUserEnvironmentInfo.js.map +1 -0
- package/esm/tools/haveSharedParentDomain.d.ts +4 -0
- package/{src/tools/haveSharedParentDomain.ts → esm/tools/haveSharedParentDomain.js} +3 -5
- package/esm/tools/haveSharedParentDomain.js.map +1 -0
- package/esm/tools/isDev.d.ts +1 -0
- package/{src/tools/isDev.ts → esm/tools/isDev.js} +5 -12
- package/esm/tools/isDev.js.map +1 -0
- package/esm/tools/parseKeycloakIssuerUri.d.ts +30 -0
- package/esm/tools/parseKeycloakIssuerUri.js +33 -0
- package/esm/tools/parseKeycloakIssuerUri.js.map +1 -0
- package/esm/tools/readExpirationTimeInJwt.d.ts +1 -0
- package/{src/tools/readExpirationTimeInJwt.ts → esm/tools/readExpirationTimeInJwt.js} +6 -7
- package/esm/tools/readExpirationTimeInJwt.js.map +1 -0
- package/esm/tools/startCountdown.d.ts +11 -0
- package/{src/tools/startCountdown.ts → esm/tools/startCountdown.js} +6 -17
- package/esm/tools/startCountdown.js.map +1 -0
- package/esm/tools/subscribeToUserInteraction.d.ts +6 -0
- package/{src/tools/subscribeToUserInteraction.ts → esm/tools/subscribeToUserInteraction.js} +4 -13
- package/esm/tools/subscribeToUserInteraction.js.map +1 -0
- package/esm/tools/toFullyQualifiedUrl.d.ts +10 -0
- package/{src/tools/toFullyQualifiedUrl.ts → esm/tools/toFullyQualifiedUrl.js} +7 -25
- package/esm/tools/toFullyQualifiedUrl.js.map +1 -0
- package/esm/tools/toHumanReadableDuration.d.ts +1 -0
- package/{src/tools/toHumanReadableDuration.ts → esm/tools/toHumanReadableDuration.js} +8 -5
- package/esm/tools/toHumanReadableDuration.js.map +1 -0
- package/esm/tools/urlSearchParams.d.ts +19 -0
- package/{src/tools/urlSearchParams.ts → esm/tools/urlSearchParams.js} +24 -70
- package/esm/tools/urlSearchParams.js.map +1 -0
- package/esm/tools/workerTimers.d.ts +5 -0
- package/{src/tools/workerTimers.ts → esm/tools/workerTimers.js} +7 -27
- package/esm/tools/workerTimers.js.map +1 -0
- package/esm/vendor/frontend/oidc-client-ts.d.ts +1 -0
- package/esm/vendor/frontend/oidc-client-ts.js +3636 -0
- package/{src/vendor/frontend/tsafe.ts → esm/vendor/frontend/tsafe.d.ts} +1 -0
- package/esm/vendor/frontend/tsafe.js +1 -0
- package/esm/vendor/frontend/worker-timers.js +1 -0
- package/index.d.ts +1 -1
- package/index.js +1 -2
- package/index.js.map +1 -1
- package/keycloak/index.d.ts +3 -0
- package/keycloak/index.js +8 -0
- package/keycloak/index.js.map +1 -0
- package/keycloak/isKeycloak.d.ts +3 -0
- package/keycloak/isKeycloak.js +20 -0
- package/keycloak/isKeycloak.js.map +1 -0
- package/keycloak/keycloak-js/Keycloak.d.ts +284 -0
- package/keycloak/keycloak-js/Keycloak.js +778 -0
- package/keycloak/keycloak-js/Keycloak.js.map +1 -0
- package/keycloak/keycloak-js/index.d.ts +2 -0
- package/keycloak/keycloak-js/index.js +6 -0
- package/keycloak/keycloak-js/index.js.map +1 -0
- package/keycloak/keycloak-js/types.d.ts +361 -0
- package/keycloak/keycloak-js/types.js +3 -0
- package/keycloak/keycloak-js/types.js.map +1 -0
- package/keycloak/keycloakIssuerUriParsed.d.ts +9 -0
- package/keycloak/keycloakIssuerUriParsed.js +19 -0
- package/keycloak/keycloakIssuerUriParsed.js.map +1 -0
- package/keycloak/keycloakUtils.d.ts +37 -0
- package/keycloak/keycloakUtils.js +47 -0
- package/keycloak/keycloakUtils.js.map +1 -0
- package/keycloak-js.d.ts +1 -0
- package/keycloak-js.js +18 -0
- package/keycloak-js.js.map +1 -0
- package/mock/index.js.map +1 -1
- package/mock/oidc.js +147 -194
- package/mock/oidc.js.map +1 -1
- package/mock/react.js +2 -2
- package/mock/react.js.map +1 -1
- package/package.json +74 -299
- package/react/index.js.map +1 -1
- package/react/react.js +133 -244
- package/react/react.js.map +1 -1
- package/tools/Deferred.js +13 -35
- package/tools/Deferred.js.map +1 -1
- package/tools/EphemeralSessionStorage.js +46 -48
- package/tools/EphemeralSessionStorage.js.map +1 -1
- package/tools/Evt.js +14 -14
- package/tools/Evt.js.map +1 -1
- package/tools/StatefulEvt.js +5 -5
- package/tools/StatefulEvt.js.map +1 -1
- package/tools/ValueOrAsyncGetter.js.map +1 -1
- package/tools/asymmetricEncryption.js +81 -172
- package/tools/asymmetricEncryption.js.map +1 -1
- package/tools/base64.js +2 -2
- package/tools/base64.js.map +1 -1
- package/tools/createObjectThatThrowsIfAccessed.js +13 -61
- package/tools/createObjectThatThrowsIfAccessed.js.map +1 -1
- package/tools/decodeJwt.d.ts +25 -2
- package/tools/decodeJwt.js +61 -3
- package/tools/decodeJwt.js.map +1 -1
- package/tools/generateUrlSafeRandom.js +5 -30
- package/tools/generateUrlSafeRandom.js.map +1 -1
- package/tools/getDownlinkAndRtt.js +8 -30
- package/tools/getDownlinkAndRtt.js.map +1 -1
- package/tools/getIsOnline.js +3 -3
- package/tools/getIsOnline.js.map +1 -1
- package/tools/getIsValidRemoteJson.js +12 -59
- package/tools/getIsValidRemoteJson.js.map +1 -1
- package/tools/getPrUserInteraction.js +4 -4
- package/tools/getPrUserInteraction.js.map +1 -1
- package/tools/getUserEnvironmentInfo.js +17 -12
- package/tools/getUserEnvironmentInfo.js.map +1 -1
- package/tools/haveSharedParentDomain.js +5 -5
- package/tools/haveSharedParentDomain.js.map +1 -1
- package/tools/isDev.js +2 -2
- package/tools/isDev.js.map +1 -1
- package/tools/parseKeycloakIssuerUri.d.ts +2 -0
- package/tools/parseKeycloakIssuerUri.js +11 -42
- package/tools/parseKeycloakIssuerUri.js.map +1 -1
- package/tools/readExpirationTimeInJwt.js +4 -4
- package/tools/readExpirationTimeInJwt.js.map +1 -1
- package/tools/startCountdown.js +17 -65
- package/tools/startCountdown.js.map +1 -1
- package/tools/subscribeToUserInteraction.js +17 -66
- package/tools/subscribeToUserInteraction.js.map +1 -1
- package/tools/toFullyQualifiedUrl.js +7 -7
- package/tools/toFullyQualifiedUrl.js.map +1 -1
- package/tools/toHumanReadableDuration.js +13 -13
- package/tools/toHumanReadableDuration.js.map +1 -1
- package/tools/urlSearchParams.js +28 -50
- package/tools/urlSearchParams.js.map +1 -1
- package/tools/workerTimers.js +10 -10
- package/tools/workerTimers.js.map +1 -1
- package/vendor/frontend/oidc-client-ts.d.ts +1 -0
- package/vendor/frontend/oidc-client-ts.js +3686 -0
- package/vendor/frontend/tsafe.d.ts +1 -0
- package/vendor/frontend/tsafe.js +1 -1
- package/LICENSE +0 -21
- package/README.md +0 -185
- package/core/trustedFetch.d.ts +0 -2
- package/core/trustedFetch.js +0 -12
- package/core/trustedFetch.js.map +0 -1
- package/src/backend.ts +0 -391
- package/src/core/Oidc.ts +0 -141
- package/src/core/StateData.ts +0 -118
- package/src/core/configId.ts +0 -3
- package/src/core/loginSilent.ts +0 -206
- package/src/core/oidcClientTsUserToTokens.ts +0 -229
- package/src/core/persistedAuthState.ts +0 -122
- package/src/core/trustedFetch.ts +0 -9
- package/src/index.ts +0 -7
- package/src/mock/react.tsx +0 -11
- package/src/react/react.tsx +0 -460
- package/src/tools/Deferred.ts +0 -39
- package/src/tools/StatefulEvt.ts +0 -38
- package/src/tools/asymmetricEncryption.ts +0 -184
- package/src/tools/decodeJwt.ts +0 -2
- package/src/tools/getIsValidRemoteJson.ts +0 -18
- package/src/tools/getUserEnvironmentInfo.ts +0 -42
- package/src/tools/parseKeycloakIssuerUri.ts +0 -68
- package/src/vendor/backend/evt.ts +0 -2
- package/src/vendor/backend/jsonwebtoken.ts +0 -1
- package/src/vendor/backend/node-fetch.ts +0 -2
- package/src/vendor/backend/node-jose.ts +0 -1
- package/src/vendor/backend/tsafe.ts +0 -5
- package/src/vendor/backend/zod.ts +0 -1
- package/src/vendor/frontend/oidc-client-ts-and-jwt-decode.ts +0 -4
- package/vendor/frontend/oidc-client-ts-and-jwt-decode.d.ts +0 -3
- package/vendor/frontend/oidc-client-ts-and-jwt-decode.js +0 -3
- /package/{src/mock/index.ts → esm/mock/index.d.ts} +0 -0
- /package/{src/react/index.ts → esm/react/index.d.ts} +0 -0
- /package/{src/tools/ValueOrAsyncGetter.ts → esm/tools/ValueOrAsyncGetter.d.ts} +0 -0
- /package/{src/vendor/frontend/worker-timers.ts → esm/vendor/frontend/worker-timers.d.ts} +0 -0
package/vendor/frontend/tsafe.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(()=>{"use strict";var e={720:function(e,r,t){var n,o=this&&this.__extends||(n=function(e,r){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,r){e.__proto__=r}||function(e,r){for(var t in r)Object.prototype.hasOwnProperty.call(r,t)&&(e[t]=r[t])},n(e,r)},function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function t(){this.constructor=e}n(e,r),e.prototype=null===r?Object.create(r):(t.prototype=r.prototype,new t)}),i=this&&this.__read||function(e,r){var t="function"==typeof Symbol&&e[Symbol.iterator];if(!t)return e;var n,o,i=t.call(e),
|
|
1
|
+
(()=>{"use strict";var e={720:function(e,r,t){var n,o=this&&this.__extends||(n=function(e,r){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,r){e.__proto__=r}||function(e,r){for(var t in r)Object.prototype.hasOwnProperty.call(r,t)&&(e[t]=r[t])},n(e,r)},function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function t(){this.constructor=e}n(e,r),e.prototype=null===r?Object.create(r):(t.prototype=r.prototype,new t)}),i=this&&this.__read||function(e,r){var t="function"==typeof Symbol&&e[Symbol.iterator];if(!t)return e;var n,o,i=t.call(e),u=[];try{for(;(void 0===r||r-- >0)&&!(n=i.next()).done;)u.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(t=i.return)&&t.call(i)}finally{if(o)throw o.error}}return u};Object.defineProperty(r,"__esModule",{value:!0}),r.AssertionError=void 0,r.assert=function(e,r){if(0===arguments.length&&(e=!0),void 0===c){if(!e)throw new a("function"==typeof r?r():r)}else c=void 0},r.is=function(e){var r={};if(void 0!==c)throw c=void 0,new Error(f);return c=r,Promise.resolve().then((function(){if(c===r)throw new Error(f)})),null};var u=t(522),a=function(e){function r(r){var t=this.constructor,n=e.call(this,"Wrong assertion encountered"+(r?': "'.concat(r,'"'):""))||this;if(n.originalMessage=r,Object.setPrototypeOf(n,t.prototype),!n.stack)return n;try{(0,u.overwriteReadonlyProp)(n,"stack",n.stack.split("\n").filter((function(){for(var e=[],r=0;r<arguments.length;r++)e[r]=arguments[r];var t=i(e,2)[1];return 1!==t&&2!==t})).join("\n"))}catch(e){}return n}return o(r,e),r}(Error);r.AssertionError=a;var c=void 0,f="Wrong usage of the `is` function refer to https://docs.tsafe.dev/is"},135:(e,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.id=void 0,r.id=function(e){return e}},952:function(e,r){var t=this&&this.__values||function(e){var r="function"==typeof Symbol&&Symbol.iterator,t=r&&e[r],n=0;if(t)return t.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(r?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(r,"__esModule",{value:!0}),r.isAmong=function(e,r){var n,o;try{for(var i=t(e),u=i.next();!u.done;u=i.next())if(u.value===r)return!0}catch(e){n={error:e}}finally{try{u&&!u.done&&(o=i.return)&&o.call(i)}finally{if(n)throw n.error}}return!1}},522:function(e,r){var t=this&&this.__assign||function(){return t=Object.assign||function(e){for(var r,t=1,n=arguments.length;t<n;t++)for(var o in r=arguments[t])Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o]);return e},t.apply(this,arguments)};Object.defineProperty(r,"__esModule",{value:!0}),r.overwriteReadonlyProp=void 0,r.overwriteReadonlyProp=function(e,r,n){try{e[r]=n}catch(e){}if(e[r]===n)return n;var o=void 0,i=Object.getOwnPropertyDescriptor(e,r)||{enumerable:!0,configurable:!0};if(i.get)throw new Error("Probably a wrong ides to overwrite ".concat(String(r)," getter"));try{Object.defineProperty(e,r,t(t({},i),{value:n}))}catch(e){o=e}if(e[r]!==n)throw o||new Error("Can't assign");return n}},505:(e,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.noUndefined=function(e){var r={};for(var t in e)void 0!==e[t]&&(r[t]=e[t]);return r}},497:(e,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.typeGuard=function(e,r){return r}}},r={};function t(n){var o=r[n];if(void 0!==o)return o.exports;var i=r[n]={exports:{}};return e[n].call(i.exports,i,i.exports,t),i.exports}var n={};(()=>{var e=n;Object.defineProperty(e,"__esModule",{value:!0}),e.isAmong=e.noUndefined=e.overwriteReadonlyProp=e.typeGuard=e.is=e.assert=e.id=void 0;var r=t(135);Object.defineProperty(e,"id",{enumerable:!0,get:function(){return r.id}});var o=t(720);Object.defineProperty(e,"assert",{enumerable:!0,get:function(){return o.assert}}),Object.defineProperty(e,"is",{enumerable:!0,get:function(){return o.is}});var i=t(497);Object.defineProperty(e,"typeGuard",{enumerable:!0,get:function(){return i.typeGuard}});var u=t(522);Object.defineProperty(e,"overwriteReadonlyProp",{enumerable:!0,get:function(){return u.overwriteReadonlyProp}});var a=t(505);Object.defineProperty(e,"noUndefined",{enumerable:!0,get:function(){return a.noUndefined}});var c=t(952);Object.defineProperty(e,"isAmong",{enumerable:!0,get:function(){return c.isAmong}})})(),module.exports=n})();
|
|
2
2
|
exports.__oidcSpaBundle = true;
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2020 GitHub user u/garronej
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
|
-
<p align="center">
|
|
4
|
-
<br>
|
|
5
|
-
<a href="https://github.com/keycloakify/oidc-spa/actions">
|
|
6
|
-
<img src="https://github.com/keycloakify/oidc-spa/actions/workflows/ci.yaml/badge.svg?branch=main">
|
|
7
|
-
</a>
|
|
8
|
-
<a href="https://www.npmjs.com/package/oidc-spa">
|
|
9
|
-
<img src="https://img.shields.io/npm/dw/oidc-spa">
|
|
10
|
-
</a>
|
|
11
|
-
<a href="https://github.com/garronej/oidc-spa/blob/main/LICENSE">
|
|
12
|
-
<img src="https://img.shields.io/npm/l/oidc-spa">
|
|
13
|
-
</a>
|
|
14
|
-
</p>
|
|
15
|
-
<p align="center">
|
|
16
|
-
We're here to help!<br/>
|
|
17
|
-
<a href="https://discord.gg/mJdYJSdcm4">
|
|
18
|
-
<img src="https://dcbadge.limes.pink/api/server/kYFZG7fQmn"/>
|
|
19
|
-
</a>
|
|
20
|
-
</p>
|
|
21
|
-
<p align="center">
|
|
22
|
-
<a href="https://www.oidc-spa.dev">Home</a>
|
|
23
|
-
-
|
|
24
|
-
<a href="https://docs.oidc-spa.dev">Documentation</a>
|
|
25
|
-
</p>
|
|
26
|
-
|
|
27
|
-
> 🗣️ oidc-spa will be introduced at [KeyConf 2025](https://keyconf.dev/) on the 28 of August.
|
|
28
|
-
|
|
29
|
-
A full-featured OpenID Connect / OAuth2 client for single-page applications (SPAs).
|
|
30
|
-
|
|
31
|
-
With `oidc-spa`, you can seamlessly integrate authentication providers like [Keycloak](https://www.keycloak.org/), [Auth0](https://auth0.com/), or [Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id) into your application, purely on the client side,
|
|
32
|
-
[without involving your backend in the token exchange](https://docs.oidc-spa.dev/resources/why-no-client-secret).
|
|
33
|
-
|
|
34
|
-
In **simple terms**, `oidc-spa` is a library that makes it easy to **add authentication** to your Vite or Create-React-App project.
|
|
35
|
-
There are many authentication and user management platforms out there: Okta, Auth0, Entra ID...
|
|
36
|
-
There are also plenty of self-hosted options like Keycloak, Ory Hydra, and Dex.
|
|
37
|
-
What all of these have in common is that they implement the OpenID Connect/OAuth2 standard.
|
|
38
|
-
|
|
39
|
-
This library provides a **unified way** to connect with these different providers instead of having to use
|
|
40
|
-
their specific SDKs.
|
|
41
|
-
|
|
42
|
-
`oidc-spa` implement the [**Authorization Code Flow with PKCE**](https://docs.oidc-spa.dev/resources/why-no-client-secret), this means that **you do not need a backend and a database** to handle the authentication process.
|
|
43
|
-
The authentication process is handled entirely in the browser. And no need for `/login` or `/logout` routes.
|
|
44
|
-
|
|
45
|
-
## Why `oidc-spa`?
|
|
46
|
-
|
|
47
|
-
Most OIDC providers push their own client libraries:
|
|
48
|
-
|
|
49
|
-
- **Auth0** → `auth0-spa-js`
|
|
50
|
-
- **Microsoft Entra ID** → `MSAL.js`
|
|
51
|
-
- **Keycloak** → `keycloak-js` (no longer actively promoted, planned for deprecation)
|
|
52
|
-
- **... and so on.**
|
|
53
|
-
|
|
54
|
-
These libraries are **tied to a specific provider**. But what if you need to:
|
|
55
|
-
|
|
56
|
-
✅ Switch OIDC providers without modifying your authentication logic?
|
|
57
|
-
✅ Build a self-hostable solution that works with any provider (e.g., you're developing a dashboard app that you sell to enterprises and need to integrate with their existing IAM system)?
|
|
58
|
-
✅ Stop re-learning authentication implementation every time you change providers?
|
|
59
|
-
|
|
60
|
-
And besides, not all SDKs are equal in terms of setup simplicity, performance, and API quality.
|
|
61
|
-
|
|
62
|
-
We wanted a **universal solution**, one that is as good or better than all existing SDKs in every aspect.
|
|
63
|
-
|
|
64
|
-
## Features
|
|
65
|
-
|
|
66
|
-
- 🎓 **No OIDC/OAuth2 expertise required**: Easy to setup and use. We're here to help [on Discord](https://discord.gg/mJdYJSdcm4)!
|
|
67
|
-
- 🛠️ **Simple setup**: No need to define `/login` or `/logout` routes, token refreshing is automatic, it just works.
|
|
68
|
-
- ✨ **React integration**: Expose a framework agnostic API but also a React adapter `oidc-spa/react`.
|
|
69
|
-
- 🔥 **No limitation**- For example, everything you could do with `keycloak-js`, you can do with `oidc-spa`.
|
|
70
|
-
- 💬 **Detailed debug messages**: If your OIDC server is not properly configured, it tells you precisely what’s wrong and what you need to do to fix it.
|
|
71
|
-
- 🕣 **Auto logout with countdown**: "You will be logged out in 10... 9... 8...", users see exactly when their session expires.
|
|
72
|
-
- 🚪 **Logout propagation**: Logging out in one tab logs out all others.
|
|
73
|
-
- 📖 **Comprehensive documentation**: Guides and examples for common scenarios.
|
|
74
|
-
- ✅ **Type safety**: Strong TypeScript support with optional [Zod](https://zod.dev/) integration validating the expected shape of the ID token.
|
|
75
|
-
- 🔒 **Security-first**: Uses [**Authorization Code Flow + PKCE**](https://docs.oidc-spa.dev/resources/why-no-client-secret#id-2.-authorization-code-flow--pkce-used-by-oidc-spa), No token persistence in `localStorage` or `sessionStorage`.
|
|
76
|
-
- 🖥️ **Optional backend utilities**: Provides tools for token validation in JavaScript backends (Node.js, Deno, Web Workers).
|
|
77
|
-
- 🍪 **No third-party cookie issues**: Third-party cookies blocked? No problem, `oidc-spa` works around it automatically with no special measures needed on your side.
|
|
78
|
-
- 🔗 **Multi-instance support**: Run multiple `oidc-spa` instances in the same app without conflict.
|
|
79
|
-
|
|
80
|
-
## Comparison with Existing Libraries
|
|
81
|
-
|
|
82
|
-
### [oidc-client-ts](https://github.com/authts/oidc-client-ts)
|
|
83
|
-
|
|
84
|
-
While `oidc-client-ts` is a comprehensive toolkit designed for various applications, `oidc-spa` is specifically built for SPAs with an easy-to-set-up API.
|
|
85
|
-
But **ease of use** isn't the only difference, `oidc-spa` also provides **out-of-the-box** solutions for features that `oidc-client-ts` leaves up to you to implement, such as:
|
|
86
|
-
|
|
87
|
-
- **Login/logout propagation** across tabs
|
|
88
|
-
- **Graceful fallback when third-party cookies are blocked**
|
|
89
|
-
- **Seamless browser back/forward cache (bfcache) management**
|
|
90
|
-
- **Auto logout countdown** so users can be automatically logged out after a set period of inactivity.
|
|
91
|
-
- **Ensuring you never get an expired access token error**, even after the computer wakes up from sleep.
|
|
92
|
-
- **Gracefully handles scenarios where the provider does not issue a refresh token or lacks a logout endpoint** (e.g., Google OAuth)
|
|
93
|
-
|
|
94
|
-
### [react-oidc-context](https://github.com/authts/react-oidc-context)
|
|
95
|
-
|
|
96
|
-
`react-oidc-context` is a React wrapper around `oidc-client-ts`.
|
|
97
|
-
`oidc-spa` also feature a carefully crafted React API that comes with [working examples that you can test locally](https://docs.oidc-spa.dev/example-setups/example-setups).
|
|
98
|
-
|
|
99
|
-
### [keycloak-js](https://www.npmjs.com/package/keycloak-js)
|
|
100
|
-
|
|
101
|
-
The official OIDC Client for Keycloak. It only works with Keycloak and [will eventually be deprecated](https://www.keycloak.org/2023/03/adapter-deprecation-update).
|
|
102
|
-
Beyond that, achieving the same seamless user experience as `oidc-spa` with `keycloak-js` requires writing a lot of custom code, code that really **shouldn’t** be handled at the application level.
|
|
103
|
-
|
|
104
|
-
### [NextAuth.js](https://next-auth.js.org/)
|
|
105
|
-
|
|
106
|
-
Since oidc-spa is built for true SPAs, Next.js applications should use NextAuth.js instead.
|
|
107
|
-
|
|
108
|
-
> _NOTE: We might create in the future a `oidc-mpa` library for Multi Page Applications that would aim at supporting Next.js projects._
|
|
109
|
-
|
|
110
|
-
## 🚀 Quick start
|
|
111
|
-
|
|
112
|
-
Head over to [the documentation website](https://docs.oidc-spa.dev) 📘!
|
|
113
|
-
|
|
114
|
-
## Sponsors
|
|
115
|
-
|
|
116
|
-
Project backers, we trust and recommend their services.
|
|
117
|
-
|
|
118
|
-
<br/>
|
|
119
|
-
|
|
120
|
-
<div align="center">
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
</div>
|
|
125
|
-
|
|
126
|
-
<div align="center">
|
|
127
|
-
|
|
128
|
-

|
|
129
|
-
|
|
130
|
-
</div>
|
|
131
|
-
|
|
132
|
-
<br/>
|
|
133
|
-
|
|
134
|
-
<p align="center">
|
|
135
|
-
<i><a href="https://phasetwo.io/?utm_source=keycloakify"><strong>Keycloak as a Service</strong></a> - Keycloak community contributors of popular <a href="https://github.com/p2-inc#our-extensions-?utm_source=keycloakify">extensions</a> providing free and dedicated <a href="https://phasetwo.io/hosting/?utm_source=keycloakify">Keycloak hosting</a> and enterprise <a href="https://phasetwo.io/support/?utm_source=keycloakify">Keycloak support</a> to businesses of all sizes.</i>
|
|
136
|
-
</p>
|
|
137
|
-
|
|
138
|
-
<br/>
|
|
139
|
-
<br/>
|
|
140
|
-
<br/>
|
|
141
|
-
|
|
142
|
-
<div align="center">
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
</div>
|
|
147
|
-
|
|
148
|
-
<div align="center">
|
|
149
|
-
|
|
150
|
-

|
|
151
|
-
|
|
152
|
-
</div>
|
|
153
|
-
|
|
154
|
-
<br/>
|
|
155
|
-
|
|
156
|
-
<p align="center">
|
|
157
|
-
<a href="https://www.zone2.tech/services/keycloak-consulting">
|
|
158
|
-
<i><strong>Keycloak Consulting Services</strong> - Your partner in Keycloak deployment, configuration, and extension development for optimized identity management solutions.</i>
|
|
159
|
-
</a>
|
|
160
|
-
</p>
|
|
161
|
-
|
|
162
|
-
## We built it because we needed it.
|
|
163
|
-
|
|
164
|
-
This library isn't a theoretical exercise or a tool for hobby projects.
|
|
165
|
-
We developed it to solve real-world problems we faced ourselves.
|
|
166
|
-
Today, it powers authentication for [Onyxia](https://onyxia.sh),
|
|
167
|
-
a data science platform deployed across multiple large organizations.
|
|
168
|
-
|
|
169
|
-
### Onyxia
|
|
170
|
-
|
|
171
|
-
- [Source code](https://github.com/InseeFrLab/onyxia)
|
|
172
|
-
- [Public instance](https://datalab.sspcloud.fr)
|
|
173
|
-
|
|
174
|
-
<a href="https://youtu.be/FvpNfVrxBFM">
|
|
175
|
-
<img width="1712" alt="image" src="https://user-images.githubusercontent.com/6702424/231314534-2eeb1ab5-5460-4caa-b78d-55afd400c9fc.png">
|
|
176
|
-
</a>
|
|
177
|
-
|
|
178
|
-
### The French Interministerial Base of Free Software
|
|
179
|
-
|
|
180
|
-
- [Source code](https://github.com/codegouvfr/sill-web/)
|
|
181
|
-
- [Deployment of the website](https://sill-preprod.lab.sspcloud.fr/)
|
|
182
|
-
|
|
183
|
-
<a href="https://youtu.be/AT3CvmY_Y7M?si=Edkf0vRNjosGLA3R">
|
|
184
|
-
<img width="1712" alt="image" src="https://github.com/garronej/i18nifty/assets/6702424/aa06cc30-b2bd-4c8b-b435-2f875f53175b">
|
|
185
|
-
</a>
|
package/core/trustedFetch.d.ts
DELETED
package/core/trustedFetch.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.trustedFetch = void 0;
|
|
4
|
-
exports.captureFetch = captureFetch;
|
|
5
|
-
var globalContext = {
|
|
6
|
-
trustedFetch: window.fetch
|
|
7
|
-
};
|
|
8
|
-
exports.trustedFetch = globalContext.trustedFetch;
|
|
9
|
-
function captureFetch() {
|
|
10
|
-
/** noop */
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=trustedFetch.js.map
|
package/core/trustedFetch.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"trustedFetch.js","sourceRoot":"","sources":["../src/core/trustedFetch.ts"],"names":[],"mappings":";;;AAMA,oCAEC;AARD,IAAM,aAAa,GAAG;IAClB,YAAY,EAAE,MAAM,CAAC,KAAK;CAC7B,CAAC;AAEa,QAAA,YAAY,GAAK,aAAa,cAAC;AAE9C,SAAgB,YAAY;IACxB,WAAW;AACf,CAAC"}
|
package/src/backend.ts
DELETED
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
import { fetch } from "./vendor/backend/node-fetch";
|
|
2
|
-
import { assert, isAmong, id, type Equals, is, exclude } from "./vendor/backend/tsafe";
|
|
3
|
-
import { JWK } from "./vendor/backend/node-jose";
|
|
4
|
-
import * as jwt from "./vendor/backend/jsonwebtoken";
|
|
5
|
-
import { z } from "./vendor/backend/zod";
|
|
6
|
-
import { Evt } from "./vendor/backend/evt";
|
|
7
|
-
import { throttleTime } from "./vendor/backend/evt";
|
|
8
|
-
|
|
9
|
-
export type ParamsOfCreateOidcBackend<DecodedAccessToken extends Record<string, unknown>> = {
|
|
10
|
-
issuerUri: string;
|
|
11
|
-
decodedAccessTokenSchema?: { parse: (data: unknown) => DecodedAccessToken };
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export type OidcBackend<DecodedAccessToken extends Record<string, unknown>> = {
|
|
15
|
-
verifyAndDecodeAccessToken(params: {
|
|
16
|
-
accessToken: string;
|
|
17
|
-
}): ResultOfAccessTokenVerify<DecodedAccessToken>;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type ResultOfAccessTokenVerify<DecodedAccessToken> =
|
|
21
|
-
| ResultOfAccessTokenVerify.Valid<DecodedAccessToken>
|
|
22
|
-
| ResultOfAccessTokenVerify.Invalid;
|
|
23
|
-
|
|
24
|
-
export namespace ResultOfAccessTokenVerify {
|
|
25
|
-
export type Valid<DecodedAccessToken> = {
|
|
26
|
-
isValid: true;
|
|
27
|
-
decodedAccessToken: DecodedAccessToken;
|
|
28
|
-
|
|
29
|
-
errorCase?: never;
|
|
30
|
-
errorMessage?: never;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export type Invalid = {
|
|
34
|
-
isValid: false;
|
|
35
|
-
errorCase: "expired" | "invalid signature" | "does not respect schema";
|
|
36
|
-
errorMessage: string;
|
|
37
|
-
|
|
38
|
-
decodedAccessToken?: never;
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export async function createOidcBackend<DecodedAccessToken extends Record<string, unknown>>(
|
|
43
|
-
params: ParamsOfCreateOidcBackend<DecodedAccessToken>
|
|
44
|
-
): Promise<OidcBackend<DecodedAccessToken>> {
|
|
45
|
-
const { issuerUri, decodedAccessTokenSchema = z.record(z.unknown()) } = params;
|
|
46
|
-
|
|
47
|
-
let publicSigningKeys = await fetchPublicSigningKeys({ issuerUri });
|
|
48
|
-
|
|
49
|
-
const evtInvalidSignature = Evt.create<void>();
|
|
50
|
-
|
|
51
|
-
evtInvalidSignature.pipe(throttleTime(3600_000)).attach(async () => {
|
|
52
|
-
const publicSigningKeys_new = await (async function callee(
|
|
53
|
-
count: number
|
|
54
|
-
): Promise<PublicSigningKey[] | undefined> {
|
|
55
|
-
let wrap;
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
wrap = await fetchPublicSigningKeys({ issuerUri });
|
|
59
|
-
} catch (error) {
|
|
60
|
-
if (count === 9) {
|
|
61
|
-
console.warn(
|
|
62
|
-
`Failed to refresh public key and signing algorithm after ${count + 1} attempts`
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const delayMs = 1000 * Math.pow(2, count);
|
|
69
|
-
|
|
70
|
-
console.warn(
|
|
71
|
-
`Failed to refresh public key and signing algorithm: ${String(
|
|
72
|
-
error
|
|
73
|
-
)}, retrying in ${delayMs}ms`
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
77
|
-
|
|
78
|
-
return callee(count + 1);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return wrap;
|
|
82
|
-
})(0);
|
|
83
|
-
|
|
84
|
-
if (publicSigningKeys_new === undefined) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
publicSigningKeys = publicSigningKeys_new;
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
verifyAndDecodeAccessToken: ({ accessToken }) => {
|
|
93
|
-
let kid: string;
|
|
94
|
-
let alg: jwt.Algorithm;
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
const jwtHeader_b64 = accessToken.split(".")[0];
|
|
98
|
-
|
|
99
|
-
let jwtHeader: string;
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
jwtHeader = Buffer.from(jwtHeader_b64, "base64").toString("utf8");
|
|
103
|
-
} catch {
|
|
104
|
-
return {
|
|
105
|
-
isValid: false,
|
|
106
|
-
errorCase: "invalid signature",
|
|
107
|
-
errorMessage: "Failed to decode the JWT header as a base64 string"
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let decodedHeader: unknown;
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
decodedHeader = JSON.parse(jwtHeader);
|
|
115
|
-
} catch {
|
|
116
|
-
return {
|
|
117
|
-
isValid: false,
|
|
118
|
-
errorCase: "invalid signature",
|
|
119
|
-
errorMessage: "Failed to parse the JWT header as a JSON"
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
type DecodedHeader = {
|
|
124
|
-
kid: string;
|
|
125
|
-
alg: string;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const zDecodedHeader = z.object({
|
|
129
|
-
kid: z.string(),
|
|
130
|
-
alg: z.string()
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
assert<Equals<DecodedHeader, z.infer<typeof zDecodedHeader>>>();
|
|
134
|
-
|
|
135
|
-
try {
|
|
136
|
-
zDecodedHeader.parse(decodedHeader);
|
|
137
|
-
} catch {
|
|
138
|
-
return {
|
|
139
|
-
isValid: false,
|
|
140
|
-
errorCase: "invalid signature",
|
|
141
|
-
errorMessage: "The decoded JWT header does not have a kid property"
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
assert(is<DecodedHeader>(decodedHeader));
|
|
146
|
-
|
|
147
|
-
{
|
|
148
|
-
const supportedAlgs = [
|
|
149
|
-
"RS256",
|
|
150
|
-
"RS384",
|
|
151
|
-
"RS512",
|
|
152
|
-
"ES256",
|
|
153
|
-
"ES384",
|
|
154
|
-
"ES512",
|
|
155
|
-
"PS256",
|
|
156
|
-
"PS384",
|
|
157
|
-
"PS512"
|
|
158
|
-
] as const;
|
|
159
|
-
|
|
160
|
-
assert<
|
|
161
|
-
Equals<
|
|
162
|
-
(typeof supportedAlgs)[number] | "none" | "HS256" | "HS384" | "HS512",
|
|
163
|
-
jwt.Algorithm
|
|
164
|
-
>
|
|
165
|
-
>();
|
|
166
|
-
|
|
167
|
-
if (!isAmong(supportedAlgs, decodedHeader.alg)) {
|
|
168
|
-
return {
|
|
169
|
-
isValid: false,
|
|
170
|
-
errorCase: "invalid signature",
|
|
171
|
-
errorMessage: `Unsupported or too week algorithm ${decodedHeader.alg}`
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
kid = decodedHeader.kid;
|
|
177
|
-
alg = decodedHeader.alg;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const publicSigningKey = publicSigningKeys.find(
|
|
181
|
-
publicSigningKey => publicSigningKey.kid === kid
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
if (publicSigningKey === undefined) {
|
|
185
|
-
return {
|
|
186
|
-
isValid: false,
|
|
187
|
-
errorCase: "invalid signature",
|
|
188
|
-
errorMessage: `No public signing key found with kid ${kid}`
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
let result = id<ResultOfAccessTokenVerify<DecodedAccessToken> | undefined>(undefined);
|
|
193
|
-
|
|
194
|
-
jwt.verify(
|
|
195
|
-
accessToken,
|
|
196
|
-
publicSigningKey.publicKey,
|
|
197
|
-
{ algorithms: [alg] },
|
|
198
|
-
(err, decoded) => {
|
|
199
|
-
invalid: {
|
|
200
|
-
if (!err) {
|
|
201
|
-
break invalid;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (err.name === "TokenExpiredError") {
|
|
205
|
-
result = id<ResultOfAccessTokenVerify.Invalid>({
|
|
206
|
-
isValid: false,
|
|
207
|
-
errorCase: "expired",
|
|
208
|
-
errorMessage: err.message
|
|
209
|
-
});
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
evtInvalidSignature.post();
|
|
214
|
-
|
|
215
|
-
result = id<ResultOfAccessTokenVerify.Invalid>({
|
|
216
|
-
isValid: false,
|
|
217
|
-
errorCase: "invalid signature",
|
|
218
|
-
errorMessage: err.message
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
let decodedAccessToken: DecodedAccessToken;
|
|
225
|
-
|
|
226
|
-
try {
|
|
227
|
-
decodedAccessToken = decodedAccessTokenSchema.parse(
|
|
228
|
-
decoded
|
|
229
|
-
) as DecodedAccessToken;
|
|
230
|
-
} catch (error) {
|
|
231
|
-
result = id<ResultOfAccessTokenVerify.Invalid>({
|
|
232
|
-
isValid: false,
|
|
233
|
-
errorCase: "does not respect schema",
|
|
234
|
-
errorMessage: String(error)
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
result = id<ResultOfAccessTokenVerify.Valid<DecodedAccessToken>>({
|
|
241
|
-
isValid: true,
|
|
242
|
-
decodedAccessToken: decodedAccessToken
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
assert(result !== undefined, "0522e6");
|
|
248
|
-
|
|
249
|
-
return result;
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
type PublicSigningKey = {
|
|
255
|
-
kid: string;
|
|
256
|
-
publicKey: string;
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
async function fetchPublicSigningKeys(params: { issuerUri: string }): Promise<PublicSigningKey[]> {
|
|
260
|
-
const { issuerUri } = params;
|
|
261
|
-
|
|
262
|
-
const { jwks_uri } = await (async () => {
|
|
263
|
-
const url = `${issuerUri.replace(/\/$/, "")}/.well-known/openid-configuration`;
|
|
264
|
-
|
|
265
|
-
const response = await fetch(url);
|
|
266
|
-
|
|
267
|
-
if (!response.ok) {
|
|
268
|
-
throw new Error(
|
|
269
|
-
`Failed to fetch openid configuration of the issuerUri: ${issuerUri} (${url}): ${response.statusText}`
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
let data: unknown;
|
|
274
|
-
|
|
275
|
-
try {
|
|
276
|
-
data = await response.json();
|
|
277
|
-
} catch (error) {
|
|
278
|
-
throw new Error(`Failed to parse json from ${url}: ${String(error)}`);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
{
|
|
282
|
-
type WellKnownConfiguration = {
|
|
283
|
-
jwks_uri: string;
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const zWellKnownConfiguration = z.object({
|
|
287
|
-
jwks_uri: z.string()
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
assert<Equals<WellKnownConfiguration, z.infer<typeof zWellKnownConfiguration>>>();
|
|
291
|
-
|
|
292
|
-
try {
|
|
293
|
-
zWellKnownConfiguration.parse(data);
|
|
294
|
-
} catch {
|
|
295
|
-
throw new Error(`${url} does not have a jwks_uri property`);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
assert(is<WellKnownConfiguration>(data));
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const { jwks_uri } = data;
|
|
302
|
-
|
|
303
|
-
return { jwks_uri };
|
|
304
|
-
})();
|
|
305
|
-
|
|
306
|
-
const { jwks } = await (async () => {
|
|
307
|
-
const response = await fetch(jwks_uri);
|
|
308
|
-
|
|
309
|
-
if (!response.ok) {
|
|
310
|
-
throw new Error(
|
|
311
|
-
`Failed to fetch public key and algorithm from ${jwks_uri}: ${response.statusText}`
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
let jwks: unknown;
|
|
316
|
-
|
|
317
|
-
try {
|
|
318
|
-
jwks = await response.json();
|
|
319
|
-
} catch (error) {
|
|
320
|
-
throw new Error(`Failed to parse json from ${jwks_uri}: ${String(error)}`);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
{
|
|
324
|
-
type Jwks = {
|
|
325
|
-
keys: {
|
|
326
|
-
kid: string;
|
|
327
|
-
kty: string;
|
|
328
|
-
e?: string;
|
|
329
|
-
n?: string;
|
|
330
|
-
use: string;
|
|
331
|
-
}[];
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
const zJwks = z.object({
|
|
335
|
-
keys: z.array(
|
|
336
|
-
z.object({
|
|
337
|
-
kid: z.string(),
|
|
338
|
-
kty: z.string(),
|
|
339
|
-
e: z.string().optional(),
|
|
340
|
-
n: z.string().optional(),
|
|
341
|
-
use: z.string()
|
|
342
|
-
})
|
|
343
|
-
)
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
assert<Equals<Jwks, z.infer<typeof zJwks>>>();
|
|
347
|
-
|
|
348
|
-
try {
|
|
349
|
-
zJwks.parse(jwks);
|
|
350
|
-
} catch {
|
|
351
|
-
throw new Error(`${jwks_uri} does not have the expected shape`);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
assert(is<Jwks>(jwks));
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
return { jwks };
|
|
358
|
-
})();
|
|
359
|
-
|
|
360
|
-
const publicSigningKeys: PublicSigningKey[] = await Promise.all(
|
|
361
|
-
jwks.keys
|
|
362
|
-
.filter(({ use }) => use === "sig")
|
|
363
|
-
.map(({ kid, kty, e, n }) => {
|
|
364
|
-
if (kty !== "RSA") {
|
|
365
|
-
return undefined;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
assert(e !== undefined, "e is undefined");
|
|
369
|
-
assert(n !== undefined, "n is undefined");
|
|
370
|
-
|
|
371
|
-
return { kid, e, n };
|
|
372
|
-
})
|
|
373
|
-
.filter(exclude(undefined))
|
|
374
|
-
.map(async ({ kid, e, n }) => {
|
|
375
|
-
const key = await JWK.asKey({ kty: "RSA", e, n });
|
|
376
|
-
const publicKey = key.toPEM(false);
|
|
377
|
-
|
|
378
|
-
return {
|
|
379
|
-
kid,
|
|
380
|
-
publicKey
|
|
381
|
-
};
|
|
382
|
-
})
|
|
383
|
-
);
|
|
384
|
-
|
|
385
|
-
assert(
|
|
386
|
-
publicSigningKeys.length !== 0,
|
|
387
|
-
`No public signing key found at ${jwks_uri}, ${JSON.stringify(jwks, null, 2)}`
|
|
388
|
-
);
|
|
389
|
-
|
|
390
|
-
return publicSigningKeys;
|
|
391
|
-
}
|