@multiplatform.one/keycloak 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +0 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.native.js +0 -2
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/state.js +1 -1
- package/dist/cjs/state.js.map +1 -1
- package/dist/cjs/state.native.js +1 -1
- package/dist/cjs/state.native.js.map +1 -1
- package/dist/esm/hooks/useTokensFromQuery/index.native.mjs +2 -0
- package/dist/esm/index.js +0 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +0 -1
- package/dist/esm/index.native.js +0 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/keycloak/keycloak.native.mjs +84 -0
- package/dist/esm/provider/AuthProvider/AuthProvider.native.mjs +111 -0
- package/dist/esm/session/session.native.mjs +7 -0
- package/dist/esm/state.js +1 -1
- package/dist/esm/state.js.map +1 -1
- package/dist/esm/state.mjs +1 -1
- package/dist/esm/state.native.js +1 -1
- package/dist/esm/state.native.js.map +2 -2
- package/dist/jsx/hooks/useTokensFromQuery/index.native.mjs +2 -0
- package/dist/jsx/index.js +0 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +0 -1
- package/dist/jsx/index.native.js +0 -1
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/keycloak/keycloak.native.mjs +84 -0
- package/dist/jsx/provider/AuthProvider/AuthProvider.native.mjs +111 -0
- package/dist/jsx/session/session.native.mjs +7 -0
- package/dist/jsx/state.js +1 -1
- package/dist/jsx/state.js.map +1 -1
- package/dist/jsx/state.mjs +1 -1
- package/dist/jsx/state.native.js +1 -1
- package/dist/jsx/state.native.js.map +2 -2
- package/package.json +25 -37
- package/src/index.ts +0 -1
- package/src/state.ts +1 -1
- package/types/Authenticated.d.ts +0 -20
- package/types/Authenticated.d.ts.map +1 -1
- package/types/index.d.ts +0 -1
- package/types/index.d.ts.map +1 -1
- package/types/provider/AfterAuth.d.ts +0 -20
- package/types/provider/AfterAuth.d.ts.map +1 -1
- package/types/provider/AuthProvider/AuthProvider.d.ts +0 -20
- package/types/provider/AuthProvider/AuthProvider.d.ts.map +1 -1
- package/types/provider/AuthProvider/AuthProvider.native.d.ts +0 -20
- package/types/provider/AuthProvider/AuthProvider.native.d.ts.map +1 -1
- package/types/provider/KeycloakProvider.d.ts +0 -20
- package/types/provider/KeycloakProvider.d.ts.map +1 -1
- package/dist/cjs/apollo.js +0 -64
- package/dist/cjs/apollo.js.map +0 -6
- package/dist/cjs/apollo.native.js +0 -95
- package/dist/cjs/apollo.native.js.map +0 -6
- package/dist/esm/apollo.js +0 -49
- package/dist/esm/apollo.js.map +0 -6
- package/dist/esm/apollo.mjs +0 -44
- package/dist/esm/apollo.native.js +0 -74
- package/dist/esm/apollo.native.js.map +0 -6
- package/dist/jsx/apollo.js +0 -49
- package/dist/jsx/apollo.js.map +0 -6
- package/dist/jsx/apollo.mjs +0 -44
- package/dist/jsx/apollo.native.js +0 -74
- package/dist/jsx/apollo.native.js.map +0 -6
- package/src/apollo.ts +0 -95
- package/types/apollo.d.ts +0 -5
- package/types/apollo.d.ts.map +0 -1
package/dist/cjs/index.js
CHANGED
|
@@ -12,7 +12,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0
|
|
|
12
12
|
var src_exports = {};
|
|
13
13
|
module.exports = __toCommonJS(src_exports);
|
|
14
14
|
__reExport(src_exports, require("./Authenticated"), module.exports);
|
|
15
|
-
__reExport(src_exports, require("./apollo"), module.exports);
|
|
16
15
|
__reExport(src_exports, require("./authConfig"), module.exports);
|
|
17
16
|
__reExport(src_exports, require("./hooks"), module.exports);
|
|
18
17
|
__reExport(src_exports, require("./keycloak"), module.exports);
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts"],
|
|
4
|
-
"mappings": ";;;;;;;;;;;AAAA;AAAA;AAqBA,wBAAc,4BArBd;AAsBA,wBAAc,
|
|
4
|
+
"mappings": ";;;;;;;;;;;AAAA;AAAA;AAqBA,wBAAc,4BArBd;AAsBA,wBAAc,yBAtBd;AAuBA,wBAAc,oBAvBd;AAwBA,wBAAc,uBAxBd;AAyBA,wBAAc,uBAzBd;AA0BA,wBAAc,sBA1Bd;AA2BA,wBAAc,oBA3Bd;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/dist/cjs/index.native.js
CHANGED
|
@@ -12,7 +12,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0
|
|
|
12
12
|
var src_exports = {};
|
|
13
13
|
module.exports = __toCommonJS(src_exports);
|
|
14
14
|
__reExport(src_exports, require("./Authenticated"), module.exports);
|
|
15
|
-
__reExport(src_exports, require("./apollo"), module.exports);
|
|
16
15
|
__reExport(src_exports, require("./authConfig"), module.exports);
|
|
17
16
|
__reExport(src_exports, require("./hooks"), module.exports);
|
|
18
17
|
__reExport(src_exports, require("./keycloak"), module.exports);
|
|
@@ -22,7 +21,6 @@ __reExport(src_exports, require("./types"), module.exports);
|
|
|
22
21
|
// Annotate the CommonJS export names for ESM import in node:
|
|
23
22
|
0 && (module.exports = {
|
|
24
23
|
...require("./Authenticated"),
|
|
25
|
-
...require("./apollo"),
|
|
26
24
|
...require("./authConfig"),
|
|
27
25
|
...require("./hooks"),
|
|
28
26
|
...require("./keycloak"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Users/clayrisser/Projects/.bitspur/multiplatform.one/packages/keycloak/src/index.ts"],
|
|
4
|
-
"mappings": ";;;;;;;;;;;AAAA;;AAqBA,wBAAc,4BArBd;AAsBA,wBAAc,
|
|
4
|
+
"mappings": ";;;;;;;;;;;AAAA;;AAqBA,wBAAc,4BArBd;AAsBA,wBAAc,yBAtBd;AAuBA,wBAAc,oBAvBd;AAwBA,wBAAc,uBAxBd;AAyBA,wBAAc,uBAzBd;AA0BA,wBAAc,sBA1Bd;AA2BA,wBAAc,oBA3Bd;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/dist/cjs/state.js
CHANGED
|
@@ -18,7 +18,7 @@ __export(state_exports, {
|
|
|
18
18
|
useAuthState: () => useAuthState
|
|
19
19
|
});
|
|
20
20
|
module.exports = __toCommonJS(state_exports);
|
|
21
|
-
var
|
|
21
|
+
var import_multiplatform = require("multiplatform.one"), import_zustand = require("@multiplatform.one/zustand");
|
|
22
22
|
const persist = import_multiplatform.MultiPlatform.isIframe || !import_multiplatform.MultiPlatform.isNext && !import_multiplatform.MultiPlatform.isServer, { useStore } = (0, import_zustand.createStateStore)(
|
|
23
23
|
"auth",
|
|
24
24
|
{
|
package/dist/cjs/state.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/state.ts"],
|
|
4
|
-
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBA,
|
|
4
|
+
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBA,2BAA8B,8BAC9B,iBAAiC;AAE1B,MAAM,UAAU,mCAAc,YAAa,CAAC,mCAAc,UAAU,CAAC,mCAAc,UAEpF,EAAE,SAAS,QAAI;AAAA,EACnB;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,cAAc;AAAA,IACd,OAAO;AAAA,EACT;AAAA,EACA;AAAA,EACA,EAAE,QAAQ;AACZ;AAEO,SAAS,eAAe;AAC7B,SAAO,SAAS;AAClB;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/dist/cjs/state.native.js
CHANGED
|
@@ -18,7 +18,7 @@ __export(state_exports, {
|
|
|
18
18
|
useAuthState: () => useAuthState
|
|
19
19
|
});
|
|
20
20
|
module.exports = __toCommonJS(state_exports);
|
|
21
|
-
var
|
|
21
|
+
var import_multiplatform = require("multiplatform.one"), import_zustand = require("@multiplatform.one/zustand"), persist = import_multiplatform.MultiPlatform.isIframe || !import_multiplatform.MultiPlatform.isNext && !import_multiplatform.MultiPlatform.isServer, useStore = (0, import_zustand.createStateStore)("auth", {
|
|
22
22
|
idToken: "",
|
|
23
23
|
refreshToken: "",
|
|
24
24
|
token: ""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Users/clayrisser/Projects/.bitspur/multiplatform.one/packages/keycloak/src/state.ts"],
|
|
4
|
-
"mappings": ";;;;;;;;;;;;;;AAAA;;;;;;AAqBA,
|
|
4
|
+
"mappings": ";;;;;;;;;;;;;;AAAA;;;;;;AAqBA,2BAA8B,8BAC9B,iBAAiC,uCAEpBA,UAAUC,mCAAcC,YAAa,CAACD,mCAAcE,UAAU,CAACF,mCAAcG,UAElFC,eAAaC,iCACnB,QACA;EACEC,SAAS;EACTC,cAAc;EACdC,OAAO;AACT,GACAC,QACA;EAAEV;AAAQ,CAAA,EARJK;AAWD,SAASM,eAAAA;AACd,SAAON,SAAAA;AACT;",
|
|
5
5
|
"names": ["persist", "MultiPlatform", "isIframe", "isNext", "isServer", "useStore", "createStateStore", "idToken", "refreshToken", "token", "undefined", "useAuthState"]
|
|
6
6
|
}
|
package/dist/esm/index.js
CHANGED
package/dist/esm/index.js.map
CHANGED
package/dist/esm/index.mjs
CHANGED
package/dist/esm/index.native.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Users/clayrisser/Projects/.bitspur/multiplatform.one/packages/keycloak/src/index.ts"],
|
|
4
|
-
"mappings": "AAqBA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;
|
|
4
|
+
"mappings": "AAqBA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { KeycloakConfigContext } from "../keycloak/config.mjs";
|
|
2
|
+
import { KeycloakContext } from "./context.mjs";
|
|
3
|
+
import { MultiPlatform } from "multiplatform.one";
|
|
4
|
+
import { jwtDecode } from "jwt-decode";
|
|
5
|
+
import { useContext } from "react";
|
|
6
|
+
class Keycloak {
|
|
7
|
+
constructor(config, input, idToken, refreshToken, login, logout) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
typeof input == "string" ? (this.token = input, this.idToken = idToken, this.refreshToken = refreshToken) : typeof input == "object" && (typeof input.init == "function" ? this.keycloakClient = input : this.mock = input), this.token && !this._tokenParsed && (this._tokenParsed = jwtDecode(this.token)), this.idToken && !this._idTokenParsed && (this._idTokenParsed = jwtDecode(this.idToken)), this.refreshToken && !this._refreshTokenParsed && (this._refreshTokenParsed = jwtDecode(this.refreshToken)), this._login = login, this._logout = logout;
|
|
10
|
+
}
|
|
11
|
+
token;
|
|
12
|
+
idToken;
|
|
13
|
+
refreshToken;
|
|
14
|
+
_idTokenParsed;
|
|
15
|
+
_login;
|
|
16
|
+
_logout;
|
|
17
|
+
_refreshTokenParsed;
|
|
18
|
+
_tokenParsed;
|
|
19
|
+
keycloakClient;
|
|
20
|
+
mock;
|
|
21
|
+
get tokenParsed() {
|
|
22
|
+
return this.keycloakClient ? this.keycloakClient.tokenParsed : this._tokenParsed;
|
|
23
|
+
}
|
|
24
|
+
get idTokenParsed() {
|
|
25
|
+
return this.keycloakClient ? this.keycloakClient.idTokenParsed : this._idTokenParsed;
|
|
26
|
+
}
|
|
27
|
+
get refreshTokenParsed() {
|
|
28
|
+
return this.keycloakClient ? this.keycloakClient.refreshTokenParsed : this._refreshTokenParsed;
|
|
29
|
+
}
|
|
30
|
+
get clientId() {
|
|
31
|
+
return this.keycloakClient ? this.keycloakClient.clientId : this.tokenParsed?.azp || this.config.clientId;
|
|
32
|
+
}
|
|
33
|
+
get email() {
|
|
34
|
+
return this.keycloakClient ? this.keycloakClient.tokenParsed?.email : this.mock ? this.mock.email : this.tokenParsed?.email;
|
|
35
|
+
}
|
|
36
|
+
get realm() {
|
|
37
|
+
return this.keycloakClient ? this.keycloakClient.realm : this.tokenParsed?.iss?.split("/").pop() || this.config.realm;
|
|
38
|
+
}
|
|
39
|
+
get realmAccess() {
|
|
40
|
+
return this.keycloakClient ? this.keycloakClient.realmAccess : this.tokenParsed?.realm_access;
|
|
41
|
+
}
|
|
42
|
+
get resourceAccess() {
|
|
43
|
+
return this.keycloakClient ? this.keycloakClient.resourceAccess : this.tokenParsed?.resource_access;
|
|
44
|
+
}
|
|
45
|
+
get sessionId() {
|
|
46
|
+
return this.keycloakClient ? this.keycloakClient.sessionId : this.tokenParsed?.session_state;
|
|
47
|
+
}
|
|
48
|
+
get subject() {
|
|
49
|
+
return this.keycloakClient ? this.keycloakClient.subject : this.tokenParsed?.sub;
|
|
50
|
+
}
|
|
51
|
+
get username() {
|
|
52
|
+
return this.mock ? this.mock.username : this.tokenParsed?.preferred_username;
|
|
53
|
+
}
|
|
54
|
+
async getUserInfo() {
|
|
55
|
+
if (!this.authenticated) return;
|
|
56
|
+
const response = await fetch(`${this.config.url}/realms/${this.config.realm}/protocol/openid-connect/userinfo`, {
|
|
57
|
+
method: "GET",
|
|
58
|
+
headers: {
|
|
59
|
+
Authorization: "Bearer " + this.token,
|
|
60
|
+
Accept: "application/json"
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
if (response.ok) return response.json();
|
|
64
|
+
}
|
|
65
|
+
async login(options = {}) {
|
|
66
|
+
this.idToken = void 0, this.refreshToken = void 0, this.token = void 0, this.keycloakClient ? await this.keycloakClient.login(options) : await this._login?.(options);
|
|
67
|
+
}
|
|
68
|
+
async logout(options = {}) {
|
|
69
|
+
this.idToken = void 0, this.refreshToken = void 0, this.token = void 0, this.keycloakClient ? await this.keycloakClient.logout(options) : await this._logout?.(options);
|
|
70
|
+
}
|
|
71
|
+
get authenticated() {
|
|
72
|
+
return this.mock ? !0 : this.keycloakClient ? !!this.keycloakClient.authenticated : !this.tokenParsed?.exp || !this.idToken ? !1 : this.tokenParsed.exp > Date.now() / 1e3;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function useKeycloak() {
|
|
76
|
+
const keycloak = useContext(KeycloakContext),
|
|
77
|
+
keycloakConfig = useContext(KeycloakConfigContext);
|
|
78
|
+
if (keycloak) return keycloak;
|
|
79
|
+
if (MultiPlatform.isStorybook) return new Keycloak(keycloakConfig, {
|
|
80
|
+
email: "storybook@example.com",
|
|
81
|
+
username: "storybook"
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
export { Keycloak, useKeycloak };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { useState, useEffect, useMemo, useCallback } from "react";
|
|
2
|
+
import { AfterAuth } from "../AfterAuth.mjs";
|
|
3
|
+
import { Keycloak, KeycloakConfigContext } from "../../keycloak/index.mjs";
|
|
4
|
+
import { KeycloakContext } from "../../keycloak/context.mjs";
|
|
5
|
+
import { makeRedirectUri, useAuthRequest, useAutoDiscovery, refreshAsync, exchangeCodeAsync } from "expo-auth-session";
|
|
6
|
+
import { persist, useAuthState } from "../../state.mjs";
|
|
7
|
+
import { validOrRefreshableToken, isTokenExpired } from "../../token.mjs";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
const REFRESH_THRESHOLD = 5;
|
|
10
|
+
function AuthProvider({
|
|
11
|
+
children,
|
|
12
|
+
keycloakConfig
|
|
13
|
+
}) {
|
|
14
|
+
const [keycloak, setKeycloak] = useState(),
|
|
15
|
+
authState = useAuthState(),
|
|
16
|
+
initialRefreshToken = useMemo(() => validOrRefreshableToken(persist && authState.refreshToken || !1), []),
|
|
17
|
+
keycloakUrl = `${keycloakConfig?.url}/realms/${keycloakConfig?.realm}`,
|
|
18
|
+
clientId = keycloakConfig.publicClientId || keycloakConfig?.clientId || "",
|
|
19
|
+
discovery = useAutoDiscovery(keycloakUrl),
|
|
20
|
+
redirectUri = makeRedirectUri(),
|
|
21
|
+
[tokens, setTokens] = useState({
|
|
22
|
+
refreshToken: initialRefreshToken,
|
|
23
|
+
token: validOrRefreshableToken(persist && authState.token || !1, initialRefreshToken),
|
|
24
|
+
idToken: validOrRefreshableToken(persist && authState.idToken || !1, initialRefreshToken)
|
|
25
|
+
}),
|
|
26
|
+
scopes = useMemo(() => [... /* @__PURE__ */new Set(["email", "openid", "profile", ...(keycloakConfig.scopes || [])])], [keycloakConfig.scopes]),
|
|
27
|
+
[request, response, promptAsync] = useAuthRequest({
|
|
28
|
+
clientId,
|
|
29
|
+
redirectUri,
|
|
30
|
+
scopes
|
|
31
|
+
}, discovery);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
!discovery || !response?.type || !request?.codeVerifier || !clientId || (async () => {
|
|
34
|
+
if (response?.type === "success" && request.codeVerifier && response.params.code) {
|
|
35
|
+
const tokenResponse = await exchangeCodeAsync({
|
|
36
|
+
clientId,
|
|
37
|
+
code: response.params.code,
|
|
38
|
+
redirectUri,
|
|
39
|
+
scopes,
|
|
40
|
+
extraParams: {
|
|
41
|
+
code_verifier: request.codeVerifier
|
|
42
|
+
}
|
|
43
|
+
}, discovery);
|
|
44
|
+
tokenResponse && setTokens({
|
|
45
|
+
idToken: tokenResponse.idToken,
|
|
46
|
+
refreshToken: tokenResponse.refreshToken,
|
|
47
|
+
token: tokenResponse.accessToken
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
}, [!discovery, request?.codeVerifier, response?.type === "success" ? response?.params?.code : void 0, clientId, scopes, redirectUri]);
|
|
52
|
+
const resetTokens = useCallback(() => {
|
|
53
|
+
authState.setIdToken(""), authState.setRefreshToken(""), authState.setToken(""), setTokens({
|
|
54
|
+
refreshToken: void 0,
|
|
55
|
+
token: void 0,
|
|
56
|
+
idToken: void 0
|
|
57
|
+
});
|
|
58
|
+
}, []),
|
|
59
|
+
refreshTokens = useCallback(async () => {
|
|
60
|
+
if (discovery) if (typeof tokens.refreshToken == "string") {
|
|
61
|
+
if (isTokenExpired(tokens.refreshToken)) resetTokens();else {
|
|
62
|
+
const tokenResponse = await refreshAsync({
|
|
63
|
+
clientId,
|
|
64
|
+
refreshToken: tokens.refreshToken,
|
|
65
|
+
scopes
|
|
66
|
+
}, discovery);
|
|
67
|
+
tokenResponse ? setTokens({
|
|
68
|
+
idToken: tokenResponse.idToken,
|
|
69
|
+
refreshToken: tokenResponse.refreshToken,
|
|
70
|
+
token: tokenResponse.accessToken
|
|
71
|
+
}) : resetTokens();
|
|
72
|
+
}
|
|
73
|
+
} else authState.refreshToken && typeof authState.refreshToken == "string" && isTokenExpired(authState.refreshToken) && resetTokens();
|
|
74
|
+
}, [!discovery, tokens.refreshToken, clientId, scopes]);
|
|
75
|
+
return useEffect(() => {
|
|
76
|
+
discovery && refreshTokens();
|
|
77
|
+
}, [!discovery]), useEffect(() => {
|
|
78
|
+
if (!request) return;
|
|
79
|
+
let refreshHandle;
|
|
80
|
+
return (async () => {
|
|
81
|
+
if (tokens.token && isTokenExpired(tokens.token)) await refreshTokens();else {
|
|
82
|
+
const _keycloak = new Keycloak(keycloakConfig, tokens.token || void 0, tokens.idToken || void 0, tokens.refreshToken || void 0, async options => {
|
|
83
|
+
await promptAsync(options);
|
|
84
|
+
}, async _options => {
|
|
85
|
+
resetTokens();
|
|
86
|
+
});
|
|
87
|
+
if (_keycloak.tokenParsed?.exp) {
|
|
88
|
+
const timeout = Math.max(Math.min(_keycloak.tokenParsed.exp, _keycloak.refreshTokenParsed?.exp || 0) - Math.floor(Date.now() / 1e3) - REFRESH_THRESHOLD, REFRESH_THRESHOLD) * 1e3;
|
|
89
|
+
if (timeout > 0) refreshHandle = setTimeout(() => {
|
|
90
|
+
refreshTokens();
|
|
91
|
+
}, timeout);else {
|
|
92
|
+
setTimeout(() => _keycloak.logout(), Math.max(0, timeout + REFRESH_THRESHOLD) * 1e3);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
setKeycloak(_keycloak);
|
|
97
|
+
}
|
|
98
|
+
})(), () => {
|
|
99
|
+
refreshHandle && clearTimeout(refreshHandle);
|
|
100
|
+
};
|
|
101
|
+
}, [!request, tokens.token, tokens.idToken, tokens.refreshToken, refreshTokens]), /* @__PURE__ */jsx(KeycloakConfigContext.Provider, {
|
|
102
|
+
value: keycloakConfig,
|
|
103
|
+
children: /* @__PURE__ */jsx(KeycloakContext.Provider, {
|
|
104
|
+
value: keycloak,
|
|
105
|
+
children: /* @__PURE__ */jsx(AfterAuth, {
|
|
106
|
+
children
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
export { AuthProvider };
|
package/dist/esm/state.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createStateStore } from "multiplatform.one/zustand";
|
|
2
1
|
import { MultiPlatform } from "multiplatform.one";
|
|
2
|
+
import { createStateStore } from "@multiplatform.one/zustand";
|
|
3
3
|
const persist = MultiPlatform.isIframe || !MultiPlatform.isNext && !MultiPlatform.isServer, { useStore } = createStateStore(
|
|
4
4
|
"auth",
|
|
5
5
|
{
|
package/dist/esm/state.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/state.ts"],
|
|
4
|
-
"mappings": "AAqBA,SAAS,
|
|
4
|
+
"mappings": "AAqBA,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AAE1B,MAAM,UAAU,cAAc,YAAa,CAAC,cAAc,UAAU,CAAC,cAAc,UAEpF,EAAE,SAAS,IAAI;AAAA,EACnB;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,cAAc;AAAA,IACd,OAAO;AAAA,EACT;AAAA,EACA;AAAA,EACA,EAAE,QAAQ;AACZ;AAEO,SAAS,eAAe;AAC7B,SAAO,SAAS;AAClB;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/dist/esm/state.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createStateStore } from "multiplatform.one/zustand";
|
|
2
1
|
import { MultiPlatform } from "multiplatform.one";
|
|
2
|
+
import { createStateStore } from "@multiplatform.one/zustand";
|
|
3
3
|
const persist = MultiPlatform.isIframe || !MultiPlatform.isNext && !MultiPlatform.isServer,
|
|
4
4
|
{
|
|
5
5
|
useStore
|
package/dist/esm/state.native.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createStateStore } from "multiplatform.one/zustand";
|
|
2
1
|
import { MultiPlatform } from "multiplatform.one";
|
|
2
|
+
import { createStateStore } from "@multiplatform.one/zustand";
|
|
3
3
|
var persist = MultiPlatform.isIframe || !MultiPlatform.isNext && !MultiPlatform.isServer, useStore = createStateStore("auth", {
|
|
4
4
|
idToken: "",
|
|
5
5
|
refreshToken: "",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Users/clayrisser/Projects/.bitspur/multiplatform.one/packages/keycloak/src/state.ts"],
|
|
4
|
-
"mappings": "AAqBA,SAASA,
|
|
5
|
-
"names": ["
|
|
4
|
+
"mappings": "AAqBA,SAASA,qBAAqB;AAC9B,SAASC,wBAAwB;AAE1B,IAAMC,UAAUF,cAAcG,YAAa,CAACH,cAAcI,UAAU,CAACJ,cAAcK,UAElFC,WAAaL,iBACnB,QACA;EACEM,SAAS;EACTC,cAAc;EACdC,OAAO;AACT,GACAC,QACA;EAAER;AAAQ,CAAA,EARJI;AAWD,SAASK,eAAAA;AACd,SAAOL,SAAAA;AACT;",
|
|
5
|
+
"names": ["MultiPlatform", "createStateStore", "persist", "isIframe", "isNext", "isServer", "useStore", "idToken", "refreshToken", "token", "undefined", "useAuthState"]
|
|
6
6
|
}
|
package/dist/jsx/index.js
CHANGED
package/dist/jsx/index.js.map
CHANGED
package/dist/jsx/index.mjs
CHANGED
package/dist/jsx/index.native.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Users/clayrisser/Projects/.bitspur/multiplatform.one/packages/keycloak/src/index.ts"],
|
|
4
|
-
"mappings": "AAqBA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;
|
|
4
|
+
"mappings": "AAqBA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { KeycloakConfigContext } from "../keycloak/config.mjs";
|
|
2
|
+
import { KeycloakContext } from "./context.mjs";
|
|
3
|
+
import { MultiPlatform } from "multiplatform.one";
|
|
4
|
+
import { jwtDecode } from "jwt-decode";
|
|
5
|
+
import { useContext } from "react";
|
|
6
|
+
class Keycloak {
|
|
7
|
+
constructor(config, input, idToken, refreshToken, login, logout) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
typeof input == "string" ? (this.token = input, this.idToken = idToken, this.refreshToken = refreshToken) : typeof input == "object" && (typeof input.init == "function" ? this.keycloakClient = input : this.mock = input), this.token && !this._tokenParsed && (this._tokenParsed = jwtDecode(this.token)), this.idToken && !this._idTokenParsed && (this._idTokenParsed = jwtDecode(this.idToken)), this.refreshToken && !this._refreshTokenParsed && (this._refreshTokenParsed = jwtDecode(this.refreshToken)), this._login = login, this._logout = logout;
|
|
10
|
+
}
|
|
11
|
+
token;
|
|
12
|
+
idToken;
|
|
13
|
+
refreshToken;
|
|
14
|
+
_idTokenParsed;
|
|
15
|
+
_login;
|
|
16
|
+
_logout;
|
|
17
|
+
_refreshTokenParsed;
|
|
18
|
+
_tokenParsed;
|
|
19
|
+
keycloakClient;
|
|
20
|
+
mock;
|
|
21
|
+
get tokenParsed() {
|
|
22
|
+
return this.keycloakClient ? this.keycloakClient.tokenParsed : this._tokenParsed;
|
|
23
|
+
}
|
|
24
|
+
get idTokenParsed() {
|
|
25
|
+
return this.keycloakClient ? this.keycloakClient.idTokenParsed : this._idTokenParsed;
|
|
26
|
+
}
|
|
27
|
+
get refreshTokenParsed() {
|
|
28
|
+
return this.keycloakClient ? this.keycloakClient.refreshTokenParsed : this._refreshTokenParsed;
|
|
29
|
+
}
|
|
30
|
+
get clientId() {
|
|
31
|
+
return this.keycloakClient ? this.keycloakClient.clientId : this.tokenParsed?.azp || this.config.clientId;
|
|
32
|
+
}
|
|
33
|
+
get email() {
|
|
34
|
+
return this.keycloakClient ? this.keycloakClient.tokenParsed?.email : this.mock ? this.mock.email : this.tokenParsed?.email;
|
|
35
|
+
}
|
|
36
|
+
get realm() {
|
|
37
|
+
return this.keycloakClient ? this.keycloakClient.realm : this.tokenParsed?.iss?.split("/").pop() || this.config.realm;
|
|
38
|
+
}
|
|
39
|
+
get realmAccess() {
|
|
40
|
+
return this.keycloakClient ? this.keycloakClient.realmAccess : this.tokenParsed?.realm_access;
|
|
41
|
+
}
|
|
42
|
+
get resourceAccess() {
|
|
43
|
+
return this.keycloakClient ? this.keycloakClient.resourceAccess : this.tokenParsed?.resource_access;
|
|
44
|
+
}
|
|
45
|
+
get sessionId() {
|
|
46
|
+
return this.keycloakClient ? this.keycloakClient.sessionId : this.tokenParsed?.session_state;
|
|
47
|
+
}
|
|
48
|
+
get subject() {
|
|
49
|
+
return this.keycloakClient ? this.keycloakClient.subject : this.tokenParsed?.sub;
|
|
50
|
+
}
|
|
51
|
+
get username() {
|
|
52
|
+
return this.mock ? this.mock.username : this.tokenParsed?.preferred_username;
|
|
53
|
+
}
|
|
54
|
+
async getUserInfo() {
|
|
55
|
+
if (!this.authenticated) return;
|
|
56
|
+
const response = await fetch(`${this.config.url}/realms/${this.config.realm}/protocol/openid-connect/userinfo`, {
|
|
57
|
+
method: "GET",
|
|
58
|
+
headers: {
|
|
59
|
+
Authorization: "Bearer " + this.token,
|
|
60
|
+
Accept: "application/json"
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
if (response.ok) return response.json();
|
|
64
|
+
}
|
|
65
|
+
async login(options = {}) {
|
|
66
|
+
this.idToken = void 0, this.refreshToken = void 0, this.token = void 0, this.keycloakClient ? await this.keycloakClient.login(options) : await this._login?.(options);
|
|
67
|
+
}
|
|
68
|
+
async logout(options = {}) {
|
|
69
|
+
this.idToken = void 0, this.refreshToken = void 0, this.token = void 0, this.keycloakClient ? await this.keycloakClient.logout(options) : await this._logout?.(options);
|
|
70
|
+
}
|
|
71
|
+
get authenticated() {
|
|
72
|
+
return this.mock ? !0 : this.keycloakClient ? !!this.keycloakClient.authenticated : !this.tokenParsed?.exp || !this.idToken ? !1 : this.tokenParsed.exp > Date.now() / 1e3;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function useKeycloak() {
|
|
76
|
+
const keycloak = useContext(KeycloakContext),
|
|
77
|
+
keycloakConfig = useContext(KeycloakConfigContext);
|
|
78
|
+
if (keycloak) return keycloak;
|
|
79
|
+
if (MultiPlatform.isStorybook) return new Keycloak(keycloakConfig, {
|
|
80
|
+
email: "storybook@example.com",
|
|
81
|
+
username: "storybook"
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
export { Keycloak, useKeycloak };
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { useState, useEffect, useMemo, useCallback } from "react";
|
|
2
|
+
import { AfterAuth } from "../AfterAuth.mjs";
|
|
3
|
+
import { Keycloak, KeycloakConfigContext } from "../../keycloak/index.mjs";
|
|
4
|
+
import { KeycloakContext } from "../../keycloak/context.mjs";
|
|
5
|
+
import { makeRedirectUri, useAuthRequest, useAutoDiscovery, refreshAsync, exchangeCodeAsync } from "expo-auth-session";
|
|
6
|
+
import { persist, useAuthState } from "../../state.mjs";
|
|
7
|
+
import { validOrRefreshableToken, isTokenExpired } from "../../token.mjs";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
const REFRESH_THRESHOLD = 5;
|
|
10
|
+
function AuthProvider({
|
|
11
|
+
children,
|
|
12
|
+
keycloakConfig
|
|
13
|
+
}) {
|
|
14
|
+
const [keycloak, setKeycloak] = useState(),
|
|
15
|
+
authState = useAuthState(),
|
|
16
|
+
initialRefreshToken = useMemo(() => validOrRefreshableToken(persist && authState.refreshToken || !1), []),
|
|
17
|
+
keycloakUrl = `${keycloakConfig?.url}/realms/${keycloakConfig?.realm}`,
|
|
18
|
+
clientId = keycloakConfig.publicClientId || keycloakConfig?.clientId || "",
|
|
19
|
+
discovery = useAutoDiscovery(keycloakUrl),
|
|
20
|
+
redirectUri = makeRedirectUri(),
|
|
21
|
+
[tokens, setTokens] = useState({
|
|
22
|
+
refreshToken: initialRefreshToken,
|
|
23
|
+
token: validOrRefreshableToken(persist && authState.token || !1, initialRefreshToken),
|
|
24
|
+
idToken: validOrRefreshableToken(persist && authState.idToken || !1, initialRefreshToken)
|
|
25
|
+
}),
|
|
26
|
+
scopes = useMemo(() => [... /* @__PURE__ */new Set(["email", "openid", "profile", ...(keycloakConfig.scopes || [])])], [keycloakConfig.scopes]),
|
|
27
|
+
[request, response, promptAsync] = useAuthRequest({
|
|
28
|
+
clientId,
|
|
29
|
+
redirectUri,
|
|
30
|
+
scopes
|
|
31
|
+
}, discovery);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
!discovery || !response?.type || !request?.codeVerifier || !clientId || (async () => {
|
|
34
|
+
if (response?.type === "success" && request.codeVerifier && response.params.code) {
|
|
35
|
+
const tokenResponse = await exchangeCodeAsync({
|
|
36
|
+
clientId,
|
|
37
|
+
code: response.params.code,
|
|
38
|
+
redirectUri,
|
|
39
|
+
scopes,
|
|
40
|
+
extraParams: {
|
|
41
|
+
code_verifier: request.codeVerifier
|
|
42
|
+
}
|
|
43
|
+
}, discovery);
|
|
44
|
+
tokenResponse && setTokens({
|
|
45
|
+
idToken: tokenResponse.idToken,
|
|
46
|
+
refreshToken: tokenResponse.refreshToken,
|
|
47
|
+
token: tokenResponse.accessToken
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
}, [!discovery, request?.codeVerifier, response?.type === "success" ? response?.params?.code : void 0, clientId, scopes, redirectUri]);
|
|
52
|
+
const resetTokens = useCallback(() => {
|
|
53
|
+
authState.setIdToken(""), authState.setRefreshToken(""), authState.setToken(""), setTokens({
|
|
54
|
+
refreshToken: void 0,
|
|
55
|
+
token: void 0,
|
|
56
|
+
idToken: void 0
|
|
57
|
+
});
|
|
58
|
+
}, []),
|
|
59
|
+
refreshTokens = useCallback(async () => {
|
|
60
|
+
if (discovery) if (typeof tokens.refreshToken == "string") {
|
|
61
|
+
if (isTokenExpired(tokens.refreshToken)) resetTokens();else {
|
|
62
|
+
const tokenResponse = await refreshAsync({
|
|
63
|
+
clientId,
|
|
64
|
+
refreshToken: tokens.refreshToken,
|
|
65
|
+
scopes
|
|
66
|
+
}, discovery);
|
|
67
|
+
tokenResponse ? setTokens({
|
|
68
|
+
idToken: tokenResponse.idToken,
|
|
69
|
+
refreshToken: tokenResponse.refreshToken,
|
|
70
|
+
token: tokenResponse.accessToken
|
|
71
|
+
}) : resetTokens();
|
|
72
|
+
}
|
|
73
|
+
} else authState.refreshToken && typeof authState.refreshToken == "string" && isTokenExpired(authState.refreshToken) && resetTokens();
|
|
74
|
+
}, [!discovery, tokens.refreshToken, clientId, scopes]);
|
|
75
|
+
return useEffect(() => {
|
|
76
|
+
discovery && refreshTokens();
|
|
77
|
+
}, [!discovery]), useEffect(() => {
|
|
78
|
+
if (!request) return;
|
|
79
|
+
let refreshHandle;
|
|
80
|
+
return (async () => {
|
|
81
|
+
if (tokens.token && isTokenExpired(tokens.token)) await refreshTokens();else {
|
|
82
|
+
const _keycloak = new Keycloak(keycloakConfig, tokens.token || void 0, tokens.idToken || void 0, tokens.refreshToken || void 0, async options => {
|
|
83
|
+
await promptAsync(options);
|
|
84
|
+
}, async _options => {
|
|
85
|
+
resetTokens();
|
|
86
|
+
});
|
|
87
|
+
if (_keycloak.tokenParsed?.exp) {
|
|
88
|
+
const timeout = Math.max(Math.min(_keycloak.tokenParsed.exp, _keycloak.refreshTokenParsed?.exp || 0) - Math.floor(Date.now() / 1e3) - REFRESH_THRESHOLD, REFRESH_THRESHOLD) * 1e3;
|
|
89
|
+
if (timeout > 0) refreshHandle = setTimeout(() => {
|
|
90
|
+
refreshTokens();
|
|
91
|
+
}, timeout);else {
|
|
92
|
+
setTimeout(() => _keycloak.logout(), Math.max(0, timeout + REFRESH_THRESHOLD) * 1e3);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
setKeycloak(_keycloak);
|
|
97
|
+
}
|
|
98
|
+
})(), () => {
|
|
99
|
+
refreshHandle && clearTimeout(refreshHandle);
|
|
100
|
+
};
|
|
101
|
+
}, [!request, tokens.token, tokens.idToken, tokens.refreshToken, refreshTokens]), /* @__PURE__ */jsx(KeycloakConfigContext.Provider, {
|
|
102
|
+
value: keycloakConfig,
|
|
103
|
+
children: /* @__PURE__ */jsx(KeycloakContext.Provider, {
|
|
104
|
+
value: keycloak,
|
|
105
|
+
children: /* @__PURE__ */jsx(AfterAuth, {
|
|
106
|
+
children
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
export { AuthProvider };
|
package/dist/jsx/state.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createStateStore } from "multiplatform.one/zustand";
|
|
2
1
|
import { MultiPlatform } from "multiplatform.one";
|
|
2
|
+
import { createStateStore } from "@multiplatform.one/zustand";
|
|
3
3
|
const persist = MultiPlatform.isIframe || !MultiPlatform.isNext && !MultiPlatform.isServer, { useStore } = createStateStore(
|
|
4
4
|
"auth",
|
|
5
5
|
{
|
package/dist/jsx/state.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/state.ts"],
|
|
4
|
-
"mappings": "AAqBA,SAAS,
|
|
4
|
+
"mappings": "AAqBA,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AAE1B,MAAM,UAAU,cAAc,YAAa,CAAC,cAAc,UAAU,CAAC,cAAc,UAEpF,EAAE,SAAS,IAAI;AAAA,EACnB;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,cAAc;AAAA,IACd,OAAO;AAAA,EACT;AAAA,EACA;AAAA,EACA,EAAE,QAAQ;AACZ;AAEO,SAAS,eAAe;AAC7B,SAAO,SAAS;AAClB;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|