@descope/nextjs-sdk 0.0.0-alpha.1
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/LICENSE +21 -0
- package/README.md +493 -0
- package/dist/cjs/client/index.js +52 -0
- package/dist/cjs/client/index.js.map +1 -0
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/server/authMiddleware.js +97 -0
- package/dist/cjs/server/authMiddleware.js.map +1 -0
- package/dist/cjs/server/constants.js +16 -0
- package/dist/cjs/server/constants.js.map +1 -0
- package/dist/cjs/server/index.js +13 -0
- package/dist/cjs/server/index.js.map +1 -0
- package/dist/cjs/server/logger.js +28 -0
- package/dist/cjs/server/logger.js.map +1 -0
- package/dist/cjs/server/sdk.js +29 -0
- package/dist/cjs/server/sdk.js.map +1 -0
- package/dist/cjs/server/session.js +62 -0
- package/dist/cjs/server/session.js.map +1 -0
- package/dist/cjs/server/utils.js +24 -0
- package/dist/cjs/server/utils.js.map +1 -0
- package/dist/cjs/shared/AuthProvider.js +15 -0
- package/dist/cjs/shared/AuthProvider.js.map +1 -0
- package/dist/cjs/shared/DescopeFlows.js +50 -0
- package/dist/cjs/shared/DescopeFlows.js.map +1 -0
- package/dist/cjs/shared/DescopeWidgets.js +27 -0
- package/dist/cjs/shared/DescopeWidgets.js.map +1 -0
- package/dist/cjs/shared/constants.js +10 -0
- package/dist/cjs/shared/constants.js.map +1 -0
- package/dist/client/dts/src/client/index.d.ts +12 -0
- package/dist/client/dts/src/index.d.ts +1 -0
- package/dist/client/dts/src/server/authMiddleware.d.ts +12 -0
- package/dist/client/dts/src/server/constants.d.ts +9 -0
- package/dist/client/dts/src/server/index.d.ts +3 -0
- package/dist/client/dts/src/server/sdk.d.ts +10 -0
- package/dist/client/dts/src/server/session.d.ts +6 -0
- package/dist/client/dts/src/server/utils.d.ts +1 -0
- package/dist/client/dts/src/shared/AuthProvider.d.ts +3 -0
- package/dist/client/dts/src/shared/DescopeFlows.d.ts +130 -0
- package/dist/client/dts/src/shared/DescopeWidgets.d.ts +72 -0
- package/dist/client/dts/src/shared/constants.d.ts +4 -0
- package/dist/client/dts/src/shared/index.d.ts +3 -0
- package/dist/client/dts/src/types.d.ts +1 -0
- package/dist/client/index.d.ts +12 -0
- package/dist/client/index.js +14 -0
- package/dist/client/index.js.map +1 -0
- package/dist/dts/src/client/index.d.ts +12 -0
- package/dist/dts/src/index.d.ts +1 -0
- package/dist/dts/src/server/authMiddleware.d.ts +12 -0
- package/dist/dts/src/server/constants.d.ts +9 -0
- package/dist/dts/src/server/index.d.ts +3 -0
- package/dist/dts/src/server/sdk.d.ts +10 -0
- package/dist/dts/src/server/session.d.ts +6 -0
- package/dist/dts/src/server/utils.d.ts +1 -0
- package/dist/dts/src/shared/AuthProvider.d.ts +3 -0
- package/dist/dts/src/shared/DescopeFlows.d.ts +130 -0
- package/dist/dts/src/shared/DescopeWidgets.d.ts +72 -0
- package/dist/dts/src/shared/constants.d.ts +4 -0
- package/dist/dts/src/shared/index.d.ts +3 -0
- package/dist/dts/src/types.d.ts +1 -0
- package/dist/esm/client/index.js +3 -0
- package/dist/esm/client/index.js.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/server/authMiddleware.js +95 -0
- package/dist/esm/server/authMiddleware.js.map +1 -0
- package/dist/esm/server/constants.js +12 -0
- package/dist/esm/server/constants.js.map +1 -0
- package/dist/esm/server/index.js +4 -0
- package/dist/esm/server/index.js.map +1 -0
- package/dist/esm/server/logger.js +25 -0
- package/dist/esm/server/logger.js.map +1 -0
- package/dist/esm/server/sdk.js +26 -0
- package/dist/esm/server/sdk.js.map +1 -0
- package/dist/esm/server/session.js +59 -0
- package/dist/esm/server/session.js.map +1 -0
- package/dist/esm/server/utils.js +22 -0
- package/dist/esm/server/utils.js.map +1 -0
- package/dist/esm/shared/AuthProvider.js +13 -0
- package/dist/esm/shared/AuthProvider.js.map +1 -0
- package/dist/esm/shared/DescopeFlows.js +45 -0
- package/dist/esm/shared/DescopeFlows.js.map +1 -0
- package/dist/esm/shared/DescopeWidgets.js +20 -0
- package/dist/esm/shared/DescopeWidgets.js.map +1 -0
- package/dist/esm/shared/constants.js +8 -0
- package/dist/esm/shared/constants.js.map +1 -0
- package/dist/index.d.ts +212 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/server/authMiddleware.js +98 -0
- package/dist/server/authMiddleware.js.map +1 -0
- package/dist/server/constants.js +12 -0
- package/dist/server/constants.js.map +1 -0
- package/dist/server/dts/src/client/index.d.ts +12 -0
- package/dist/server/dts/src/index.d.ts +1 -0
- package/dist/server/dts/src/server/authMiddleware.d.ts +12 -0
- package/dist/server/dts/src/server/constants.d.ts +9 -0
- package/dist/server/dts/src/server/index.d.ts +3 -0
- package/dist/server/dts/src/server/sdk.d.ts +10 -0
- package/dist/server/dts/src/server/session.d.ts +6 -0
- package/dist/server/dts/src/server/utils.d.ts +1 -0
- package/dist/server/dts/src/shared/AuthProvider.d.ts +3 -0
- package/dist/server/dts/src/shared/DescopeFlows.d.ts +130 -0
- package/dist/server/dts/src/shared/DescopeWidgets.d.ts +72 -0
- package/dist/server/dts/src/shared/constants.d.ts +4 -0
- package/dist/server/dts/src/shared/index.d.ts +3 -0
- package/dist/server/dts/src/types.d.ts +1 -0
- package/dist/server/index.d.ts +32 -0
- package/dist/server/index.js +4 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/sdk.js +27 -0
- package/dist/server/sdk.js.map +1 -0
- package/dist/server/session.js +32 -0
- package/dist/server/session.js.map +1 -0
- package/dist/server/utils.js +22 -0
- package/dist/server/utils.js.map +1 -0
- package/dist/shared/AuthProvider.js +19 -0
- package/dist/shared/AuthProvider.js.map +1 -0
- package/dist/shared/DescopeFlows.js +53 -0
- package/dist/shared/DescopeFlows.js.map +1 -0
- package/dist/shared/DescopeWidgets.js +35 -0
- package/dist/shared/DescopeWidgets.js.map +1 -0
- package/dist/shared/constants.js +8 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/types/client/index.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/server/authMiddleware.d.ts +12 -0
- package/dist/types/server/constants.d.ts +9 -0
- package/dist/types/server/index.d.ts +3 -0
- package/dist/types/server/logger.d.ts +25 -0
- package/dist/types/server/sdk.d.ts +9 -0
- package/dist/types/server/session.d.ts +10 -0
- package/dist/types/server/utils.d.ts +1 -0
- package/dist/types/shared/AuthProvider.d.ts +3 -0
- package/dist/types/shared/DescopeFlows.d.ts +141 -0
- package/dist/types/shared/DescopeWidgets.d.ts +54 -0
- package/dist/types/shared/constants.d.ts +4 -0
- package/dist/types/shared/index.d.ts +3 -0
- package/dist/types/types.d.ts +1 -0
- package/package.json +152 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Descope <help@descope.com>
|
|
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
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
# Descope SDK for Next.js
|
|
2
|
+
|
|
3
|
+
The Descope SDK for Next.js provides convenient access to the Descope for an application written on top of Next.js. You can read more on the [Descope Website](https://descope.com).
|
|
4
|
+
|
|
5
|
+
This SDK uses under the hood the Descope React SDK and Descope Node SDK
|
|
6
|
+
Refer to the [Descope React SDK](https://github.com/descope/descope-js/tree/main/packages/sdks/react-sdk) and [Descope Node SDK](https://github.com/descope/node-sdk) for more details.
|
|
7
|
+
|
|
8
|
+
## Requirements
|
|
9
|
+
|
|
10
|
+
- The SDK supports Next.js version 13 and above.
|
|
11
|
+
- A Descope `Project ID` is required for using the SDK. Find it on the [project page in the Descope Console](https://app.descope.com/settings/project).
|
|
12
|
+
|
|
13
|
+
## Installing the SDK
|
|
14
|
+
|
|
15
|
+
Install the package with:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm i --save @descope/nextjs-sdk
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
This section contains guides for App router and Pages router.
|
|
24
|
+
For Pages router, see the [Pages Router](#pages-router) section.
|
|
25
|
+
|
|
26
|
+
### App Router
|
|
27
|
+
|
|
28
|
+
#### Wrap your app layout with Auth Provider
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
// src/app/layout.tsx
|
|
32
|
+
|
|
33
|
+
import { AuthProvider } from '@descope/nextjs-sdk';
|
|
34
|
+
|
|
35
|
+
export default function RootLayout({
|
|
36
|
+
children
|
|
37
|
+
}: {
|
|
38
|
+
children: React.ReactNode
|
|
39
|
+
}) {
|
|
40
|
+
return (
|
|
41
|
+
<AuthProvider projectId="your-descope-project-id">
|
|
42
|
+
<html lang="en">
|
|
43
|
+
<body>{children}</body>
|
|
44
|
+
</html>
|
|
45
|
+
</AuthProvider>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Note: `AuthProvider` uses `sessionTokenViaCookie={true}` by default, in order that the [AuthMiddleware](<#Require-authentication-for-application-(Middleware)>) will work out of the box.
|
|
51
|
+
The session token cookie is set to [`SameSite=Strict; Secure;`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) by default.
|
|
52
|
+
If you need to customize this, you can set `sessionTokenViaCookie={sameSite: 'Lax', secure: false}` (if you pass only `sameSite`, `secure` will be set to `true` by default).
|
|
53
|
+
|
|
54
|
+
#### Use Descope to render Flow
|
|
55
|
+
|
|
56
|
+
You can use **default flows** or **provide flow id** directly to the Descope component
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
// Login page, e.g. src/app/sign-in.tsx
|
|
60
|
+
import { Descope } from '@descope/nextjs-sdk';
|
|
61
|
+
// you can choose flow to run from the following without `flowId` instead
|
|
62
|
+
// import { SignInFlow, SignUpFlow, SignUpOrInFlow } from '@descope/nextjs-sdk'
|
|
63
|
+
|
|
64
|
+
const Page = () => {
|
|
65
|
+
return (
|
|
66
|
+
<Descope
|
|
67
|
+
flowId="sign-up-or-in"
|
|
68
|
+
onSuccess={(e) => console.log('Logged in!')}
|
|
69
|
+
onError={(e) => console.log('Could not logged in!')}
|
|
70
|
+
redirectAfterSuccess="/"
|
|
71
|
+
// redirectAfterError="/error-page"
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Refer to the [Descope React SDK Section](../react-sdk/README.md) for a list of available props.
|
|
78
|
+
|
|
79
|
+
**Note:** Descope is a client component. if the component that renders it is a server component, you cannot pass `onSuccess`/`onError`/`errorTransformer`/`logger` props because they are not serializable. To redirect the user after the flow is completed, use the `redirectAfterSuccess` and `redirectAfterError` props.
|
|
80
|
+
|
|
81
|
+
#### Client Side Usage
|
|
82
|
+
|
|
83
|
+
Use the `useDescope`, `useSession` and `useUser` hooks in your components in order to get authentication state, user details and utilities
|
|
84
|
+
|
|
85
|
+
This can be helpful to implement application-specific logic. Examples:
|
|
86
|
+
|
|
87
|
+
- Render different components if current session is authenticated
|
|
88
|
+
- Render user's content
|
|
89
|
+
- Logout button
|
|
90
|
+
|
|
91
|
+
Note: these hooks should be used in a client component only (For example, component with `use client` notation).
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
'use client';
|
|
95
|
+
import { useDescope, useSession, useUser } from '@descope/nextjs-sdk/client';
|
|
96
|
+
import { useCallback } from 'react';
|
|
97
|
+
|
|
98
|
+
const App = () => {
|
|
99
|
+
// NOTE - `useDescope`, `useSession`, `useUser` should be used inside `AuthProvider` context,
|
|
100
|
+
// and will throw an exception if this requirement is not met
|
|
101
|
+
// useSession retrieves authentication state, session loading status, and session token
|
|
102
|
+
const { isAuthenticated, isSessionLoading, sessionToken } = useSession();
|
|
103
|
+
// useUser retrieves the logged in user information
|
|
104
|
+
const { user } = useUser();
|
|
105
|
+
// useDescope retrieves Descope SDK for further operations related to authentication
|
|
106
|
+
// such as logout
|
|
107
|
+
const sdk = useDescope();
|
|
108
|
+
|
|
109
|
+
if (isSessionLoading || isUserLoading) {
|
|
110
|
+
return <p>Loading...</p>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const handleLogout = useCallback(() => {
|
|
114
|
+
sdk.logout();
|
|
115
|
+
}, [sdk]);
|
|
116
|
+
|
|
117
|
+
if (isAuthenticated) {
|
|
118
|
+
return (
|
|
119
|
+
<>
|
|
120
|
+
<p>Hello {user.name}</p>
|
|
121
|
+
<button onClick={handleLogout}>Logout</button>
|
|
122
|
+
</>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return <p>You are not logged in</p>;
|
|
127
|
+
};
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### Server Side Usage
|
|
131
|
+
|
|
132
|
+
##### Require authentication for application (Middleware)
|
|
133
|
+
|
|
134
|
+
You can use Next.js Middleware to require authentication for a page/route or a group of pages/routes.
|
|
135
|
+
|
|
136
|
+
Descope SDK provides a middleware function that can be used to require authentication for a page/route or a group of pages/routes.
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
// src/middleware.ts
|
|
140
|
+
import { authMiddleware } from '@descope/nextjs-sdk/server'
|
|
141
|
+
|
|
142
|
+
export default authMiddleware({
|
|
143
|
+
// The Descope project ID to use for authentication
|
|
144
|
+
// Defaults to process.env.DESCOPE_PROJECT_ID
|
|
145
|
+
projectId: 'your-descope-project-id',
|
|
146
|
+
|
|
147
|
+
// The URL to redirect to if the user is not authenticated
|
|
148
|
+
// Defaults to process.env.SIGN_IN_ROUTE or '/sign-in' if not provided
|
|
149
|
+
// NOTE: In case it contains query parameters that exist in the original URL, they will override the original query parameters. e.g. if the original URL is /page?param1=1¶m2=2 and the redirect URL is /sign-in?param1=3, the final redirect URL will be /sign-in?param1=3¶m2=2
|
|
150
|
+
redirectUrl?: string,
|
|
151
|
+
|
|
152
|
+
// These are the public and private routes in your app. You can also use wildcards (e.g. /api/*) with routes as well in these definitions.
|
|
153
|
+
// Read more about how to use these below.
|
|
154
|
+
publicRoutes?: string[],
|
|
155
|
+
privateRoutes?: string[]
|
|
156
|
+
// If you having privateRoutes and publicRoutes defined at the same time, privateRoutes will be ignored.
|
|
157
|
+
|
|
158
|
+
// Optional: log level for the middleware
|
|
159
|
+
// Defaults to 'info'
|
|
160
|
+
// logLevel: 'debug' | 'info' | 'warn' | 'error'
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
export const config = {
|
|
164
|
+
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)']
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
##### Public and Private Route Definitions
|
|
169
|
+
|
|
170
|
+
- **All routes are private by default.**
|
|
171
|
+
- **`publicRoutes`:** Use this to specify which routes do not require authentication. If specified, only these routes and the default public routes will be public.
|
|
172
|
+
- **`privateRoutes`:** Use this to specify which routes require authentication. If specified, only these routes will be private, and all other routes will be public.
|
|
173
|
+
- **Conflict Handling:** If both `publicRoutes` and `privateRoutes` are provided, `privateRoutes` will be ignored, and a warning will be logged.
|
|
174
|
+
|
|
175
|
+
This setup ensures that you can clearly define which routes in your application require authentication and which do not, while providing a mechanism to handle potential misconfigurations gracefully.
|
|
176
|
+
|
|
177
|
+
###### Public Routes
|
|
178
|
+
|
|
179
|
+
- **Description:** An array of public routes that do not require authentication.
|
|
180
|
+
- **Configuration:** Use `publicRoutes` to specify routes that don't require authentication.
|
|
181
|
+
- **Additional Defaults:** In addition to the routes you specify, the following default public routes are included:
|
|
182
|
+
- `process.env.SIGN_IN_ROUTE` or `/sign-in` if not provided
|
|
183
|
+
- `process.env.SIGN_UP_ROUTE` or `/sign-up` if not provided
|
|
184
|
+
- **Example:**
|
|
185
|
+
```typescript
|
|
186
|
+
const options = {
|
|
187
|
+
publicRoutes: ['/home', '/about']
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
###### Private Routes
|
|
192
|
+
|
|
193
|
+
- **Description:** An array of private routes that require authentication.
|
|
194
|
+
- **Configuration:** Use `privateRoutes` to specify routes that require authentication. All other routes will be considered public.
|
|
195
|
+
- **Conflict Handling:** If both `publicRoutes` and `privateRoutes` are defined at the same time, `privateRoutes` will be ignored, and a warning will be logged.
|
|
196
|
+
- **Example:**
|
|
197
|
+
```typescript
|
|
198
|
+
const options = {
|
|
199
|
+
privateRoutes: ['/dashboard', '/profile']
|
|
200
|
+
};
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
##### Read session information in server side
|
|
204
|
+
|
|
205
|
+
use the `session()` helper to read session information in Server Components and Route handlers.
|
|
206
|
+
|
|
207
|
+
Note: While using `authMiddleware` is still recommended for session management (because it validates the session only once), `session()` can function without it. If `authMiddleware` does not set a session, `session()` will attempt to retrieve the session token from cookies, then parse and validate it.
|
|
208
|
+
|
|
209
|
+
Server Component:
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
// src/app/page.tsx
|
|
213
|
+
|
|
214
|
+
import { session } from '@descope/nextjs-sdk/server';
|
|
215
|
+
|
|
216
|
+
async function Page() {
|
|
217
|
+
const sessionRes = await session();
|
|
218
|
+
if (!sessionRes) {
|
|
219
|
+
// ...
|
|
220
|
+
}
|
|
221
|
+
// Use the session jwt or parsed token
|
|
222
|
+
const { jwt, token } = sessionRes;
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Route handler:
|
|
227
|
+
|
|
228
|
+
```js
|
|
229
|
+
// src/pages/api/routes.ts
|
|
230
|
+
export async function GET() {
|
|
231
|
+
const currSession = await session();
|
|
232
|
+
if (!currSession) {
|
|
233
|
+
// ...
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Use the session jwt or parsed token
|
|
237
|
+
const { jwt, token } = currSession;
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
The `session()` function uses Next.js's `cookies()` and `headers()` functions to retrieve the session token. If you are using Next.js Version 13, you can use the `getSession(req)` instead.
|
|
242
|
+
|
|
243
|
+
```js
|
|
244
|
+
import { getSession } from '@descope/nextjs-sdk/server';
|
|
245
|
+
|
|
246
|
+
export async function GET(req) {
|
|
247
|
+
const currSession = await getSession(req);
|
|
248
|
+
|
|
249
|
+
// ...
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
##### Optional Parameters
|
|
254
|
+
|
|
255
|
+
If the middleware did not set a session, The `session()` function will attempt to retrieve the session token from cookies and validates it, this requires the project ID to be either set in the environment variables or passed as a parameter to the function.
|
|
256
|
+
You can also pass the log level to the function (defaults to 'info').
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
session({
|
|
260
|
+
projectId?: string;
|
|
261
|
+
baseUrl?: string;
|
|
262
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error'
|
|
263
|
+
})
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
- **projectId:** The Descope Project ID. If not provided, the function will fall back to `DESCOPE_PROJECT_ID` from the environment variables.
|
|
267
|
+
- **baseUrl:** The Descope API base URL.
|
|
268
|
+
|
|
269
|
+
This allows developers to use `session()` even if the project ID is not set in the environment.
|
|
270
|
+
|
|
271
|
+
#### Access Descope SDK in server side
|
|
272
|
+
|
|
273
|
+
Use `createSdk` function to create Descope SDK in server side.
|
|
274
|
+
|
|
275
|
+
Refer to the [Descope Node SDK](https://github.com/descope/node-sdk/?tab=readme-ov-file#authentication-functions) for a list of available functions.
|
|
276
|
+
|
|
277
|
+
Usage example in Route handler:
|
|
278
|
+
|
|
279
|
+
```js
|
|
280
|
+
// src/pages/api/routes.ts
|
|
281
|
+
import { createSdk } from '@descope/nextjs-sdk/server';
|
|
282
|
+
|
|
283
|
+
const sdk = createSdk({
|
|
284
|
+
// The Descope project ID to use for authentication
|
|
285
|
+
// Defaults to process.env.DESCOPE_PROJECT_ID
|
|
286
|
+
projectId: 'your-descope-project-id',
|
|
287
|
+
|
|
288
|
+
// The Descope management key to use for management operations
|
|
289
|
+
// Defaults to process.env.DESCOPE_MANAGEMENT_KEY
|
|
290
|
+
managementKey: 'your-descope-management-key'
|
|
291
|
+
|
|
292
|
+
// Optional: Descope API base URL
|
|
293
|
+
// Defaults to process.env.DESCOPE_BASE_URL
|
|
294
|
+
// baseUrl: 'https://...'
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
export async function GET(req) {
|
|
298
|
+
const { searchParams } = new URL(req.url);
|
|
299
|
+
const loginId = searchParams.get('loginId');
|
|
300
|
+
|
|
301
|
+
const { ok, data: user } = await sdk.management.user.load(loginId);
|
|
302
|
+
if (!ok) {
|
|
303
|
+
// ...
|
|
304
|
+
}
|
|
305
|
+
// Use the user data ...
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Pages Router
|
|
310
|
+
|
|
311
|
+
This section is Working in progress :-)
|
|
312
|
+
In the meantime, you can see the example in the [Pages Router](./examples/pages-router/) folder.
|
|
313
|
+
|
|
314
|
+
### Widgets
|
|
315
|
+
|
|
316
|
+
Widgets are components that allow you to expose management features for tenant-based implementation. In certain scenarios, your customers may require the capability to perform managerial actions independently, alleviating the necessity to contact you. Widgets serve as a feature enabling you to delegate these capabilities to your customers in a modular manner.
|
|
317
|
+
|
|
318
|
+
Important Note:
|
|
319
|
+
|
|
320
|
+
- For the user to be able to use the widget, they need to be assigned the `Tenant Admin` Role.
|
|
321
|
+
|
|
322
|
+
#### User Management
|
|
323
|
+
|
|
324
|
+
The `UserManagement` widget will let you embed a user table in your site to view and take action.
|
|
325
|
+
|
|
326
|
+
The widget lets you:
|
|
327
|
+
|
|
328
|
+
- Create a new user
|
|
329
|
+
- Edit an existing user
|
|
330
|
+
- Activate / disable an existing user
|
|
331
|
+
- Reset an existing user's password
|
|
332
|
+
- Remove an existing user's passkey
|
|
333
|
+
- Delete an existing user
|
|
334
|
+
|
|
335
|
+
Note:
|
|
336
|
+
|
|
337
|
+
- Custom fields also appear in the table.
|
|
338
|
+
|
|
339
|
+
###### Usage
|
|
340
|
+
|
|
341
|
+
```js
|
|
342
|
+
import { UserManagement } from '@descope/nextjs-sdk';
|
|
343
|
+
...
|
|
344
|
+
<UserManagement
|
|
345
|
+
widgetId="user-management-widget"
|
|
346
|
+
tenant="tenant-id"
|
|
347
|
+
/>
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Example:
|
|
351
|
+
[Manage Users](./examples/app-router/app/manage-users/page.tsx)
|
|
352
|
+
|
|
353
|
+
#### Role Management
|
|
354
|
+
|
|
355
|
+
The `RoleManagement` widget will let you embed a role table in your site to view and take action.
|
|
356
|
+
|
|
357
|
+
The widget lets you:
|
|
358
|
+
|
|
359
|
+
- Create a new role
|
|
360
|
+
- Change an existing role's fields
|
|
361
|
+
- Delete an existing role
|
|
362
|
+
|
|
363
|
+
Note:
|
|
364
|
+
|
|
365
|
+
- The `Editable` field is determined by the user's access to the role - meaning that project-level roles are not editable by tenant level users.
|
|
366
|
+
- You need to pre-define the permissions that the user can use, which are not editable in the widget.
|
|
367
|
+
|
|
368
|
+
###### Usage
|
|
369
|
+
|
|
370
|
+
```js
|
|
371
|
+
import { RoleManagement } from '@descope/nextjs-sdk';
|
|
372
|
+
...
|
|
373
|
+
<RoleManagement
|
|
374
|
+
widgetId="role-management-widget"
|
|
375
|
+
tenant="tenant-id"
|
|
376
|
+
/>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Example:
|
|
380
|
+
[Manage Roles](./examples/app-router/app/manage-roles/page.tsx)
|
|
381
|
+
|
|
382
|
+
#### Access Key Management
|
|
383
|
+
|
|
384
|
+
The `AccessKeyManagement` widget will let you embed an access key table in your site to view and take action.
|
|
385
|
+
|
|
386
|
+
The widget lets you:
|
|
387
|
+
|
|
388
|
+
- Create a new access key
|
|
389
|
+
- Activate / deactivate an existing access key
|
|
390
|
+
- Delete an exising access key
|
|
391
|
+
|
|
392
|
+
###### Usage
|
|
393
|
+
|
|
394
|
+
```js
|
|
395
|
+
import { AccessKeyManagement } from '@descope/nextjs-sdk';
|
|
396
|
+
{
|
|
397
|
+
/* admin view: manage all tenant users' access keys */
|
|
398
|
+
}
|
|
399
|
+
<AccessKeyManagement
|
|
400
|
+
widgetId="access-key-management-widget"
|
|
401
|
+
tenant="tenant-id"
|
|
402
|
+
/>;
|
|
403
|
+
|
|
404
|
+
{
|
|
405
|
+
/* user view: mange access key for the logged-in tenant's user */
|
|
406
|
+
}
|
|
407
|
+
<AccessKeyManagement
|
|
408
|
+
widgetId="user-access-key-management-widget"
|
|
409
|
+
tenant="tenant-id"
|
|
410
|
+
/>;
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Example:
|
|
414
|
+
[Manage Access Keys](./examples/app-router/app/manage-access-keys/page.tsx)
|
|
415
|
+
|
|
416
|
+
#### Audit Management
|
|
417
|
+
|
|
418
|
+
The `AuditManagement` widget will let you embed an audit table in your site.
|
|
419
|
+
|
|
420
|
+
###### Usage
|
|
421
|
+
|
|
422
|
+
```js
|
|
423
|
+
import { AuditManagement } from '@descope/nextjs-sdk';
|
|
424
|
+
...
|
|
425
|
+
<AuditManagement
|
|
426
|
+
widgetId="audit-management-widget"
|
|
427
|
+
tenant="tenant-id"
|
|
428
|
+
/>
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Example:
|
|
432
|
+
[Manage Audit](./examples/app-router/app/manage-audit/page.tsx)
|
|
433
|
+
|
|
434
|
+
#### User Profile
|
|
435
|
+
|
|
436
|
+
The `UserProfile` widget lets you embed a user profile component in your app and let the logged in user update his profile.
|
|
437
|
+
|
|
438
|
+
The widget lets you:
|
|
439
|
+
|
|
440
|
+
- Update user profile picture
|
|
441
|
+
- Update user personal information
|
|
442
|
+
- Update authentication methods
|
|
443
|
+
- Logout
|
|
444
|
+
|
|
445
|
+
###### Usage
|
|
446
|
+
|
|
447
|
+
```js
|
|
448
|
+
import { UserProfile } from '@descope/nextjs-sdk';
|
|
449
|
+
...
|
|
450
|
+
<UserProfile
|
|
451
|
+
widgetId="user-profile-widget"
|
|
452
|
+
onLogout={() => {
|
|
453
|
+
// add here you own logout callback
|
|
454
|
+
window.location.href = '/login';
|
|
455
|
+
}}
|
|
456
|
+
/>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Example:
|
|
460
|
+
[User Profile](./examples/app-router/app/my-user-profile/page.tsx)
|
|
461
|
+
|
|
462
|
+
#### Applications Portal
|
|
463
|
+
|
|
464
|
+
The `ApplicationsPortal` lets you embed an applications portal component in your app and allows the logged-in user to open applications they are assigned to.
|
|
465
|
+
|
|
466
|
+
###### Usage
|
|
467
|
+
|
|
468
|
+
```js
|
|
469
|
+
import { ApplicationsPortal } from '@descope/nextjs-sdk';
|
|
470
|
+
...
|
|
471
|
+
<ApplicationsPortal
|
|
472
|
+
widgetId="applications-portal-widget"
|
|
473
|
+
/>
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Example:
|
|
477
|
+
[User Profile](./examples/app-router/app/my-applications-portal/page.tsx)
|
|
478
|
+
|
|
479
|
+
## Code Example
|
|
480
|
+
|
|
481
|
+
You can find an example react app in the [examples folder](./examples). - [App Router](./examples/app-router/) - [Pages Router](./examples/pages-router/)
|
|
482
|
+
|
|
483
|
+
## Learn More
|
|
484
|
+
|
|
485
|
+
To learn more please see the [Descope Documentation and API reference page](https://docs.descope.com/).
|
|
486
|
+
|
|
487
|
+
## Contact Us
|
|
488
|
+
|
|
489
|
+
If you need help you can email [Descope Support](mailto:support@descope.com)
|
|
490
|
+
|
|
491
|
+
## License
|
|
492
|
+
|
|
493
|
+
The Descope SDK for React is licensed for use under the terms and conditions of the [MIT license Agreement](./LICENSE).
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var reactSdk = require('@descope/react-sdk');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "getCurrentTenant", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return reactSdk.getCurrentTenant; }
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "getJwtPermissions", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return reactSdk.getJwtPermissions; }
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(exports, "getJwtRoles", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return reactSdk.getJwtRoles; }
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(exports, "getRefreshToken", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return reactSdk.getRefreshToken; }
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "getSessionToken", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return reactSdk.getSessionToken; }
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports, "isRefreshTokenExpired", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
get: function () { return reactSdk.isRefreshTokenExpired; }
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(exports, "isSessionTokenExpired", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () { return reactSdk.isSessionTokenExpired; }
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "refresh", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () { return reactSdk.refresh; }
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(exports, "useDescope", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function () { return reactSdk.useDescope; }
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(exports, "useSession", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function () { return reactSdk.useSession; }
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "useUser", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return reactSdk.useUser; }
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var AuthProvider = require('./shared/AuthProvider.js');
|
|
4
|
+
var DescopeFlows = require('./shared/DescopeFlows.js');
|
|
5
|
+
var DescopeWidgets = require('./shared/DescopeWidgets.js');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports.AuthProvider = AuthProvider;
|
|
10
|
+
exports.Descope = DescopeFlows.Descope;
|
|
11
|
+
exports.SignInFlow = DescopeFlows.SignInFlow;
|
|
12
|
+
exports.SignUpFlow = DescopeFlows.SignUpFlow;
|
|
13
|
+
exports.SignUpOrInFlow = DescopeFlows.SignUpOrInFlow;
|
|
14
|
+
exports.AccessKeyManagement = DescopeWidgets.AccessKeyManagement;
|
|
15
|
+
exports.ApplicationsPortal = DescopeWidgets.ApplicationsPortal;
|
|
16
|
+
exports.AuditManagement = DescopeWidgets.AuditManagement;
|
|
17
|
+
exports.RoleManagement = DescopeWidgets.RoleManagement;
|
|
18
|
+
exports.UserManagement = DescopeWidgets.UserManagement;
|
|
19
|
+
exports.UserProfile = DescopeWidgets.UserProfile;
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var server_js = require('next/server.js');
|
|
4
|
+
var descopeSdk = require('@descope/node-sdk');
|
|
5
|
+
var constants = require('./constants.js');
|
|
6
|
+
var sdk = require('./sdk.js');
|
|
7
|
+
var utils = require('./utils.js');
|
|
8
|
+
var logger = require('./logger.js');
|
|
9
|
+
|
|
10
|
+
const getSessionJwt = (req) => {
|
|
11
|
+
let jwt = req.headers?.get('Authorization')?.split(' ')[1];
|
|
12
|
+
if (jwt) {
|
|
13
|
+
return jwt;
|
|
14
|
+
}
|
|
15
|
+
jwt = req.cookies?.get(descopeSdk.SessionTokenCookieName)?.value;
|
|
16
|
+
if (jwt) {
|
|
17
|
+
return jwt;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
};
|
|
21
|
+
const matchWildcardRoute = (route, path) => {
|
|
22
|
+
let regexPattern = route.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
23
|
+
// Convert wildcard (*) to match path segments only
|
|
24
|
+
regexPattern = regexPattern.replace(/\*/g, '[^/]*');
|
|
25
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
26
|
+
return regex.test(path);
|
|
27
|
+
};
|
|
28
|
+
const isPublicRoute = (req, options) => {
|
|
29
|
+
// Ensure publicRoutes and privateRoutes are arrays, defaulting to empty arrays if not defined
|
|
30
|
+
const { publicRoutes = [], privateRoutes = [] } = options;
|
|
31
|
+
const { pathname } = req.nextUrl;
|
|
32
|
+
const isDefaultPublicRoute = Object.values(constants.DEFAULT_PUBLIC_ROUTES).includes(pathname);
|
|
33
|
+
if (publicRoutes.length > 0) {
|
|
34
|
+
if (privateRoutes.length > 0) {
|
|
35
|
+
logger.logger.warn('Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.');
|
|
36
|
+
}
|
|
37
|
+
return (isDefaultPublicRoute ||
|
|
38
|
+
publicRoutes.some((route) => matchWildcardRoute(route, pathname)));
|
|
39
|
+
}
|
|
40
|
+
if (privateRoutes.length > 0) {
|
|
41
|
+
return (isDefaultPublicRoute ||
|
|
42
|
+
!privateRoutes.some((route) => matchWildcardRoute(route, pathname)));
|
|
43
|
+
}
|
|
44
|
+
// If no routes are provided, all routes are private
|
|
45
|
+
return isDefaultPublicRoute;
|
|
46
|
+
};
|
|
47
|
+
const addSessionToHeadersIfExists = (headers, session) => {
|
|
48
|
+
if (session) {
|
|
49
|
+
const requestHeaders = new Headers(headers);
|
|
50
|
+
requestHeaders.set(constants.DESCOPE_SESSION_HEADER, Buffer.from(JSON.stringify(session)).toString('base64'));
|
|
51
|
+
return requestHeaders;
|
|
52
|
+
}
|
|
53
|
+
return headers;
|
|
54
|
+
};
|
|
55
|
+
// returns a Middleware that checks if the user is authenticated
|
|
56
|
+
// if the user is not authenticated, it redirects to the redirectUrl
|
|
57
|
+
// if the user is authenticated, it adds the session to the headers
|
|
58
|
+
const createAuthMiddleware = (options = {}) => async (req) => {
|
|
59
|
+
logger.setLogger(options.logLevel);
|
|
60
|
+
logger.logger.debug('Auth middleware starts');
|
|
61
|
+
const jwt = getSessionJwt(req);
|
|
62
|
+
// check if the user is authenticated
|
|
63
|
+
let session;
|
|
64
|
+
try {
|
|
65
|
+
session = await sdk.getGlobalSdk({
|
|
66
|
+
projectId: options.projectId,
|
|
67
|
+
baseUrl: options.baseUrl
|
|
68
|
+
}).validateJwt(jwt);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
logger.logger.debug('Auth middleware, Failed to validate JWT', err);
|
|
72
|
+
if (!isPublicRoute(req, options)) {
|
|
73
|
+
const redirectUrl = options.redirectUrl || constants.DEFAULT_PUBLIC_ROUTES.signIn;
|
|
74
|
+
const url = req.nextUrl.clone();
|
|
75
|
+
// Create a URL object for redirectUrl. 'http://example.com' is just a placeholder.
|
|
76
|
+
const parsedRedirectUrl = new URL(redirectUrl, 'http://example.com');
|
|
77
|
+
url.pathname = parsedRedirectUrl.pathname;
|
|
78
|
+
const searchParams = utils.mergeSearchParams(url.search, parsedRedirectUrl.search);
|
|
79
|
+
if (searchParams) {
|
|
80
|
+
url.search = searchParams;
|
|
81
|
+
}
|
|
82
|
+
logger.logger.debug(`Auth middleware, Redirecting to ${redirectUrl}`);
|
|
83
|
+
return server_js.NextResponse.redirect(url);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
logger.logger.debug('Auth middleware finishes');
|
|
87
|
+
// add the session to the request, if it exists
|
|
88
|
+
const headers = addSessionToHeadersIfExists(req.headers, session);
|
|
89
|
+
return server_js.NextResponse.next({
|
|
90
|
+
request: {
|
|
91
|
+
headers
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
module.exports = createAuthMiddleware;
|
|
97
|
+
//# sourceMappingURL=authMiddleware.js.map
|