@frontegg/nextjs 5.4.0 → 5.5.0-alpha.2630278530
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 +214 -4
- package/helpers.d.ts +2 -0
- package/index.cjs.js +102 -29
- package/index.esm.js +84 -30
- package/package.json +4 -4
- package/withFronteggApp.d.ts +5 -3
package/README.md
CHANGED
|
@@ -1,7 +1,217 @@
|
|
|
1
|
-
|
|
1
|
+

|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Frontegg is a web platform where SaaS companies can set up their fully managed, scalable and brand aware - SaaS features
|
|
4
|
+
and integrate them into their SaaS portals in up to 5 lines of code.
|
|
4
5
|
|
|
5
|
-
##
|
|
6
|
+
## Table of Contents
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Create new NextJS project](#create-new-nextjs-project)
|
|
10
|
+
- [Add to existing project](#add-to-existing-project)
|
|
11
|
+
- [Getting Started](#getting-started)
|
|
12
|
+
- [Create Frontegg worksapce](#create-frontegg-worksapce)
|
|
13
|
+
- [Setup environment](#setup-environment)
|
|
14
|
+
- [Documentation](#documentation)
|
|
15
|
+
- [API Reference](#api-reference)
|
|
16
|
+
- [Frontegg Provider Options](#frontegg-provider-options)
|
|
17
|
+
- [getSession](#getsession)
|
|
18
|
+
- [withSSRSession](#withssrsession)
|
|
19
|
+
- for more [visit](https://docs.frontegg.com/docs/self-service-introduction)
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
### Create new NextJS project
|
|
24
|
+
|
|
25
|
+
To start a new Create Next App project with TypeScript, you can run:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx create-next-app --example "https://github.com/frontegg/frontegg-nextjs/tree/main" --example-path "apps/example" my-nextjs-app-name
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
or
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
yarn create next-app --example "https://github.com/frontegg/frontegg-nextjs/tree/main" --example-path "apps/example" my-nextjs-app-name
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> If you've previously installed `create-react-app` globally via `npm install -g create-next-app`, we recommend you uninstall the package using `npm uninstall -g create-next-app` or `yarn global remove create-next-app` to ensure that `npx` always uses the latest version.
|
|
38
|
+
>
|
|
39
|
+
> Global installations of `create-next-app` are no longer supported.
|
|
40
|
+
|
|
41
|
+
### Add to existing project
|
|
42
|
+
|
|
43
|
+
To Add Frontegg to your existing Nextjs project, follow below steps:
|
|
44
|
+
|
|
45
|
+
1. Use package manager to install Frontegg Next.JS library.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install --save @frontegg/nextjs
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
or
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
yarn add --save @frontegg/nextjs
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
2. Wrap the default export with `withFronteggApp` in `./pages/_app.tsx`:
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
// ./pages/_app.tsx
|
|
61
|
+
|
|
62
|
+
import { withFronteggApp } from '@frontegg/nextjs';
|
|
63
|
+
|
|
64
|
+
function CustomApp({ Component, pageProps }: AppProps) {
|
|
65
|
+
return <Component {...pageProps} />;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default withFronteggApp(CustomApp);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
3. Create files for frontegg middleware under `./pages/api/frontegg/[...frontegg-middleware].ts`:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
// ./pages/api/frontegg/[...frontegg-middleware].ts
|
|
75
|
+
|
|
76
|
+
export { fronteggMiddleware as default } from '@frontegg/nextjs';
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
4. Create placeholder pages for frontegg router under `./pages/[...frontegg-router].tsx`:
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
// ./pages/[...frontegg-router].tsx
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
FronteggRouter as default,
|
|
86
|
+
FronteggRouterProps as getServerSideProps,
|
|
87
|
+
} from '@frontegg/nextjs';
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Getting Started
|
|
91
|
+
|
|
92
|
+
### Create Frontegg worksapce
|
|
93
|
+
|
|
94
|
+
Navigate to [Frontegg Portal Settgins](https://portal.frontegg.com/development/settings), If you don't have application
|
|
95
|
+
follow integration steps after signing up.
|
|
96
|
+
|
|
97
|
+
Next, configure the "Allowed Origins" in your application under "Domain" tab of the "Settings" page :
|
|
98
|
+
|
|
99
|
+
- http://localhost:3000 // for development environments
|
|
100
|
+
- https://my-company-domain.com // for production environments
|
|
101
|
+
|
|
102
|
+
Copy ClientID, Frontegg Domain from "Settings" page, You'll need these values in the next step.
|
|
103
|
+
|
|
104
|
+
### Setup environment
|
|
105
|
+
|
|
106
|
+
To setup your Next.js application to communicate with Frontegg, you have to create a new file named `.env.local` under
|
|
107
|
+
your root project directory, this file will be used to store environment variables that will be used, configuration
|
|
108
|
+
options:
|
|
109
|
+
|
|
110
|
+
```dotenv
|
|
111
|
+
# The AppUrl is to tell Frontegg your application hostname
|
|
112
|
+
FRONTEGG_APP_URL='http://localhost:3000'
|
|
113
|
+
|
|
114
|
+
# The Frontegg domain is your unique URL to connect to the Frontegg gateway
|
|
115
|
+
FRONTEGG_BASE_URL='https://{YOUR_SUB_DOMAIN}.frontegg.com'
|
|
116
|
+
|
|
117
|
+
# Your Frontegg application's Client ID
|
|
118
|
+
FRONTEGG_CLIENT_ID='{YOUR_APPLICATION_CLIENT_ID}'
|
|
119
|
+
|
|
120
|
+
# The statless session encruption password, used to encrypt
|
|
121
|
+
# jwt before sending it to the client side.
|
|
122
|
+
#
|
|
123
|
+
# For quick password generation use the following command:
|
|
124
|
+
# node -e "console.log(crypto.randomBytes(32).toString('hex'))"
|
|
125
|
+
FRONTEGG_ENCRYPTION_PASSWORD='{SESSION_ENCRYPTION_PASSWORD}'
|
|
126
|
+
|
|
127
|
+
# The statless session cookie name
|
|
128
|
+
FRONTEGG_COOKIE_NAME='fe_session'
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Documentation
|
|
132
|
+
|
|
133
|
+
### API Reference
|
|
134
|
+
|
|
135
|
+
Visit [Frontegg Docs](https://docs.frontegg.com) for the full documentation.
|
|
136
|
+
|
|
137
|
+
### Frontegg Provider Options
|
|
138
|
+
|
|
139
|
+
Pass seconds argument to `withFronteggApp` function in `_app.ts` file to customize
|
|
140
|
+
Frontegg library.
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
// ./pages/_app.tsx
|
|
144
|
+
|
|
145
|
+
import { withFronteggApp } from '@frontegg/nextjs';
|
|
146
|
+
|
|
147
|
+
function CustomApp({ Component, pageProps }: AppProps) {
|
|
148
|
+
return <Component {...pageProps} />;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export default withFronteggApp(CustomApp, {
|
|
152
|
+
/**
|
|
153
|
+
* Frontegg options for customizations
|
|
154
|
+
*/
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### getSession
|
|
159
|
+
|
|
160
|
+
For any pages that required AccessToken in Server Side, you can use:
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
import { GetServerSideProps } from 'next';
|
|
164
|
+
import { getSession } from '@frontegg/nextjs';
|
|
165
|
+
|
|
166
|
+
export default function MyPage({ products }) {
|
|
167
|
+
return (
|
|
168
|
+
<div>
|
|
169
|
+
<h1>My Page</h1>
|
|
170
|
+
{products}
|
|
171
|
+
</div>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const getServerSideProps: GetServerSideProps = async (context) => {
|
|
176
|
+
const session = await getSession(context.req);
|
|
177
|
+
if (session) {
|
|
178
|
+
const { data } = await fetch('{external}/product', {
|
|
179
|
+
headers: {
|
|
180
|
+
Authorization: 'bearer ' + session.accessToken,
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
return { props: { products: data } };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return { props: { products: [] } };
|
|
187
|
+
};
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### withSSRSession
|
|
191
|
+
|
|
192
|
+
withSSRSession HOC can be used to automatic redirect users to login screen if not logged in:
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { GetServerSideProps } from 'next';
|
|
196
|
+
import { withSSRSession } from '@frontegg/nextjs';
|
|
197
|
+
|
|
198
|
+
export default function MyPage({ products }) {
|
|
199
|
+
return (
|
|
200
|
+
<div>
|
|
201
|
+
<h1>My Page</h1>
|
|
202
|
+
{products}
|
|
203
|
+
</div>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export const getServerSideProps: GetServerSideProps = withSSRSession(
|
|
208
|
+
async (context, session) => {
|
|
209
|
+
const { data } = await fetch('{external}/product', {
|
|
210
|
+
headers: {
|
|
211
|
+
Authorization: 'bearer ' + session.accessToken,
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
return { props: { products: data } };
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
```
|
package/helpers.d.ts
CHANGED
|
@@ -5,5 +5,7 @@ import { FronteggNextJSSession } from './types';
|
|
|
5
5
|
export declare function refreshToken(ctx: NextPageContext): Promise<FronteggNextJSSession | null>;
|
|
6
6
|
export declare function addToCookies(cookieValue: string, res: ServerResponse): void;
|
|
7
7
|
export declare function removeCookies(cookieName: string, isSecured: boolean, cookieDomain: string, res: ServerResponse): void;
|
|
8
|
+
export declare function compress(input: string): Promise<string>;
|
|
9
|
+
export declare function uncompress(input: string): Promise<string>;
|
|
8
10
|
export declare function createSessionFromAccessToken(output: string): Promise<[string, any] | []>;
|
|
9
11
|
export declare const modifySetCookieIfUnsecure: (setCookieValue: string[] | undefined, isSecured: boolean) => string[] | undefined;
|
package/index.cjs.js
CHANGED
|
@@ -13,12 +13,32 @@ var reduxStore = require('@frontegg/redux-store');
|
|
|
13
13
|
var url = require('url');
|
|
14
14
|
var cookie = require('cookie');
|
|
15
15
|
var ironSession = require('iron-session');
|
|
16
|
+
var zlib = require('zlib');
|
|
16
17
|
var httpProxy = require('http-proxy');
|
|
17
18
|
var types = require('@frontegg/types');
|
|
18
19
|
|
|
19
20
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
20
21
|
|
|
22
|
+
function _interopNamespace(e) {
|
|
23
|
+
if (e && e.__esModule) return e;
|
|
24
|
+
var n = Object.create(null);
|
|
25
|
+
if (e) {
|
|
26
|
+
Object.keys(e).forEach(function (k) {
|
|
27
|
+
if (k !== 'default') {
|
|
28
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
29
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
get: function () { return e[k]; }
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
n["default"] = e;
|
|
37
|
+
return Object.freeze(n);
|
|
38
|
+
}
|
|
39
|
+
|
|
21
40
|
var cookie__default = /*#__PURE__*/_interopDefaultLegacy(cookie);
|
|
41
|
+
var zlib__namespace = /*#__PURE__*/_interopNamespace(zlib);
|
|
22
42
|
var httpProxy__default = /*#__PURE__*/_interopDefaultLegacy(httpProxy);
|
|
23
43
|
|
|
24
44
|
/******************************************************************************
|
|
@@ -1062,7 +1082,7 @@ var FronteggConfig = /*#__PURE__*/function () {
|
|
|
1062
1082
|
this.authRoutes = {};
|
|
1063
1083
|
this.fronteggAppOptions = {};
|
|
1064
1084
|
this._clientId = (_a = process.env['FRONTEGG_CLIENT_ID']) !== null && _a !== void 0 ? _a : '';
|
|
1065
|
-
this._cookieName = (_b = process.env['FRONTEGG_COOKIE_NAME']) !== null && _b !== void 0 ? _b : "
|
|
1085
|
+
this._cookieName = (_b = process.env['FRONTEGG_COOKIE_NAME']) !== null && _b !== void 0 ? _b : "fe_next_session";
|
|
1066
1086
|
this._password = (_c = process.env['FRONTEGG_ENCRYPTION_PASSWORD']) !== null && _c !== void 0 ? _c : '';
|
|
1067
1087
|
this._passwordsAsMap = normalizeStringPasswordToMap(this._password);
|
|
1068
1088
|
}
|
|
@@ -1070,7 +1090,7 @@ var FronteggConfig = /*#__PURE__*/function () {
|
|
|
1070
1090
|
_createClass(FronteggConfig, [{
|
|
1071
1091
|
key: "cookieName",
|
|
1072
1092
|
get: function get() {
|
|
1073
|
-
return this._cookieName;
|
|
1093
|
+
return "".concat(this._cookieName, "-").concat(this._clientId.replace(/-/g, ''));
|
|
1074
1094
|
}
|
|
1075
1095
|
}, {
|
|
1076
1096
|
key: "password",
|
|
@@ -1198,9 +1218,14 @@ function FronteggRouter() {
|
|
|
1198
1218
|
var app = react.useContext(AppContext);
|
|
1199
1219
|
|
|
1200
1220
|
var _useRouter = router.useRouter(),
|
|
1201
|
-
query = _useRouter.query
|
|
1221
|
+
query = _useRouter.query,
|
|
1222
|
+
replace = _useRouter.replace;
|
|
1202
1223
|
|
|
1203
1224
|
var loginWithRedirect = reactHooks.useLoginWithRedirect();
|
|
1225
|
+
|
|
1226
|
+
var _useLoginActions = reactHooks.useLoginActions(),
|
|
1227
|
+
logout = _useLoginActions.logout;
|
|
1228
|
+
|
|
1204
1229
|
react.useEffect(function () {
|
|
1205
1230
|
if (!app) {
|
|
1206
1231
|
return;
|
|
@@ -1216,21 +1241,31 @@ function FronteggRouter() {
|
|
|
1216
1241
|
var pathname = "/".concat(pathArr.join('/'));
|
|
1217
1242
|
|
|
1218
1243
|
if (pathname === routesObj.loginUrl) {
|
|
1244
|
+
if (queryParams.redirectUrl) {
|
|
1245
|
+
localStorage.setItem('FRONTEGG_AFTER_AUTH_REDIRECT_URL', "".concat(window.location.origin, "/").concat(queryParams.redirectUrl));
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1219
1248
|
loginWithRedirect();
|
|
1220
|
-
} else {
|
|
1221
|
-
|
|
1249
|
+
} else if (pathname === routesObj.logoutUrl) {
|
|
1250
|
+
var _baseUrl = app.options.contextOptions.baseUrl;
|
|
1251
|
+
var baseUrl = typeof _baseUrl === 'string' ? _baseUrl : _baseUrl('');
|
|
1252
|
+
logout(function () {
|
|
1253
|
+
window.location.href = "".concat(baseUrl, "/oauth/logout?post_logout_redirect_uri=").concat(encodeURIComponent(window.location.origin));
|
|
1254
|
+
});
|
|
1222
1255
|
}
|
|
1223
1256
|
}
|
|
1224
|
-
}, [app, query, loginWithRedirect]);
|
|
1257
|
+
}, [app, query, loginWithRedirect, logout, replace]);
|
|
1225
1258
|
return '';
|
|
1226
1259
|
}
|
|
1227
1260
|
function FronteggRouterProps(context) {
|
|
1261
|
+
var _a;
|
|
1262
|
+
|
|
1228
1263
|
var routesObj = Object.assign(Object.assign({}, reduxStore.authInitialState.routes), fronteggConfig.authRoutes);
|
|
1229
1264
|
var routesArr = Object.keys(routesObj).reduce(function (p, key) {
|
|
1230
1265
|
return [].concat(_toConsumableArray(p), [routesObj[key]]);
|
|
1231
1266
|
}, []);
|
|
1232
1267
|
|
|
1233
|
-
var _parse = url.parse(context.req.url, true),
|
|
1268
|
+
var _parse = url.parse((_a = context.resolvedUrl) !== null && _a !== void 0 ? _a : context.req.url, true),
|
|
1234
1269
|
pathname = _parse.pathname;
|
|
1235
1270
|
|
|
1236
1271
|
if (!pathname || pathname.startsWith('/_next/data')) {
|
|
@@ -1241,7 +1276,7 @@ function FronteggRouterProps(context) {
|
|
|
1241
1276
|
var notFound = routesArr.indexOf(pathname) === -1;
|
|
1242
1277
|
|
|
1243
1278
|
if (fronteggConfig.fronteggAppOptions.hostedLoginBox) {
|
|
1244
|
-
var _notFound = !(routesObj.loginUrl === pathname || routesObj.hostedLoginRedirectUrl === pathname);
|
|
1279
|
+
var _notFound = !(routesObj.loginUrl === pathname || routesObj.logoutUrl === pathname || routesObj.hostedLoginRedirectUrl === pathname);
|
|
1245
1280
|
|
|
1246
1281
|
return {
|
|
1247
1282
|
notFound: _notFound,
|
|
@@ -1314,7 +1349,7 @@ function _defineProperty(obj, key, value) {
|
|
|
1314
1349
|
|
|
1315
1350
|
function getSession(req) {
|
|
1316
1351
|
return __awaiter(this, void 0, void 0, /*#__PURE__*/regenerator.mark(function _callee() {
|
|
1317
|
-
var sealFromCookies, jwt, publicKey, _yield$jwtVerify, payload, session;
|
|
1352
|
+
var sealFromCookies, compressedJwt, jwt, publicKey, _yield$jwtVerify, payload, session;
|
|
1318
1353
|
|
|
1319
1354
|
return regenerator.wrap(function _callee$(_context) {
|
|
1320
1355
|
while (1) {
|
|
@@ -1337,16 +1372,21 @@ function getSession(req) {
|
|
|
1337
1372
|
});
|
|
1338
1373
|
|
|
1339
1374
|
case 6:
|
|
1340
|
-
|
|
1375
|
+
compressedJwt = _context.sent;
|
|
1341
1376
|
_context.next = 9;
|
|
1342
|
-
return
|
|
1377
|
+
return uncompress(compressedJwt);
|
|
1343
1378
|
|
|
1344
1379
|
case 9:
|
|
1345
|
-
|
|
1380
|
+
jwt = _context.sent;
|
|
1346
1381
|
_context.next = 12;
|
|
1347
|
-
return
|
|
1382
|
+
return fronteggConfig.getJwtPublicKey();
|
|
1348
1383
|
|
|
1349
1384
|
case 12:
|
|
1385
|
+
publicKey = _context.sent;
|
|
1386
|
+
_context.next = 15;
|
|
1387
|
+
return jose.jwtVerify(jwt, publicKey);
|
|
1388
|
+
|
|
1389
|
+
case 15:
|
|
1350
1390
|
_yield$jwtVerify = _context.sent;
|
|
1351
1391
|
payload = _yield$jwtVerify.payload;
|
|
1352
1392
|
session = {
|
|
@@ -1355,27 +1395,27 @@ function getSession(req) {
|
|
|
1355
1395
|
};
|
|
1356
1396
|
|
|
1357
1397
|
if (!(session.user.exp * 1000 < Date.now())) {
|
|
1358
|
-
_context.next =
|
|
1398
|
+
_context.next = 20;
|
|
1359
1399
|
break;
|
|
1360
1400
|
}
|
|
1361
1401
|
|
|
1362
1402
|
return _context.abrupt("return", undefined);
|
|
1363
1403
|
|
|
1364
|
-
case
|
|
1404
|
+
case 20:
|
|
1365
1405
|
return _context.abrupt("return", session);
|
|
1366
1406
|
|
|
1367
|
-
case
|
|
1368
|
-
_context.prev =
|
|
1407
|
+
case 23:
|
|
1408
|
+
_context.prev = 23;
|
|
1369
1409
|
_context.t0 = _context["catch"](0);
|
|
1370
1410
|
console.error(_context.t0);
|
|
1371
1411
|
return _context.abrupt("return", undefined);
|
|
1372
1412
|
|
|
1373
|
-
case
|
|
1413
|
+
case 27:
|
|
1374
1414
|
case "end":
|
|
1375
1415
|
return _context.stop();
|
|
1376
1416
|
}
|
|
1377
1417
|
}
|
|
1378
|
-
}, _callee, null, [[0,
|
|
1418
|
+
}, _callee, null, [[0, 23]]);
|
|
1379
1419
|
}));
|
|
1380
1420
|
}
|
|
1381
1421
|
function withSSRSession(handler) {
|
|
@@ -1383,7 +1423,7 @@ function withSSRSession(handler) {
|
|
|
1383
1423
|
|
|
1384
1424
|
return function (context) {
|
|
1385
1425
|
return __awaiter(_this, void 0, void 0, /*#__PURE__*/regenerator.mark(function _callee2() {
|
|
1386
|
-
var _a, session;
|
|
1426
|
+
var _a, _b, session, loginUrl;
|
|
1387
1427
|
|
|
1388
1428
|
return regenerator.wrap(function _callee2$(_context2) {
|
|
1389
1429
|
while (1) {
|
|
@@ -1403,15 +1443,21 @@ function withSSRSession(handler) {
|
|
|
1403
1443
|
return _context2.abrupt("return", handler(context, session));
|
|
1404
1444
|
|
|
1405
1445
|
case 7:
|
|
1446
|
+
loginUrl = (_a = fronteggConfig.authRoutes.loginUrl) !== null && _a !== void 0 ? _a : reduxStore.authInitialState.routes.loginUrl;
|
|
1447
|
+
|
|
1448
|
+
if (!loginUrl.startsWith('/')) {
|
|
1449
|
+
loginUrl = "/".concat(loginUrl);
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1406
1452
|
return _context2.abrupt("return", {
|
|
1407
1453
|
redirect: {
|
|
1408
1454
|
permanent: false,
|
|
1409
|
-
destination: "
|
|
1455
|
+
destination: "".concat(loginUrl, "?redirectUrl=").concat(encodeURIComponent((_b = context.resolvedUrl) !== null && _b !== void 0 ? _b : context.req.url))
|
|
1410
1456
|
},
|
|
1411
1457
|
props: {}
|
|
1412
1458
|
});
|
|
1413
1459
|
|
|
1414
|
-
case
|
|
1460
|
+
case 10:
|
|
1415
1461
|
case "end":
|
|
1416
1462
|
return _context2.stop();
|
|
1417
1463
|
}
|
|
@@ -1628,11 +1674,33 @@ function removeCookies(cookieName, isSecured, cookieDomain, res) {
|
|
|
1628
1674
|
|
|
1629
1675
|
res.setHeader('set-cookie', [].concat(_toConsumableArray(existingSetCookie), [cookieValue]));
|
|
1630
1676
|
}
|
|
1677
|
+
function compress(input) {
|
|
1678
|
+
return new Promise(function (resolve, reject) {
|
|
1679
|
+
zlib__namespace.brotliCompress(input, function (error, result) {
|
|
1680
|
+
if (error) {
|
|
1681
|
+
reject(error);
|
|
1682
|
+
} else {
|
|
1683
|
+
resolve(result.toString('base64'));
|
|
1684
|
+
}
|
|
1685
|
+
});
|
|
1686
|
+
});
|
|
1687
|
+
}
|
|
1688
|
+
function uncompress(input) {
|
|
1689
|
+
return new Promise(function (resolve, reject) {
|
|
1690
|
+
zlib__namespace.brotliDecompress(Buffer.from(input, 'base64'), function (error, result) {
|
|
1691
|
+
if (error) {
|
|
1692
|
+
reject(error);
|
|
1693
|
+
} else {
|
|
1694
|
+
resolve(result.toString('utf-8'));
|
|
1695
|
+
}
|
|
1696
|
+
});
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1631
1699
|
function createSessionFromAccessToken(output) {
|
|
1632
1700
|
var _a;
|
|
1633
1701
|
|
|
1634
1702
|
return __awaiter(this, void 0, void 0, /*#__PURE__*/regenerator.mark(function _callee2() {
|
|
1635
|
-
var data, accessToken, decodedJwt, session;
|
|
1703
|
+
var data, accessToken, decodedJwt, compressedAccessToken, session;
|
|
1636
1704
|
return regenerator.wrap(function _callee2$(_context2) {
|
|
1637
1705
|
while (1) {
|
|
1638
1706
|
switch (_context2.prev = _context2.next) {
|
|
@@ -1643,26 +1711,31 @@ function createSessionFromAccessToken(output) {
|
|
|
1643
1711
|
decodedJwt = jose.decodeJwt(accessToken);
|
|
1644
1712
|
decodedJwt.expiresIn = Math.floor((decodedJwt.exp * 1000 - Date.now()) / 1000);
|
|
1645
1713
|
_context2.next = 7;
|
|
1646
|
-
return
|
|
1714
|
+
return compress(accessToken);
|
|
1715
|
+
|
|
1716
|
+
case 7:
|
|
1717
|
+
compressedAccessToken = _context2.sent;
|
|
1718
|
+
_context2.next = 10;
|
|
1719
|
+
return ironSession.sealData(compressedAccessToken, {
|
|
1647
1720
|
password: fronteggConfig.passwordsAsMap,
|
|
1648
1721
|
ttl: decodedJwt.exp
|
|
1649
1722
|
});
|
|
1650
1723
|
|
|
1651
|
-
case
|
|
1724
|
+
case 10:
|
|
1652
1725
|
session = _context2.sent;
|
|
1653
1726
|
return _context2.abrupt("return", [session, decodedJwt]);
|
|
1654
1727
|
|
|
1655
|
-
case
|
|
1656
|
-
_context2.prev =
|
|
1728
|
+
case 14:
|
|
1729
|
+
_context2.prev = 14;
|
|
1657
1730
|
_context2.t0 = _context2["catch"](0);
|
|
1658
1731
|
return _context2.abrupt("return", []);
|
|
1659
1732
|
|
|
1660
|
-
case
|
|
1733
|
+
case 17:
|
|
1661
1734
|
case "end":
|
|
1662
1735
|
return _context2.stop();
|
|
1663
1736
|
}
|
|
1664
1737
|
}
|
|
1665
|
-
}, _callee2, null, [[0,
|
|
1738
|
+
}, _callee2, null, [[0, 14]]);
|
|
1666
1739
|
}));
|
|
1667
1740
|
}
|
|
1668
1741
|
var modifySetCookieIfUnsecure = function modifySetCookieIfUnsecure(setCookieValue, isSecured) {
|
package/index.esm.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { createContext, useCallback, useMemo, useEffect, useContext } from 'react';
|
|
3
3
|
import { AppHolder, initialize } from '@frontegg/admin-portal';
|
|
4
4
|
export { AdminPortal } from '@frontegg/admin-portal';
|
|
5
|
-
import { FronteggStoreProvider, useAuthUserOrNull, useAuthActions, useLoginWithRedirect } from '@frontegg/react-hooks';
|
|
5
|
+
import { FronteggStoreProvider, useAuthUserOrNull, useAuthActions, useLoginWithRedirect, useLoginActions } from '@frontegg/react-hooks';
|
|
6
6
|
export * from '@frontegg/react-hooks';
|
|
7
7
|
import { fronteggAuthApiRoutes, ContextHolder, fronteggRefreshTokenUrl } from '@frontegg/rest-api';
|
|
8
8
|
import { useRouter } from 'next/router';
|
|
@@ -11,6 +11,7 @@ import { authInitialState } from '@frontegg/redux-store';
|
|
|
11
11
|
import { parse } from 'url';
|
|
12
12
|
import cookie from 'cookie';
|
|
13
13
|
import { unsealData, sealData } from 'iron-session';
|
|
14
|
+
import * as zlib from 'zlib';
|
|
14
15
|
import httpProxy from 'http-proxy';
|
|
15
16
|
export * from '@frontegg/types';
|
|
16
17
|
|
|
@@ -1055,7 +1056,7 @@ var FronteggConfig = /*#__PURE__*/function () {
|
|
|
1055
1056
|
this.authRoutes = {};
|
|
1056
1057
|
this.fronteggAppOptions = {};
|
|
1057
1058
|
this._clientId = (_a = process.env['FRONTEGG_CLIENT_ID']) !== null && _a !== void 0 ? _a : '';
|
|
1058
|
-
this._cookieName = (_b = process.env['FRONTEGG_COOKIE_NAME']) !== null && _b !== void 0 ? _b : "
|
|
1059
|
+
this._cookieName = (_b = process.env['FRONTEGG_COOKIE_NAME']) !== null && _b !== void 0 ? _b : "fe_next_session";
|
|
1059
1060
|
this._password = (_c = process.env['FRONTEGG_ENCRYPTION_PASSWORD']) !== null && _c !== void 0 ? _c : '';
|
|
1060
1061
|
this._passwordsAsMap = normalizeStringPasswordToMap(this._password);
|
|
1061
1062
|
}
|
|
@@ -1063,7 +1064,7 @@ var FronteggConfig = /*#__PURE__*/function () {
|
|
|
1063
1064
|
_createClass(FronteggConfig, [{
|
|
1064
1065
|
key: "cookieName",
|
|
1065
1066
|
get: function get() {
|
|
1066
|
-
return this._cookieName;
|
|
1067
|
+
return "".concat(this._cookieName, "-").concat(this._clientId.replace(/-/g, ''));
|
|
1067
1068
|
}
|
|
1068
1069
|
}, {
|
|
1069
1070
|
key: "password",
|
|
@@ -1191,9 +1192,14 @@ function FronteggRouter() {
|
|
|
1191
1192
|
var app = useContext(AppContext);
|
|
1192
1193
|
|
|
1193
1194
|
var _useRouter = useRouter(),
|
|
1194
|
-
query = _useRouter.query
|
|
1195
|
+
query = _useRouter.query,
|
|
1196
|
+
replace = _useRouter.replace;
|
|
1195
1197
|
|
|
1196
1198
|
var loginWithRedirect = useLoginWithRedirect();
|
|
1199
|
+
|
|
1200
|
+
var _useLoginActions = useLoginActions(),
|
|
1201
|
+
logout = _useLoginActions.logout;
|
|
1202
|
+
|
|
1197
1203
|
useEffect(function () {
|
|
1198
1204
|
if (!app) {
|
|
1199
1205
|
return;
|
|
@@ -1209,21 +1215,31 @@ function FronteggRouter() {
|
|
|
1209
1215
|
var pathname = "/".concat(pathArr.join('/'));
|
|
1210
1216
|
|
|
1211
1217
|
if (pathname === routesObj.loginUrl) {
|
|
1218
|
+
if (queryParams.redirectUrl) {
|
|
1219
|
+
localStorage.setItem('FRONTEGG_AFTER_AUTH_REDIRECT_URL', "".concat(window.location.origin, "/").concat(queryParams.redirectUrl));
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1212
1222
|
loginWithRedirect();
|
|
1213
|
-
} else {
|
|
1214
|
-
|
|
1223
|
+
} else if (pathname === routesObj.logoutUrl) {
|
|
1224
|
+
var _baseUrl = app.options.contextOptions.baseUrl;
|
|
1225
|
+
var baseUrl = typeof _baseUrl === 'string' ? _baseUrl : _baseUrl('');
|
|
1226
|
+
logout(function () {
|
|
1227
|
+
window.location.href = "".concat(baseUrl, "/oauth/logout?post_logout_redirect_uri=").concat(encodeURIComponent(window.location.origin));
|
|
1228
|
+
});
|
|
1215
1229
|
}
|
|
1216
1230
|
}
|
|
1217
|
-
}, [app, query, loginWithRedirect]);
|
|
1231
|
+
}, [app, query, loginWithRedirect, logout, replace]);
|
|
1218
1232
|
return '';
|
|
1219
1233
|
}
|
|
1220
1234
|
function FronteggRouterProps(context) {
|
|
1235
|
+
var _a;
|
|
1236
|
+
|
|
1221
1237
|
var routesObj = Object.assign(Object.assign({}, authInitialState.routes), fronteggConfig.authRoutes);
|
|
1222
1238
|
var routesArr = Object.keys(routesObj).reduce(function (p, key) {
|
|
1223
1239
|
return [].concat(_toConsumableArray(p), [routesObj[key]]);
|
|
1224
1240
|
}, []);
|
|
1225
1241
|
|
|
1226
|
-
var _parse = parse(context.req.url, true),
|
|
1242
|
+
var _parse = parse((_a = context.resolvedUrl) !== null && _a !== void 0 ? _a : context.req.url, true),
|
|
1227
1243
|
pathname = _parse.pathname;
|
|
1228
1244
|
|
|
1229
1245
|
if (!pathname || pathname.startsWith('/_next/data')) {
|
|
@@ -1234,7 +1250,7 @@ function FronteggRouterProps(context) {
|
|
|
1234
1250
|
var notFound = routesArr.indexOf(pathname) === -1;
|
|
1235
1251
|
|
|
1236
1252
|
if (fronteggConfig.fronteggAppOptions.hostedLoginBox) {
|
|
1237
|
-
var _notFound = !(routesObj.loginUrl === pathname || routesObj.hostedLoginRedirectUrl === pathname);
|
|
1253
|
+
var _notFound = !(routesObj.loginUrl === pathname || routesObj.logoutUrl === pathname || routesObj.hostedLoginRedirectUrl === pathname);
|
|
1238
1254
|
|
|
1239
1255
|
return {
|
|
1240
1256
|
notFound: _notFound,
|
|
@@ -1307,7 +1323,7 @@ function _defineProperty(obj, key, value) {
|
|
|
1307
1323
|
|
|
1308
1324
|
function getSession(req) {
|
|
1309
1325
|
return __awaiter(this, void 0, void 0, /*#__PURE__*/regenerator.mark(function _callee() {
|
|
1310
|
-
var sealFromCookies, jwt, publicKey, _yield$jwtVerify, payload, session;
|
|
1326
|
+
var sealFromCookies, compressedJwt, jwt, publicKey, _yield$jwtVerify, payload, session;
|
|
1311
1327
|
|
|
1312
1328
|
return regenerator.wrap(function _callee$(_context) {
|
|
1313
1329
|
while (1) {
|
|
@@ -1330,16 +1346,21 @@ function getSession(req) {
|
|
|
1330
1346
|
});
|
|
1331
1347
|
|
|
1332
1348
|
case 6:
|
|
1333
|
-
|
|
1349
|
+
compressedJwt = _context.sent;
|
|
1334
1350
|
_context.next = 9;
|
|
1335
|
-
return
|
|
1351
|
+
return uncompress(compressedJwt);
|
|
1336
1352
|
|
|
1337
1353
|
case 9:
|
|
1338
|
-
|
|
1354
|
+
jwt = _context.sent;
|
|
1339
1355
|
_context.next = 12;
|
|
1340
|
-
return
|
|
1356
|
+
return fronteggConfig.getJwtPublicKey();
|
|
1341
1357
|
|
|
1342
1358
|
case 12:
|
|
1359
|
+
publicKey = _context.sent;
|
|
1360
|
+
_context.next = 15;
|
|
1361
|
+
return jwtVerify(jwt, publicKey);
|
|
1362
|
+
|
|
1363
|
+
case 15:
|
|
1343
1364
|
_yield$jwtVerify = _context.sent;
|
|
1344
1365
|
payload = _yield$jwtVerify.payload;
|
|
1345
1366
|
session = {
|
|
@@ -1348,27 +1369,27 @@ function getSession(req) {
|
|
|
1348
1369
|
};
|
|
1349
1370
|
|
|
1350
1371
|
if (!(session.user.exp * 1000 < Date.now())) {
|
|
1351
|
-
_context.next =
|
|
1372
|
+
_context.next = 20;
|
|
1352
1373
|
break;
|
|
1353
1374
|
}
|
|
1354
1375
|
|
|
1355
1376
|
return _context.abrupt("return", undefined);
|
|
1356
1377
|
|
|
1357
|
-
case
|
|
1378
|
+
case 20:
|
|
1358
1379
|
return _context.abrupt("return", session);
|
|
1359
1380
|
|
|
1360
|
-
case
|
|
1361
|
-
_context.prev =
|
|
1381
|
+
case 23:
|
|
1382
|
+
_context.prev = 23;
|
|
1362
1383
|
_context.t0 = _context["catch"](0);
|
|
1363
1384
|
console.error(_context.t0);
|
|
1364
1385
|
return _context.abrupt("return", undefined);
|
|
1365
1386
|
|
|
1366
|
-
case
|
|
1387
|
+
case 27:
|
|
1367
1388
|
case "end":
|
|
1368
1389
|
return _context.stop();
|
|
1369
1390
|
}
|
|
1370
1391
|
}
|
|
1371
|
-
}, _callee, null, [[0,
|
|
1392
|
+
}, _callee, null, [[0, 23]]);
|
|
1372
1393
|
}));
|
|
1373
1394
|
}
|
|
1374
1395
|
function withSSRSession(handler) {
|
|
@@ -1376,7 +1397,7 @@ function withSSRSession(handler) {
|
|
|
1376
1397
|
|
|
1377
1398
|
return function (context) {
|
|
1378
1399
|
return __awaiter(_this, void 0, void 0, /*#__PURE__*/regenerator.mark(function _callee2() {
|
|
1379
|
-
var _a, session;
|
|
1400
|
+
var _a, _b, session, loginUrl;
|
|
1380
1401
|
|
|
1381
1402
|
return regenerator.wrap(function _callee2$(_context2) {
|
|
1382
1403
|
while (1) {
|
|
@@ -1396,15 +1417,21 @@ function withSSRSession(handler) {
|
|
|
1396
1417
|
return _context2.abrupt("return", handler(context, session));
|
|
1397
1418
|
|
|
1398
1419
|
case 7:
|
|
1420
|
+
loginUrl = (_a = fronteggConfig.authRoutes.loginUrl) !== null && _a !== void 0 ? _a : authInitialState.routes.loginUrl;
|
|
1421
|
+
|
|
1422
|
+
if (!loginUrl.startsWith('/')) {
|
|
1423
|
+
loginUrl = "/".concat(loginUrl);
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1399
1426
|
return _context2.abrupt("return", {
|
|
1400
1427
|
redirect: {
|
|
1401
1428
|
permanent: false,
|
|
1402
|
-
destination: "
|
|
1429
|
+
destination: "".concat(loginUrl, "?redirectUrl=").concat(encodeURIComponent((_b = context.resolvedUrl) !== null && _b !== void 0 ? _b : context.req.url))
|
|
1403
1430
|
},
|
|
1404
1431
|
props: {}
|
|
1405
1432
|
});
|
|
1406
1433
|
|
|
1407
|
-
case
|
|
1434
|
+
case 10:
|
|
1408
1435
|
case "end":
|
|
1409
1436
|
return _context2.stop();
|
|
1410
1437
|
}
|
|
@@ -1621,11 +1648,33 @@ function removeCookies(cookieName, isSecured, cookieDomain, res) {
|
|
|
1621
1648
|
|
|
1622
1649
|
res.setHeader('set-cookie', [].concat(_toConsumableArray(existingSetCookie), [cookieValue]));
|
|
1623
1650
|
}
|
|
1651
|
+
function compress(input) {
|
|
1652
|
+
return new Promise(function (resolve, reject) {
|
|
1653
|
+
zlib.brotliCompress(input, function (error, result) {
|
|
1654
|
+
if (error) {
|
|
1655
|
+
reject(error);
|
|
1656
|
+
} else {
|
|
1657
|
+
resolve(result.toString('base64'));
|
|
1658
|
+
}
|
|
1659
|
+
});
|
|
1660
|
+
});
|
|
1661
|
+
}
|
|
1662
|
+
function uncompress(input) {
|
|
1663
|
+
return new Promise(function (resolve, reject) {
|
|
1664
|
+
zlib.brotliDecompress(Buffer.from(input, 'base64'), function (error, result) {
|
|
1665
|
+
if (error) {
|
|
1666
|
+
reject(error);
|
|
1667
|
+
} else {
|
|
1668
|
+
resolve(result.toString('utf-8'));
|
|
1669
|
+
}
|
|
1670
|
+
});
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1624
1673
|
function createSessionFromAccessToken(output) {
|
|
1625
1674
|
var _a;
|
|
1626
1675
|
|
|
1627
1676
|
return __awaiter(this, void 0, void 0, /*#__PURE__*/regenerator.mark(function _callee2() {
|
|
1628
|
-
var data, accessToken, decodedJwt, session;
|
|
1677
|
+
var data, accessToken, decodedJwt, compressedAccessToken, session;
|
|
1629
1678
|
return regenerator.wrap(function _callee2$(_context2) {
|
|
1630
1679
|
while (1) {
|
|
1631
1680
|
switch (_context2.prev = _context2.next) {
|
|
@@ -1636,26 +1685,31 @@ function createSessionFromAccessToken(output) {
|
|
|
1636
1685
|
decodedJwt = decodeJwt(accessToken);
|
|
1637
1686
|
decodedJwt.expiresIn = Math.floor((decodedJwt.exp * 1000 - Date.now()) / 1000);
|
|
1638
1687
|
_context2.next = 7;
|
|
1639
|
-
return
|
|
1688
|
+
return compress(accessToken);
|
|
1689
|
+
|
|
1690
|
+
case 7:
|
|
1691
|
+
compressedAccessToken = _context2.sent;
|
|
1692
|
+
_context2.next = 10;
|
|
1693
|
+
return sealData(compressedAccessToken, {
|
|
1640
1694
|
password: fronteggConfig.passwordsAsMap,
|
|
1641
1695
|
ttl: decodedJwt.exp
|
|
1642
1696
|
});
|
|
1643
1697
|
|
|
1644
|
-
case
|
|
1698
|
+
case 10:
|
|
1645
1699
|
session = _context2.sent;
|
|
1646
1700
|
return _context2.abrupt("return", [session, decodedJwt]);
|
|
1647
1701
|
|
|
1648
|
-
case
|
|
1649
|
-
_context2.prev =
|
|
1702
|
+
case 14:
|
|
1703
|
+
_context2.prev = 14;
|
|
1650
1704
|
_context2.t0 = _context2["catch"](0);
|
|
1651
1705
|
return _context2.abrupt("return", []);
|
|
1652
1706
|
|
|
1653
|
-
case
|
|
1707
|
+
case 17:
|
|
1654
1708
|
case "end":
|
|
1655
1709
|
return _context2.stop();
|
|
1656
1710
|
}
|
|
1657
1711
|
}
|
|
1658
|
-
}, _callee2, null, [[0,
|
|
1712
|
+
}, _callee2, null, [[0, 14]]);
|
|
1659
1713
|
}));
|
|
1660
1714
|
}
|
|
1661
1715
|
var modifySetCookieIfUnsecure = function modifySetCookieIfUnsecure(setCookieValue, isSecured) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontegg/nextjs",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.0-alpha.2630278530",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"@frontegg/admin-portal": "5.
|
|
6
|
-
"@frontegg/react-hooks": "5.
|
|
5
|
+
"@frontegg/admin-portal": "5.64.1",
|
|
6
|
+
"@frontegg/react-hooks": "5.64.1",
|
|
7
7
|
"jose": "^4.8.0",
|
|
8
8
|
"iron-session": "^6.1.2",
|
|
9
9
|
"http-proxy": "^1.18.1",
|
|
@@ -16,4 +16,4 @@
|
|
|
16
16
|
"main": "./index.cjs.js",
|
|
17
17
|
"module": "./index.esm.js",
|
|
18
18
|
"typings": "./index.d.ts"
|
|
19
|
-
}
|
|
19
|
+
}
|
package/withFronteggApp.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { AppContextType, AppPropsType, NextComponentType } from 'next/dist/shared/lib/utils';
|
|
1
|
+
import type { AppProps, AppInitialProps } from 'next/app';
|
|
2
|
+
import type { AppType, AppContextType, AppPropsType, NextComponentType } from 'next/dist/shared/lib/utils';
|
|
3
3
|
import { FronteggNextJSSession } from './types';
|
|
4
4
|
import { FronteggAppOptions } from '@frontegg/types';
|
|
5
|
-
export declare const withFronteggApp: (app:
|
|
5
|
+
export declare const withFronteggApp: (app: ((props: AppProps) => JSX.Element) & {
|
|
6
|
+
getInitialProps?: AppType['getInitialProps'];
|
|
7
|
+
}, options?: (Omit<FronteggAppOptions, "contextOptions"> & {
|
|
6
8
|
contextOptions?: import("@frontegg/types/ContextOptions").ContextOptions | undefined;
|
|
7
9
|
}) | undefined) => NextComponentType<AppContextType & {
|
|
8
10
|
session: FronteggNextJSSession | null;
|