diff --git a/package.json b/package.json index 8855b1f..51be40f 100755 --- a/package.json +++ b/package.json @@ -23,10 +23,14 @@ "license": "MIT", "keywords": [], "dependencies": { + "evt": "^2.4.1", + "jwt-decode": "^3.1.2", + "keycloak-js": "^21.0.1", "keycloakify": "^6.12.1", + "powerhooks": "^0.26.2", "react": "18.1.0", "react-dom": "18.1.0", - "evt": "^2.4.1" + "tsafe": "^1.4.3" }, "devDependencies": { "@types/node": "^15.3.1", @@ -41,7 +45,9 @@ "react-app/jest" ], "rules": { - "react-hooks/exhaustive-deps": "off" + "react-hooks/exhaustive-deps": "off", + "@typescript-eslint/no-redeclare": "off", + "no-labels": "off" } }, "browserslist": { diff --git a/public/silent-sso.html b/public/silent-sso.html new file mode 100644 index 0000000..2bf0c57 --- /dev/null +++ b/public/silent-sso.html @@ -0,0 +1,7 @@ + +
+ + + diff --git a/src/App/App.tsx b/src/App/App.tsx index 0d3ecfe..08b165f 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -1,11 +1,63 @@ import "./App.css"; import logo from "./logo.svg"; import myimg from "./myimg.png"; +import { createOidcClientProvider, useOidcClient } from "./oidc"; +import { addFooToQueryParams, addBarToQueryParams } from "../keycloak-theme/valuesTransferredOverUrl"; +import { Evt } from "evt"; +import { id } from "tsafe/id"; +import jwt_decode from "jwt-decode"; + +const { OidcClientProvider } = createOidcClientProvider({ + url: "https://auth.code.gouv.fr/auth", + realm: "keycloakify", + clientId: "starter", + log: console.log, + //The login pages will be in english. + getUiLocales: () => "en", + transformUrlBeforeRedirect: url => + [url] + //Instead of foo and bar you could have isDark for example or any other state that you wish to + //transfer from the main app to the login pages. + .map(url => addFooToQueryParams({ url, value: { foo: 42 } })) + .map(url => addBarToQueryParams({ url, "value": "value of bar transferred to login page" })) + [0], + // An event emitter that posts whenever the user interacts with the app + // This is to tell if we should allow the token to expires. + evtUserActivity: + Evt.merge([ + Evt.from(document, "mousemove"), + Evt.from(document, "keydown") + ]).pipe(() => [id{JSON.stringify(jwt_decode(oidcClient.accessToken))}+ + > + : + <> + + > + }
Hello world
diff --git a/src/App/oidc.tsx b/src/App/oidc.tsx new file mode 100644 index 0000000..036437e --- /dev/null +++ b/src/App/oidc.tsx @@ -0,0 +1,206 @@ +import { useState, useContext, createContext, useEffect } from "react"; +import keycloak_js from "keycloak-js"; +import { id } from "tsafe/id"; +import { addParamToUrl } from "powerhooks/tools/urlSearchParams"; +import type { ReturnType } from "tsafe/ReturnType"; +import type { Param0 } from "tsafe/Param0"; +import { assert } from "tsafe/assert"; +import { createKeycloakAdapter } from "keycloakify"; +import type { NonPostableEvt } from "evt"; +import jwt_decode from "jwt-decode"; + +export declare type OidcClient = OidcClient.LoggedIn | OidcClient.NotLoggedIn; + +export declare namespace OidcClient { + export type NotLoggedIn = { + isUserLoggedIn: false; + login: (params: { + //To prevent infinite loop if the user click login then cancel. + doesCurrentHrefRequiresAuth: boolean; + }) => Promise