@propelauth/nextjs 0.3.9 → 0.3.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/README.md CHANGED
@@ -1,10 +1,15 @@
1
+ <p align="center">
2
+ <a href="https://www.propelauth.com?ref=github" target="_blank" align="center">
3
+ <img src="https://www.propelauth.com/imgs/lockup.svg" width="200">
4
+ </a>
5
+ </p>
6
+
7
+
1
8
  # PropelAuth Next.js (v13+) Library
2
9
 
3
10
  [PropelAuth](https://www.propelauth.com?utm_source=github&utm_medium=library&utm_campaign=nextjs) is a user management and authentication service for your B2B/multi-tenant applications.
4
11
 
5
- This library provides a simple way to integrate your Next.js application (either AppRouter or Pages) with PropelAuth.
6
-
7
- Next.js SSR/AppRouter support is currently in beta.
12
+ This library provides a simple way to integrate your Next.js application (either App Router or Pages) with PropelAuth.
8
13
 
9
14
  ## Installation
10
15
 
@@ -12,297 +17,163 @@ Next.js SSR/AppRouter support is currently in beta.
12
17
  npm install @propelauth/nextjs
13
18
  ```
14
19
 
15
- ## Setup
16
-
17
- Before you start, make sure you have a PropelAuth account. You can sign up for free at [here](https://auth.propelauth.com).
18
-
19
- You'll need to set the following .env variables in your Next.js application:
20
-
21
- - NEXT_PUBLIC_AUTH_URL
22
- - PROPELAUTH_API_KEY
23
- - PROPELAUTH_VERIFIER_KEY
24
- - PROPELAUTH_REDIRECT_URI
25
-
26
- You can find the NEXT_PUBLIC_AUTH_URL, PROPELAUTH_API_KEY, and PROPELAUTH_VERIFIER_KEY variables for your application in the PropelAuth Dashboard under Backend Integration.
27
-
28
- When you copy the PROPELAUTH_VERIFIER_KEY from the PropelAuth dashboard, it will automatically paste into your .env file with line breaks. However, due to the way some systems interpret multiline environment variables, you will need to edit the verifier key value to include ‘\n’ instead of newline characters. For example:
29
-
30
- ```
31
- PROPELAUTH_VERIFIER_KEY=-----BEGIN PUBLIC KEY-----\nMIIBIjANBgk...
32
- ```
20
+ ## Automatic Installation
33
21
 
34
- If authentication URL needs to be set at runtime, use `PROPELAUTH_AUTH_URL`. Otherwise, it falls back to `NEXT_PUBLIC_AUTH_URL`, which is set at build time.
22
+ If you would prefer a manual installation process instead of an automatic one, check out the installation guides for [App Router](https://docs.propelauth.com/reference/fullstack-apis/nextjsapp/installation-and-setup) and [Pages Router](https://docs.propelauth.com/reference/fullstack-apis/nextjspages/installation-and-setup).
35
23
 
36
- For the PROPELAUTH_REDIRECT_URI variable, you need to add /api/auth/callback to the end of one of your allowed frontend locations. So, for example, if you are developing in the test environment and using http://localhost:3000, you would use http://localhost:3000/api/auth/callback
24
+ Begin by installing the PropelAuth CLI:
37
25
 
38
- ### 1. Set up routes
39
-
40
- In your `src/app/api/auth/[slug]` directory, create a file called `route.ts` with the following content:
41
-
42
- ```typescript
43
- import { getRouteHandlers } from '@propelauth/nextjs/server/app-router'
44
- import { NextRequest } from 'next/server'
45
-
46
- // postLoginRedirectPathFn is optional, but if you want to redirect the user to a different page after login, you can do so here.
47
- const routeHandlers = getRouteHandlers({
48
- postLoginRedirectPathFn: (req: NextRequest) => {
49
- return '/'
50
- },
51
- })
52
- export const GET = routeHandlers.getRouteHandler
53
- export const POST = routeHandlers.postRouteHandler
26
+ ```bash
27
+ npm i -g @propelauth/cli
54
28
  ```
55
29
 
56
- ### 2. Set up AuthProvider
30
+ ## Logging into the PropelAuth CLI
57
31
 
58
- #### App Router
32
+ Before we install PropelAuth in your Next.js project we first have to log into the CLI. If you haven't already created an account in PropelAuth, navigate to [auth.propelauth.com](https://auth.propelauth.com/en/signup) to get started.
59
33
 
60
- In your root layout, `src/app/layout.tsx`, add the `AuthProvider`:
34
+ Once you have an account with PropelAuth, run this command to login to the CLI:
61
35
 
62
- ```typescript jsx
63
- export default async function RootLayout({children}: {children: React.ReactNode}) {
64
- return (
65
- <html lang="en">
66
- <AuthProvider authUrl={process.env.NEXT_PUBLIC_AUTH_URL}>
67
- <body className={inter.className}>{children}</body>
68
- </AuthProvider>
69
- </html>
70
- )
71
- }
36
+ ```bash
37
+ propelauth login
72
38
  ```
73
39
 
74
- #### Pages Router
75
-
76
- In your `_app.tsx` file, add the `AuthProvider`:
40
+ To login you'll be prompted to create and copy/paste a Personal API Key into your terminal.
77
41
 
78
- ```typescript jsx
79
- export default function MyApp({Component, pageProps}: AppProps) {
80
- return (
81
- <AuthProvider authUrl={process.env.NEXT_PUBLIC_AUTH_URL}>
82
- <Component {...pageProps} />
83
- </AuthProvider>
84
- )
85
- }
86
42
  ```
87
-
88
- ### 3. Set up middleware (App Router only - skip if using Pages)
89
-
90
- In your `src/middleware.ts` file, add the following:
91
-
92
- ```typescript
93
- import { authMiddleware } from '@propelauth/nextjs/server/app-router'
94
-
95
- export const middleware = authMiddleware
96
-
97
- // The middleware is responsible for keeping the user session up to date.
98
- // It should be called on every request that requires authentication AND /api/auth/.* routes.
99
- export const config = {
100
- matcher: [
101
- // REQUIRED: Match all request paths that start with /api/auth/
102
- '/api/auth/(.*)',
103
- // OPTIONAL: Don't match any static assets
104
- '/((?!_next/static|_next/image|favicon.ico).*)',
105
- ],
106
- }
43
+ ┌ ⚡ PropelAuth Login
44
+
45
+
46
+ │ Please visit the following URL to create a personal API key:
47
+
48
+ ● https://auth.propelauth.com/api_keys/personal
49
+
50
+
51
+ ◆ Enter your API key
52
+ │ # enter your API key here
53
+
107
54
  ```
108
55
 
109
- ## Usage
56
+ You can create a Personal API Key by navigating to https://auth.propelauth.com/api_keys/personal and clicking **+ New API Key**.
110
57
 
111
- ### Get the user in Server Components (App Router example)
112
58
 
113
- ```tsx
114
- import { getUser } from '@propelauth/nextjs/server/app-router'
59
+ ### Selecting a Default Project
115
60
 
116
- const WelcomeMessage = async () => {
117
- const user = await getUser()
61
+ Once your API Key is validated the CLI will prompt you to select a default project, if desired. If you select a default project, the CLI will not prompt you to select a project again until you repeat the login process or run the `set-default-project` command.
118
62
 
119
- if (user) {
120
- return <div>Hello {user.firstName}!</div>
121
- } else {
122
- return <div>Please log in to be welcomed</div>
123
- }
124
- }
125
63
  ```
126
-
127
- ```tsx
128
- import { getUserOrRedirect } from '@propelauth/nextjs/server/app-router'
129
-
130
- const WelcomeMessage = async () => {
131
- // If the user is not logged in, they will be redirected to the login page
132
- const user = await getUserOrRedirect()
133
-
134
- return <div>Hello {user.firstName}!</div>
135
- }
64
+
65
+ ◇ ✓ Projects fetched successfully
66
+
67
+ ◆ Select a project to use
68
+ │ ● Always ask which project to use (You will be prompted for each command)
69
+ │ ○ Acme Inc / New Project
70
+
136
71
  ```
137
72
 
138
- ### Get the user in getServerSideProps (Pages example)
73
+ ## Installing and Setting up PropelAuth in Next.js
139
74
 
140
- ```tsx
141
- import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
142
- import { getUserFromServerSideProps } from '@propelauth/nextjs/server/pages'
143
- import { User } from '@propelauth/nextjs/client'
75
+ Once you have logged into the CLI it's time to install PropelAuth within your Next.js app! Navigate to your Next.js project directory and run the following command:
144
76
 
145
- export default function WelcomeMessage({ userJson }: InferGetServerSidePropsType<typeof getServerSideProps>) {
146
- // Deserialize the user from the JSON string so you can call functions like user.getOrg()
147
- const user = User.fromJSON(userJson)
148
- return <div>Hello, {user.firstName}</div>
149
- }
77
+ ```bash
78
+ propelauth setup
79
+ ```
80
+
81
+ During installation you'll see the following prompts:
82
+
83
+ ```
84
+ ┌ ⚡ PropelAuth Setup
85
+
86
+ ◆ Select your project framework:
87
+ │ ○ Next.js (App Router)
88
+ │ ● Next.js (Pages Router) (Uses pages/ directory structure)
89
+
90
+ ◆ Select a project to use for this command
91
+ │ ● Acme Inc / New Project
92
+
93
+ ◆ Enter the URL your Next.js app runs on:
94
+ │ ↳ http://localhost:3000
95
+
96
+ ● No API key found in environment file
97
+
98
+ ◆ Would you like to generate a new Backend Integration API Key for this project?
99
+ │ ● yes / ○ no
100
+
101
+ │ Enter a name for the new Backend Integration API Key:
102
+ │ ↳ Next.js Integration
103
+
104
+ ● Updates needed for the Frontend Integration settings for your test environment
105
+ │ - Login redirect path: / → /api/auth/callback
106
+ │ - Logout redirect path: / → /api/auth/logout
107
+ │ - Development URL: none → http://localhost:3000
108
+
109
+ ◆ Your test environment config needs to be updated, would you like to apply these changes now?
110
+ │ ● yes / ○ no
111
+
112
+ ◆ Install @propelauth/nextjs now?
113
+ │ ● npm install @propelauth/nextjs (detected)
114
+ │ ○ yarn add @propelauth/nextjs
115
+ │ ○ pnpm install @propelauth/nextjs
116
+ │ ○ bun install @propelauth/nextjs
117
+ │ ○ Skip installation
118
+
119
+ ● _app.tsx with AuthProvider at /src/pages/_app.tsx differs from what we expected.
120
+
121
+ ◆ Overwrite _app.tsx with AuthProvider?
122
+ │ ● Yes / ○ No
123
+
124
+ └ PropelAuth has been successfully set up in your Next.js project!
125
+ ```
126
+
127
+ Once the CLI has successfully installed PropelAuth within your Next.js project it will also include some example components to help you get started.
128
+
129
+ ### App Router Server Component
130
+
131
+ ```jsx {{ title: "Server Component" }}
132
+ import { getUserOrRedirect } from "@propelauth/nextjs/server/app-router";
150
133
 
151
- export const getServerSideProps: GetServerSideProps = async (context) => {
152
- const user = await getUserFromServerSideProps(context)
153
- if (!user) {
154
- return { redirect: { destination: '/api/auth/login', permanent: false } }
155
- }
156
- return { props: { userJson: JSON.stringify(user) } }
134
+ const WelcomeMessage = async () => {
135
+ const user = await getUserOrRedirect()
136
+ return <div>Welcome, {user.email}!</div>
157
137
  }
158
- ```
159
-
160
- ### Get the user in API Routes (Pages example)
161
138
 
162
- ```ts
163
- import { NextApiRequest, NextApiResponse } from 'next'
164
- import { getUserFromApiRouteRequest } from '@propelauth/nextjs/server/pages'
165
-
166
- export default async function handler(req: NextApiRequest, res: NextApiResponse) {
167
- const user = await getUserFromApiRouteRequest(req, res)
168
- if (user) {
169
- res.status(200).json({ email: user.email })
170
- } else {
171
- res.status(401).json({ error: 'unauthorized' })
172
- }
173
- }
139
+ export default WelcomeMessage;
174
140
  ```
175
141
 
176
- ### Get the user in Client Components
142
+ ### App Router Client Component
177
143
 
178
- ```tsx
179
- 'use client'
144
+ ```jsx
145
+ "use client";
180
146
 
181
- import { useUser } from '@propelauth/nextjs/client'
147
+ import { useUser } from "@propelauth/nextjs/client";
182
148
 
183
149
  const WelcomeMessage = () => {
184
- const { loading, user } = useUser()
185
-
150
+ const {loading, user} = useUser()
186
151
  if (loading) {
187
152
  return <div>Loading...</div>
188
153
  } else if (user) {
189
- return <div>Hello {user.firstName}!</div>
154
+ return <div>Welcome, {user.email}!</div>
190
155
  } else {
191
156
  return <div>Please log in to be welcomed</div>
192
157
  }
193
158
  }
194
- ```
195
-
196
- ### Checking organization membership / RBAC
197
-
198
- Note that this works on both the client's `User` object or the client/server `UserFromToken` object, but the below example is on the server.
199
-
200
- If you are curious where the organization information comes from, check out our documentation on [organizations](https://docs.propelauth.com/overview/organizations?utm_source=github&utm_medium=library&utm_campaign=nextjs).
201
- The quick answer is:
202
-
203
- - PropelAuth provides UI for users to create organizations and invite other users to join them.
204
- - Your users can also create Enterprise SSO/SAML connections to their own Identity Providers (IdPs) so their organization members can log in with their existing work credentials.
205
- - You can create organizations and add users to them via our APIs or our Dashboard.
206
-
207
- ```tsx
208
- // src/app/org/[slug]/page.tsx
209
- import { getUserOrRedirect } from '@propelauth/nextjs/server/app-router'
210
-
211
- export default async function AdminOnlyPage({ params }: { params: { slug: string } }) {
212
- const user = await getUserOrRedirect()
213
- const org = user.getOrgByName(params.slug)
214
- const isAdmin = org?.isRole('Admin')
215
-
216
- if (!isAdmin) {
217
- return <div>Not found</div>
218
- } else {
219
- return (
220
- <div>
221
- Welcome {user.firstName}, Admin of {org?.orgName}
222
- </div>
223
- )
224
- }
225
- }
226
- ```
227
-
228
- ### Logging out
229
-
230
- ```tsx
231
- 'use client'
232
-
233
- import { useLogoutFunction } from '@propelauth/nextjs/client'
234
-
235
- export default function LogoutButton() {
236
- const logoutFn = useLogoutFunction()
237
- return <button onClick={logoutFn}>Logout</button>
238
- }
239
- ```
240
-
241
- ### Logging in / Signing up
242
-
243
- If you don't want to use redirect functions, you can also use `useHostedPageUrls` which will return the URLs instead of redirecting.
244
-
245
- ```tsx
246
- 'use client'
247
159
 
248
- import { useRedirectFunctions } from '@propelauth/nextjs/client'
249
-
250
- export default function SignupAndLoginButtons() {
251
- const { redirectToSignupPage, redirectToLoginPage } = useRedirectFunctions()
252
- return (
253
- <>
254
- <button onClick={redirectToSignupPage}>Sign up</button>
255
- <button onClick={redirectToLoginPage}>Log in</button>
256
- </>
257
- )
258
- }
160
+ export default WelcomeMessage;
259
161
  ```
260
162
 
261
- ### Redirecting to Account / Org pages
262
-
263
- PropelAuth also provides you with pre-built account and organization management UIs.
264
- You can redirect your users to these pages by using the following functions:
163
+ ## Calling Backend APIs
265
164
 
266
- ```tsx
267
- 'use client'
165
+ You can also use the library to call the PropelAuth APIs directly, allowing you to fetch users, create orgs, and a lot more.
166
+ See the [API Reference](https://docs.propelauth.com/reference) for more information.
268
167
 
269
- import { useRedirectFunctions } from '@propelauth/nextjs/client'
270
-
271
- export default function AccountAndOrgButtons() {
272
- const { redirectToAccountPage, redirectToOrgPage } = useRedirectFunctions()
273
- return (
274
- <>
275
- <button onClick={redirectToAccountPage}>Account</button>
276
- <button onClick={redirectToOrgPage}>Organization</button>
277
- </>
278
- )
279
- }
280
- ```
281
-
282
- ### Using APIs
283
-
284
- You can use our [APIs](https://docs.propelauth.com/reference/backend-apis/node) like so:
285
-
286
- ```ts
287
- import { getPropelAuthApis } from '@propelauth/nextjs/server'
168
+ ```typescript
169
+ import { getPropelAuthApis } from "@propelauth/nextjs/server";
288
170
 
171
+ // Can be done in an API route or getServerSideProps
289
172
  const apis = getPropelAuthApis()
290
173
  await apis.disableUser(userId)
291
174
  ```
292
175
 
293
- ### Making a call to an external API
176
+ ## Questions?
294
177
 
295
- PropelAuth also supports backend that are not Next.js. To make an [authenticated request](https://docs.propelauth.com/getting-started/making-authenticated-requests)
296
- to an external API, you'll need an access token. You can get an access token on the frontend from the `useUser` hook:
297
-
298
- ```tsx
299
- import { useUser } from '@propelauth/nextjs/client'
300
-
301
- const MyComponent = () => {
302
- const { loading, accessToken } = useUser()
303
-
304
- // Make a request to an external API with useEffect, useQuery, etc.
305
- }
306
- ```
178
+ Feel free to reach out at support@propelauth.com
307
179
 
308
- Within the App Router, you can also call `getAccessToken` to get the access token.
@@ -1,5 +1,5 @@
1
1
  import * as _propelauth_node_apis from '@propelauth/node-apis';
2
- export { AccessToken, AccessTokenCreationException, AddUserToOrgException, AddUserToOrgRequest, ApiKeyCreateException, ApiKeyDeleteException, ApiKeyFetchException, ApiKeyFull, ApiKeyNew, ApiKeyResultPage, ApiKeyUpdateException, ApiKeyUpdateRequest, ApiKeyValidateException, ApiKeyValidateRateLimitedException, ApiKeyValidation, ApiKeysCreateRequest, ApiKeysQueryRequest, ChangeUserRoleInOrgException, CreateAccessTokenRequest, CreateMagicLinkRequest, CreateOrgException, CreateOrgRequest, CreateUserException, CreateUserRequest, FetchPendingInvitesParams, FetchSamlSpMetadataResponse, ForbiddenException, IdpProvider, MagicLink, MagicLinkCreationException, MigrateUserException, MigrateUserFromExternalSourceRequest, Org, OrgApiKeyValidation, OrgQuery, OrgQueryResponse, Organization, PendingInvite, PendingInvitesPage, PersonalApiKeyValidation, RateLimitedException, RemoveUserFromOrgException, RemoveUserFromOrgRequest, RevokePendingOrgInviteRequest, SetSamlIdpMetadataRequest, TokenVerificationMetadata, UnexpectedException, UpdateOrgException, UpdateOrgRequest, UpdateUserEmailException, UpdateUserEmailRequest, UpdateUserMetadataException, UpdateUserMetadataRequest, UpdateUserPasswordException, UpdateUserPasswordRequest, UserInOrgMetadata, UserNotFoundException, UsersInOrgPagedResponse, UsersInOrgQuery, UsersPagedResponse, UsersQuery } from '@propelauth/node-apis';
2
+ export { AccessToken, AccessTokenCreationException, AddUserToOrgException, AddUserToOrgRequest, ApiKeyCreateException, ApiKeyDeleteException, ApiKeyFetchException, ApiKeyFull, ApiKeyNew, ApiKeyResultPage, ApiKeyUpdateException, ApiKeyUpdateRequest, ApiKeyValidateException, ApiKeyValidateRateLimitedException, ApiKeyValidation, ApiKeysCreateRequest, ApiKeysQueryRequest, ChangeUserRoleInOrgException, CreateAccessTokenRequest, CreateMagicLinkRequest, CreateOrgException, CreateOrgRequest, CreateUserException, CreateUserRequest, FetchPendingInvitesParams, FetchSamlSpMetadataResponse, ForbiddenException, IdpProvider, MagicLink, MagicLinkCreationException, MigrateUserException, MigrateUserFromExternalSourceRequest, MigrateUserPasswordException, MigrateUserPasswordRequest, Org, OrgApiKeyValidation, OrgQuery, OrgQueryResponse, Organization, PendingInvite, PendingInvitesPage, PersonalApiKeyValidation, RateLimitedException, RemoveUserFromOrgException, RemoveUserFromOrgRequest, RevokePendingOrgInviteRequest, SetSamlIdpMetadataRequest, TokenVerificationMetadata, UnexpectedException, UpdateOrgException, UpdateOrgRequest, UpdateUserEmailException, UpdateUserEmailRequest, UpdateUserMetadataException, UpdateUserMetadataRequest, UpdateUserPasswordException, UpdateUserPasswordRequest, UserInOrgMetadata, UserNotFoundException, UsersInOrgPagedResponse, UsersInOrgQuery, UsersPagedResponse, UsersQuery } from '@propelauth/node-apis';
3
3
  import { NextResponse, NextRequest } from 'next/server';
4
4
 
5
5
  declare enum SocialLoginProvider {
@@ -210,6 +210,7 @@ declare const getPropelAuthApis: () => {
210
210
  createMagicLink: (createMagicLinkRequest: _propelauth_node_apis.CreateMagicLinkRequest) => Promise<_propelauth_node_apis.MagicLink>;
211
211
  createAccessToken: (createAccessTokenRequest: _propelauth_node_apis.CreateAccessTokenRequest) => Promise<_propelauth_node_apis.AccessToken>;
212
212
  migrateUserFromExternalSource: (migrateUserFromExternalSourceRequest: _propelauth_node_apis.MigrateUserFromExternalSourceRequest) => Promise<_propelauth_node_apis.CreatedUser>;
213
+ migrateUserPassword: (migrateUserPasswordRequest: _propelauth_node_apis.MigrateUserPasswordRequest) => Promise<boolean>;
213
214
  deleteUser: (userId: string) => Promise<boolean>;
214
215
  disableUser: (userId: string) => Promise<boolean>;
215
216
  enableUser: (userId: string) => Promise<boolean>;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/index.ts","../../src/loginMethod.ts","../../src/user.ts","../../src/server/exceptions.ts","../../src/server/shared.ts","../../src/server/api.ts","../../src/server/middleware/auth-hook-response.ts","../../src/shared.ts","../../src/server/app-router.ts","../../src/server/middleware/advanced-middleware.ts"],"sourcesContent":["export { validateAccessToken, validateAccessTokenOrUndefined } from './shared'\nexport type { OrgIdToOrgMemberInfo } from '../user'\nexport { UserFromToken, OrgMemberInfo } from '../user'\nexport { UnauthorizedException, ConfigurationException } from './exceptions'\nexport { getPropelAuthApis } from './api'\nexport { AuthHookResponse } from './middleware/auth-hook-response'\nexport { buildAuthMiddleware } from './middleware/advanced-middleware'\nexport type { PropelAuthMiddlewareOptions } from './middleware/advanced-middleware'\nexport type {\n AccessToken,\n AccessTokenCreationException,\n AddUserToOrgException,\n AddUserToOrgRequest,\n ApiKeyCreateException,\n ApiKeyDeleteException,\n ApiKeyFetchException,\n ApiKeyFull,\n ApiKeyNew,\n ApiKeyResultPage,\n ApiKeyUpdateException,\n ApiKeyUpdateRequest,\n ApiKeyValidateException,\n ApiKeyValidateRateLimitedException,\n ApiKeyValidation,\n ApiKeysCreateRequest,\n ApiKeysQueryRequest,\n ChangeUserRoleInOrgException,\n CreateAccessTokenRequest,\n CreateMagicLinkRequest,\n CreateOrgException,\n CreateOrgRequest,\n CreateUserException,\n CreateUserRequest,\n ForbiddenException,\n MagicLink,\n MagicLinkCreationException,\n MigrateUserException,\n MigrateUserFromExternalSourceRequest,\n Org,\n Organization,\n OrgApiKeyValidation,\n OrgQuery,\n OrgQueryResponse,\n PersonalApiKeyValidation,\n RateLimitedException,\n RemoveUserFromOrgException,\n RemoveUserFromOrgRequest,\n TokenVerificationMetadata,\n UnexpectedException,\n UpdateOrgException,\n UpdateOrgRequest,\n UpdateUserEmailException,\n UpdateUserEmailRequest,\n UpdateUserMetadataException,\n UpdateUserMetadataRequest,\n UpdateUserPasswordException,\n UpdateUserPasswordRequest,\n UserNotFoundException,\n UserInOrgMetadata,\n UsersInOrgQuery,\n UsersPagedResponse,\n UsersInOrgPagedResponse,\n UsersQuery,\n FetchPendingInvitesParams,\n PendingInvitesPage,\n PendingInvite,\n RevokePendingOrgInviteRequest,\n FetchSamlSpMetadataResponse,\n SetSamlIdpMetadataRequest,\n IdpProvider,\n} from '@propelauth/node-apis'\n","export enum SocialLoginProvider {\n Google = 'Google',\n GitHub = 'GitHub',\n Microsoft = 'Microsoft',\n Slack = 'Slack',\n LinkedIn = 'LinkedIn',\n Salesforce = 'Salesforce',\n Xero = 'Xero',\n QuickBooksOnline = 'QuickBooks Online',\n}\n\nexport enum SamlLoginProvider {\n Google = 'Google',\n Rippling = 'Rippling',\n OneLogin = 'OneLogin',\n JumpCloud = 'JumpCloud',\n Okta = 'Okta',\n Azure = 'Azure',\n Duo = 'Duo',\n Generic = 'Generic',\n}\n\ntype InternalPasswordLoginMethod = {\n login_method: 'password'\n}\n\ntype InternalMagicLinkLoginMethod = {\n login_method: 'magic_link'\n}\n\ntype InternalSocialSsoLoginMethod = {\n login_method: 'social_sso'\n provider: SocialLoginProvider\n}\n\ntype InternalEmailConfirmationLinkLoginMethod = {\n login_method: 'email_confirmation_link'\n}\n\ntype InternalSamlSsoLoginMethod = {\n login_method: 'saml_sso'\n provider: SamlLoginProvider\n org_id: string\n}\n\ntype InternalImpersonationLoginMethod = {\n login_method: 'impersonation'\n}\n\ntype InternalGeneratedFromBackendApiLoginMethod = {\n login_method: 'generated_from_backend_api'\n}\n\ntype InternalUnknownLoginMethod = {\n login_method: 'unknown'\n}\n\nexport type InternalLoginMethod =\n | InternalPasswordLoginMethod\n | InternalMagicLinkLoginMethod\n | InternalSocialSsoLoginMethod\n | InternalEmailConfirmationLinkLoginMethod\n | InternalSamlSsoLoginMethod\n | InternalImpersonationLoginMethod\n | InternalGeneratedFromBackendApiLoginMethod\n | InternalUnknownLoginMethod\n\ntype PasswordLoginMethod = {\n loginMethod: 'password'\n}\n\ntype MagicLinkLoginMethod = {\n loginMethod: 'magic_link'\n}\n\ntype SocialSsoLoginMethod = {\n loginMethod: 'social_sso'\n provider: SocialLoginProvider\n}\n\ntype EmailConfirmationLinkLoginMethod = {\n loginMethod: 'email_confirmation_link'\n}\n\ntype SamlSsoLoginMethod = {\n loginMethod: 'saml_sso'\n provider: SamlLoginProvider\n orgId: string\n}\n\ntype ImpersonationLoginMethod = {\n loginMethod: 'impersonation'\n}\n\ntype GeneratedFromBackendApiLoginMethod = {\n loginMethod: 'generated_from_backend_api'\n}\n\ntype UnknownLoginMethod = {\n loginMethod: 'unknown'\n}\n\nexport type LoginMethod =\n | PasswordLoginMethod\n | MagicLinkLoginMethod\n | SocialSsoLoginMethod\n | EmailConfirmationLinkLoginMethod\n | SamlSsoLoginMethod\n | ImpersonationLoginMethod\n | GeneratedFromBackendApiLoginMethod\n | UnknownLoginMethod\n\nexport function toLoginMethod(snake_case?: InternalLoginMethod): LoginMethod {\n if (!snake_case) {\n return { loginMethod: 'unknown' }\n }\n\n switch (snake_case.login_method) {\n case 'password':\n return { loginMethod: 'password' }\n case 'magic_link':\n return { loginMethod: 'magic_link' }\n case 'social_sso':\n return { loginMethod: 'social_sso', provider: snake_case.provider }\n case 'email_confirmation_link':\n return { loginMethod: 'email_confirmation_link' }\n case 'saml_sso':\n return { loginMethod: 'saml_sso', provider: snake_case.provider, orgId: snake_case.org_id }\n case 'impersonation':\n return { loginMethod: 'impersonation' }\n case 'generated_from_backend_api':\n return { loginMethod: 'generated_from_backend_api' }\n default:\n return { loginMethod: 'unknown' }\n }\n}\n","import { InternalLoginMethod, LoginMethod, toLoginMethod } from './loginMethod'\n\nexport class UserFromToken {\n public userId: string\n\n public activeOrgId?: string\n public orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo\n\n // Metadata about the user\n public email: string\n public firstName?: string\n public lastName?: string\n public username?: string\n public properties?: { [key: string]: unknown }\n public loginMethod?: LoginMethod\n\n // If you used our migration APIs to migrate this user from a different system,\n // this is their original ID from that system.\n public legacyUserId?: string\n public impersonatorUserId?: string\n\n constructor(\n userId: string,\n email: string,\n orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo,\n firstName?: string,\n lastName?: string,\n username?: string,\n legacyUserId?: string,\n impersonatorUserId?: string,\n properties?: { [key: string]: unknown },\n activeOrgId?: string,\n loginMethod?: LoginMethod\n ) {\n this.userId = userId\n\n this.activeOrgId = activeOrgId\n this.orgIdToOrgMemberInfo = orgIdToOrgMemberInfo\n\n this.email = email\n this.firstName = firstName\n this.lastName = lastName\n this.username = username\n\n this.legacyUserId = legacyUserId\n this.impersonatorUserId = impersonatorUserId\n\n this.properties = properties\n this.loginMethod = loginMethod\n }\n\n public getActiveOrg(): OrgMemberInfo | undefined {\n if (!this.activeOrgId || !this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n return this.orgIdToOrgMemberInfo[this.activeOrgId]\n }\n\n public getActiveOrgId(): string | undefined {\n return this.activeOrgId\n }\n\n public getOrg(orgId: string): OrgMemberInfo | undefined {\n if (!this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n return this.orgIdToOrgMemberInfo[orgId]\n }\n\n public getOrgByName(orgName: string): OrgMemberInfo | undefined {\n if (!this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n const urlSafeOrgName = orgName.toLowerCase().replace(/ /g, '-')\n for (const orgId in this.orgIdToOrgMemberInfo) {\n const orgMemberInfo = this.orgIdToOrgMemberInfo[orgId]\n if (orgMemberInfo.urlSafeOrgName === urlSafeOrgName) {\n return orgMemberInfo\n }\n }\n\n return undefined\n }\n\n public getOrgs(): OrgMemberInfo[] {\n if (!this.orgIdToOrgMemberInfo) {\n return []\n }\n\n return Object.values(this.orgIdToOrgMemberInfo)\n }\n\n public isImpersonating(): boolean {\n return !!this.impersonatorUserId\n }\n\n public static fromJSON(json: string): UserFromToken {\n const obj = JSON.parse(json)\n const orgIdToOrgMemberInfo: OrgIdToOrgMemberInfo = {}\n for (const orgId in obj.orgIdToOrgMemberInfo) {\n orgIdToOrgMemberInfo[orgId] = OrgMemberInfo.fromJSON(JSON.stringify(obj.orgIdToOrgMemberInfo[orgId]))\n }\n return new UserFromToken(\n obj.userId,\n obj.email,\n orgIdToOrgMemberInfo,\n obj.firstName,\n obj.lastName,\n obj.username,\n obj.legacyUserId,\n obj.impersonatorUserId,\n obj.properties,\n obj.activeOrgId,\n obj.loginMethod\n )\n }\n\n public static fromJwtPayload(payload: InternalUser): UserFromToken {\n let activeOrgId: string | undefined\n let orgIdToOrgMemberInfo: OrgIdToOrgMemberInfo | undefined\n\n if (payload.org_member_info) {\n activeOrgId = payload.org_member_info.org_id\n orgIdToOrgMemberInfo = toOrgIdToOrgMemberInfo({ [activeOrgId]: payload.org_member_info })\n } else {\n activeOrgId = undefined\n orgIdToOrgMemberInfo = toOrgIdToOrgMemberInfo(payload.org_id_to_org_member_info)\n }\n\n const loginMethod = toLoginMethod(payload.login_method)\n\n return new UserFromToken(\n payload.user_id,\n payload.email,\n orgIdToOrgMemberInfo,\n payload.first_name,\n payload.last_name,\n payload.username,\n payload.legacy_user_id,\n payload.impersonator_user_id,\n payload.properties,\n activeOrgId,\n loginMethod\n )\n }\n}\n\nexport type OrgIdToOrgMemberInfo = {\n [orgId: string]: OrgMemberInfo\n}\n\nexport enum OrgRoleStructure {\n SingleRole = \"single_role_in_hierarchy\",\n MultiRole = \"multi_role\",\n}\n\nexport class OrgMemberInfo {\n public orgId: string\n public orgName: string\n public orgMetadata: { [key: string]: any }\n public urlSafeOrgName: string\n public orgRoleStructure: OrgRoleStructure\n\n public userAssignedRole: string\n public userInheritedRolesPlusCurrentRole: string[]\n public userPermissions: string[]\n public userAssignedAdditionalRoles: string[]\n\n constructor(\n orgId: string,\n orgName: string,\n orgMetadata: { [key: string]: any },\n urlSafeOrgName: string,\n userAssignedRole: string,\n userInheritedRolesPlusCurrentRole: string[],\n userPermissions: string[],\n orgRoleStructure: OrgRoleStructure,\n userAssignedAdditionalRoles: string[]\n ) {\n this.orgId = orgId\n this.orgName = orgName\n this.orgMetadata = orgMetadata\n this.urlSafeOrgName = urlSafeOrgName\n this.orgRoleStructure = orgRoleStructure\n\n this.userAssignedRole = userAssignedRole\n this.userInheritedRolesPlusCurrentRole = userInheritedRolesPlusCurrentRole\n this.userPermissions = userPermissions\n this.userAssignedAdditionalRoles = userAssignedAdditionalRoles\n }\n\n // validation methods\n\n public isRole(role: string): boolean {\n if (this.orgRoleStructure === OrgRoleStructure.MultiRole) {\n return this.userAssignedRole === role || this.userAssignedAdditionalRoles.includes(role)\n } else {\n return this.userAssignedRole === role\n }\n }\n\n public isAtLeastRole(role: string): boolean {\n if (this.orgRoleStructure === OrgRoleStructure.MultiRole) {\n return this.userAssignedRole === role || this.userAssignedAdditionalRoles.includes(role)\n } else {\n return this.userInheritedRolesPlusCurrentRole.includes(role)\n }\n }\n\n public hasPermission(permission: string): boolean {\n return this.userPermissions.includes(permission)\n }\n\n public hasAllPermissions(permissions: string[]): boolean {\n return permissions.every((permission) => this.hasPermission(permission))\n }\n\n public static fromJSON(json: string): OrgMemberInfo {\n const obj = JSON.parse(json)\n return new OrgMemberInfo(\n obj.orgId,\n obj.orgName,\n obj.orgMetadata,\n obj.urlSafeOrgName,\n obj.userAssignedRole,\n obj.userInheritedRolesPlusCurrentRole,\n obj.userPermissions,\n obj.orgRoleStructure,\n obj.userAssignedAdditionalRoles\n )\n }\n\n // getters for the private fields\n\n get assignedRole(): string {\n return this.userAssignedRole\n }\n\n get assignedRoles(): string[] {\n if (this.orgRoleStructure === OrgRoleStructure.MultiRole) {\n return this.userAssignedAdditionalRoles.concat(this.userAssignedRole)\n } else {\n return [this.userAssignedRole]\n }\n }\n\n get inheritedRolesPlusCurrentRole(): string[] {\n if (this.orgRoleStructure === OrgRoleStructure.MultiRole) {\n return this.userAssignedAdditionalRoles.concat(this.userAssignedRole)\n } else {\n return this.userInheritedRolesPlusCurrentRole\n }\n }\n\n get permissions(): string[] {\n return this.userPermissions\n }\n}\n\n// These Internal types exist since the server returns snake case, but typescript/javascript\n// convention is camelCase.\nexport type InternalOrgMemberInfo = {\n org_id: string\n org_name: string\n org_metadata: { [key: string]: any }\n url_safe_org_name: string\n org_role_structure: OrgRoleStructure\n user_role: string\n inherited_user_roles_plus_current_role: string[]\n user_permissions: string[]\n additional_roles: string[]\n}\n\nexport type InternalUser = {\n user_id: string\n\n org_member_info?: InternalOrgMemberInfo\n org_id_to_org_member_info?: { [org_id: string]: InternalOrgMemberInfo }\n\n email: string\n first_name?: string\n last_name?: string\n username?: string\n properties?: { [key: string]: unknown }\n login_method?: InternalLoginMethod\n\n // If you used our migration APIs to migrate this user from a different system, this is their original ID from that system.\n legacy_user_id?: string\n impersonator_user_id?: string\n}\n\nexport function toUser(snake_case: InternalUser): UserFromToken {\n return UserFromToken.fromJwtPayload(snake_case)\n}\n\nexport function toOrgIdToOrgMemberInfo(snake_case?: {\n [org_id: string]: InternalOrgMemberInfo\n}): OrgIdToOrgMemberInfo | undefined {\n if (snake_case === undefined) {\n return undefined\n }\n const camelCase: OrgIdToOrgMemberInfo = {}\n\n for (const key of Object.keys(snake_case)) {\n const snakeCaseValue = snake_case[key]\n if (snakeCaseValue) {\n camelCase[key] = new OrgMemberInfo(\n snakeCaseValue.org_id,\n snakeCaseValue.org_name,\n snakeCaseValue.org_metadata,\n snakeCaseValue.url_safe_org_name,\n snakeCaseValue.user_role,\n snakeCaseValue.inherited_user_roles_plus_current_role,\n snakeCaseValue.user_permissions,\n snakeCaseValue.org_role_structure,\n snakeCaseValue.additional_roles\n )\n }\n }\n\n return camelCase\n}\n","export class UnauthorizedException extends Error {\n readonly message: string\n readonly status: number\n\n constructor(message: string) {\n super(message)\n this.message = message\n this.status = 401\n }\n}\n\nexport class ConfigurationException extends Error {\n readonly message: string\n readonly status: number\n\n constructor(message: string) {\n super(message)\n this.message = message\n this.status = 500\n }\n}\n","import { ResponseCookie } from 'next/dist/compiled/@edge-runtime/cookies'\nimport { InternalUser, toUser, UserFromToken } from '../user'\nimport { ConfigurationException, UnauthorizedException } from './exceptions'\nimport * as jose from 'jose'\n\ntype RefreshAndAccessTokens = {\n refreshToken: string\n accessToken: string\n error: 'none'\n}\n\ntype RefreshAndAccessTokensUnauthorizedError = {\n error: 'unauthorized'\n}\n\ntype RefreshAndAccessTokensUnexpectedError = {\n error: 'unexpected'\n}\n\nexport type RefreshTokenResponse =\n | RefreshAndAccessTokens\n | RefreshAndAccessTokensUnauthorizedError\n | RefreshAndAccessTokensUnexpectedError\n\nexport const LOGIN_PATH = '/api/auth/login'\nexport const CALLBACK_PATH = '/api/auth/callback'\nexport const USERINFO_PATH = '/api/auth/userinfo'\nexport const LOGOUT_PATH = '/api/auth/logout'\nexport const ACCESS_TOKEN_COOKIE_NAME = '__pa_at'\nexport const REFRESH_TOKEN_COOKIE_NAME = '__pa_rt'\nexport const STATE_COOKIE_NAME = '__pa_state'\nexport const CUSTOM_HEADER_FOR_ACCESS_TOKEN = 'x-propelauth-access-token'\nexport const CUSTOM_HEADER_FOR_URL = 'x-propelauth-current-url'\nexport const CUSTOM_HEADER_FOR_PATH = 'x-propelauth-current-path'\nexport const RETURN_TO_PATH_COOKIE_NAME = '__pa_return_to_path'\n\nexport const COOKIE_OPTIONS: Partial<ResponseCookie> = {\n httpOnly: true,\n secure: true,\n path: '/',\n}\n\nexport function getAuthUrlOrigin() {\n return getAuthUrl().origin\n}\n\nexport function getAuthUrl() {\n const authUrl = process.env.PROPELAUTH_AUTH_URL || process.env.NEXT_PUBLIC_AUTH_URL\n if (!authUrl) {\n throw new Error('NEXT_PUBLIC_AUTH_URL is not set')\n }\n return new URL(authUrl)\n}\n\nexport function getRedirectUri() {\n const redirectUri = process.env.PROPELAUTH_REDIRECT_URI\n if (!redirectUri) {\n throw new Error('PROPELAUTH_REDIRECT_URI is not set')\n }\n return redirectUri\n}\n\nexport function getIntegrationApiKey() {\n const integrationApiKey = process.env.PROPELAUTH_API_KEY\n if (!integrationApiKey) {\n throw new Error('PROPELAUTH_API_KEY is not set')\n }\n return integrationApiKey\n}\n\nexport function getVerifierKey() {\n const verifierKey = process.env.PROPELAUTH_VERIFIER_KEY\n if (!verifierKey) {\n throw new Error('PROPELAUTH_VERIFIER_KEY is not set')\n }\n return verifierKey.replace(/\\\\n/g, '\\n')\n}\n\nexport function getSameSiteCookieValue(): \"none\" | \"lax\" | \"strict\" {\n const sameSiteOverride = process.env.PROPELAUTH_SAME_SITE_COOKIE_OVERRIDE\n if (sameSiteOverride === 'none') {\n return 'none'\n } else if (sameSiteOverride === 'lax') {\n return 'lax'\n } else if (sameSiteOverride === 'strict') {\n return 'strict'\n } else if (sameSiteOverride) {\n throw new Error(\n 'Invalid value for PROPELAUTH_SAME_SITE_COOKIE_OVERRIDE, must be one of \"none\", \"lax\", or \"strict\"'\n )\n } else {\n return 'lax'\n }\n}\n\nexport async function refreshTokenWithAccessAndRefreshToken(\n refreshToken: string,\n activeOrgId?: string\n): Promise<RefreshTokenResponse> {\n const body = {\n refresh_token: refreshToken,\n }\n\n const queryParams = new URLSearchParams()\n if (activeOrgId) {\n queryParams.set('with_active_org_support', 'true')\n queryParams.set('active_org_id', activeOrgId)\n }\n\n const url = `${getAuthUrlOrigin()}/api/backend/v1/refresh_token?${queryParams.toString()}`\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + getIntegrationApiKey(),\n },\n })\n\n if (response.ok) {\n const data = await response.json()\n const newRefreshToken = data.refresh_token\n const { access_token: accessToken, expires_at_seconds: expiresAtSeconds } = data.access_token\n\n return {\n refreshToken: newRefreshToken,\n accessToken,\n error: 'none',\n }\n } else if (response.status === 400 || response.status === 401) {\n return { error: 'unauthorized' }\n } else {\n return { error: 'unexpected' }\n }\n}\n\nexport async function validateAccessTokenOrUndefined(\n accessToken: string | undefined\n): Promise<UserFromToken | undefined> {\n try {\n return await validateAccessToken(accessToken)\n } catch (err) {\n if (err instanceof ConfigurationException) {\n throw err\n } else if (err instanceof UnauthorizedException) {\n return undefined\n } else {\n console.info('Error validating access token', err)\n return undefined\n }\n }\n}\n\nexport async function validateAccessToken(accessToken: string | undefined): Promise<UserFromToken> {\n let publicKey\n try {\n publicKey = await jose.importSPKI(getVerifierKey(), 'RS256')\n } catch (err) {\n console.error(\"Verifier key is invalid. Make sure it's specified correctly, including the newlines.\", err)\n throw new ConfigurationException('Invalid verifier key')\n }\n\n if (!accessToken) {\n throw new UnauthorizedException('No access token provided')\n }\n\n let accessTokenWithoutBearer = accessToken\n if (accessToken.toLowerCase().startsWith('bearer ')) {\n accessTokenWithoutBearer = accessToken.substring('bearer '.length)\n }\n\n try {\n const { payload } = await jose.jwtVerify(accessTokenWithoutBearer, publicKey, {\n issuer: getAuthUrlOrigin(),\n algorithms: ['RS256'],\n })\n\n return toUser(<InternalUser>payload)\n } catch (e) {\n if (e instanceof Error) {\n throw new UnauthorizedException(e.message)\n } else {\n throw new UnauthorizedException('Unable to decode jwt')\n }\n }\n}\n","import {getApis} from \"@propelauth/node-apis\";\nimport {getAuthUrl, getIntegrationApiKey} from \"./shared\";\n\nexport const getPropelAuthApis = () => {\n const authUrl = getAuthUrl()\n const integrationApiKey = getIntegrationApiKey()\n\n return getApis(authUrl, integrationApiKey)\n}","import { NextResponse } from 'next/server'\n\nexport class AuthHookResponse {\n private constructor(\n private readonly type: 'continue' | 'reject',\n private readonly response?: NextResponse\n ) {}\n\n static continue(): AuthHookResponse {\n return new AuthHookResponse('continue')\n }\n\n static reject(response: NextResponse): AuthHookResponse {\n return new AuthHookResponse('reject', response)\n }\n\n shouldContinue(): boolean {\n return this.type === 'continue'\n }\n\n getResponse(): NextResponse | undefined {\n return this.response\n }\n}\n","export const ACTIVE_ORG_ID_COOKIE_NAME = '__pa_org_id'\n","import { redirect } from 'next/navigation'\nimport { cookies, headers } from 'next/headers'\nimport { NextRequest, NextResponse } from 'next/server'\nimport {\n ACCESS_TOKEN_COOKIE_NAME,\n CALLBACK_PATH,\n COOKIE_OPTIONS,\n CUSTOM_HEADER_FOR_ACCESS_TOKEN,\n CUSTOM_HEADER_FOR_PATH,\n CUSTOM_HEADER_FOR_URL,\n getAuthUrlOrigin,\n getIntegrationApiKey,\n getRedirectUri,\n getSameSiteCookieValue,\n LOGIN_PATH,\n LOGOUT_PATH,\n REFRESH_TOKEN_COOKIE_NAME,\n refreshTokenWithAccessAndRefreshToken,\n RETURN_TO_PATH_COOKIE_NAME,\n STATE_COOKIE_NAME,\n USERINFO_PATH,\n validateAccessToken,\n validateAccessTokenOrUndefined,\n} from './shared'\nimport { UserFromToken } from './index'\nimport { ACTIVE_ORG_ID_COOKIE_NAME } from '../shared'\nimport { buildAuthMiddleware } from './middleware/advanced-middleware'\n\nexport type RedirectOptions =\n | {\n returnToPath: string\n returnToCurrentPath?: never\n }\n | {\n returnToPath?: never\n returnToCurrentPath: boolean\n }\n\nexport async function getUserOrRedirect(redirectOptions?: RedirectOptions): Promise<UserFromToken> {\n const user = await getUser()\n if (user) {\n return user\n } else {\n await redirectToLogin(redirectOptions)\n throw new Error('Redirecting to login')\n }\n}\n\nexport async function getUser(): Promise<UserFromToken | undefined> {\n const accessToken = await getAccessTokenAsync()\n if (accessToken) {\n const user = await validateAccessTokenOrUndefined(accessToken)\n if (user) {\n return user\n }\n }\n return undefined\n}\n\nexport function getAccessToken(): string | undefined {\n return headers().get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || cookies().get(ACCESS_TOKEN_COOKIE_NAME)?.value\n}\n\nexport async function getAccessTokenAsync(): Promise<string | undefined> {\n return (\n (await headers()).get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || (await cookies()).get(ACCESS_TOKEN_COOKIE_NAME)?.value\n )\n}\n\nexport async function authMiddleware(req: NextRequest): Promise<Response> {\n return buildAuthMiddleware()(req)\n}\n\nexport function getNextResponse(request: NextRequest, newAccessToken?: string) {\n const headers = new Headers(request.headers)\n headers.set(CUSTOM_HEADER_FOR_URL, request.nextUrl.toString())\n headers.set(CUSTOM_HEADER_FOR_PATH, request.nextUrl.pathname + request.nextUrl.search)\n if (newAccessToken) {\n headers.set(CUSTOM_HEADER_FOR_ACCESS_TOKEN, newAccessToken)\n }\n return NextResponse.next({\n request: {\n headers,\n },\n })\n}\n\nexport type RouteHandlerArgs = {\n postLoginRedirectPathFn?: (req: NextRequest) => string\n getDefaultActiveOrgId?: (req: NextRequest, user: UserFromToken) => string | undefined\n}\n\nexport function getRouteHandlers(args?: RouteHandlerArgs) {\n function loginGetHandler(req: NextRequest) {\n return signupOrLoginHandler(req, false)\n }\n\n function signupGetHandler(req: NextRequest) {\n return signupOrLoginHandler(req, true)\n }\n\n function signupOrLoginHandler(req: NextRequest, isSignup: boolean) {\n const returnToPath = req.nextUrl.searchParams.get('return_to_path')\n const state = randomState()\n const redirectUri = getRedirectUri()\n const sameSite = getSameSiteCookieValue()\n\n const authorizeUrlSearchParams = req.nextUrl.searchParams\n authorizeUrlSearchParams.set('redirect_uri', redirectUri)\n authorizeUrlSearchParams.set('state', state)\n authorizeUrlSearchParams.set('signup', isSignup ? 'true' : 'false')\n const authorize_url = getAuthUrlOrigin() + '/propelauth/ssr/authorize?' + authorizeUrlSearchParams.toString()\n\n const headers = new Headers()\n headers.append('Location', authorize_url)\n headers.append('Set-Cookie', `${STATE_COOKIE_NAME}=${state}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`)\n if (returnToPath) {\n if (returnToPath.startsWith('/')) {\n headers.append(\n 'Set-Cookie',\n `${RETURN_TO_PATH_COOKIE_NAME}=${returnToPath}; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=600`\n )\n } else {\n console.warn('return_to_path must start with /')\n }\n }\n\n return new Response(null, {\n status: 302,\n headers,\n })\n }\n\n async function callbackGetHandler(req: NextRequest) {\n const sameSite = getSameSiteCookieValue()\n const oauthState = req.cookies.get(STATE_COOKIE_NAME)?.value\n if (!oauthState || oauthState.length !== 64) {\n return new Response(null, { status: 302, headers: { Location: LOGIN_PATH } })\n }\n\n const queryParams = req.nextUrl.searchParams\n const state = queryParams.get('state')\n const code = queryParams.get('code')\n if (state !== oauthState) {\n return new Response(null, { status: 302, headers: { Location: LOGIN_PATH } })\n }\n\n const authUrlOrigin = getAuthUrlOrigin()\n const redirectUri = getRedirectUri()\n const integrationApiKey = getIntegrationApiKey()\n const oauth_token_body = {\n redirect_uri: redirectUri,\n code,\n }\n const url = `${authUrlOrigin}/propelauth/ssr/token`\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(oauth_token_body),\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + integrationApiKey,\n },\n })\n\n if (response.ok) {\n const data = await response.json()\n\n const accessToken = data.access_token\n\n // If we have a return_to_path cookie, we'll use that\n // Otherwise, we'll use the postLoginRedirectPathFn\n const returnToPathFromCookie = req.cookies.get(RETURN_TO_PATH_COOKIE_NAME)?.value\n const returnToPath =\n returnToPathFromCookie ?? (args?.postLoginRedirectPathFn ? args.postLoginRedirectPathFn(req) : '/')\n if (!returnToPath) {\n console.error('postLoginRedirectPathFn returned undefined')\n return new Response('Unexpected error', { status: 500 })\n }\n\n // For Active Org, if there is one set, we need to issue a new access token\n // We start by checking if there's an existing cookie AND the user is in that org\n // Otherwise, we'll use the default active org function to get the active org\n // If none of that, we'll just use the access token as is\n const currentActiveOrgId = req.cookies.get(ACTIVE_ORG_ID_COOKIE_NAME)?.value\n\n const user = await validateAccessToken(accessToken)\n const isUserInCurrentActiveOrg = !!currentActiveOrgId && !!user.getOrg(currentActiveOrgId)\n\n let activeOrgId = undefined\n if (isUserInCurrentActiveOrg) {\n activeOrgId = currentActiveOrgId\n } else if (args?.getDefaultActiveOrgId) {\n activeOrgId = args.getDefaultActiveOrgId(req, user)\n }\n\n // If there's an active org, we need to re-issue a new access token for the active org\n if (activeOrgId) {\n const response = await refreshTokenWithAccessAndRefreshToken(data.refresh_token, activeOrgId)\n if (response.error === 'unexpected') {\n throw new Error('Unexpected error while setting active org')\n } else if (response.error === 'unauthorized') {\n console.error(\n 'Unauthorized error while setting active org. Your user may not have access to this org'\n )\n return new Response('Unauthorized', { status: 401 })\n } else {\n const headers = new Headers()\n headers.append('Location', returnToPath)\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=${response.accessToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=${response.refreshToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=${activeOrgId}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append('Set-Cookie', getCookieForReturnToPathInCallback(returnToPathFromCookie))\n return new Response(null, {\n status: 302,\n headers,\n })\n }\n }\n\n const headers = new Headers()\n headers.append('Location', returnToPath)\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=${data.refresh_token}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append('Set-Cookie', getCookieForReturnToPathInCallback(returnToPathFromCookie))\n return new Response(null, {\n status: 302,\n headers,\n })\n } else if (response.status === 401) {\n const apiKey = getIntegrationApiKey()\n const firstFourChars = apiKey.substring(0, 4)\n console.error(\n `Couldn't finish the login process for this user. This is most likely caused by an incorrect PROPELAUTH_API_KEY. Your API key starts with ${firstFourChars}... double check that that matches the API key in the PropelAuth dashboard for this environment.`\n )\n return new Response('Unexpected error', { status: 500 })\n } else {\n return new Response('Unexpected error', { status: 500 })\n }\n }\n\n async function userinfoGetHandler(req: NextRequest) {\n const oldRefreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n const activeOrgId = req.cookies.get(ACTIVE_ORG_ID_COOKIE_NAME)?.value\n const sameSite = getSameSiteCookieValue()\n\n // For the userinfo endpoint, we want to get the most up-to-date info, so we'll refresh the access token\n if (oldRefreshToken) {\n const refreshResponse = await refreshTokenWithAccessAndRefreshToken(oldRefreshToken, activeOrgId)\n if (refreshResponse.error === 'unexpected') {\n throw new Error('Unexpected error while refreshing access token')\n } else if (refreshResponse.error === 'unauthorized') {\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response('Unauthorized', { status: 401, headers })\n }\n\n const refreshToken = refreshResponse.refreshToken\n const accessToken = refreshResponse.accessToken\n\n const authUrlOrigin = getAuthUrlOrigin()\n const path = `${authUrlOrigin}/propelauth/oauth/userinfo`\n const response = await fetch(path, {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + accessToken,\n },\n })\n if (response.ok) {\n const userFromToken = await validateAccessToken(accessToken)\n const data = await response.json()\n const jsonResponse = {\n userinfo: data,\n accessToken,\n impersonatorUserId: userFromToken.impersonatorUserId,\n activeOrgId,\n }\n\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=${refreshToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append('Content-Type', 'application/json')\n return new Response(JSON.stringify(jsonResponse), {\n status: 200,\n headers,\n })\n } else if (response.status === 401) {\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, {\n status: 401,\n headers,\n })\n } else {\n return new Response(null, { status: 500 })\n }\n }\n\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, { status: 401 })\n }\n\n async function logoutGetHandler(req: NextRequest) {\n // Real logout requests will go to the logout POST handler\n // This endpoint is a landing page for when people logout from the hosted UIs\n // Instead of doing a logout we'll check the refresh token.\n // If it's invalid, we'll clear the cookies and redirect using the postLoginRedirectPathFn\n const path = args?.postLoginRedirectPathFn ? args.postLoginRedirectPathFn(req) : '/'\n if (!path) {\n console.error('postLoginPathFn returned undefined')\n return new Response('Unexpected error', { status: 500 })\n }\n const sameSite = getSameSiteCookieValue()\n\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n if (!refreshToken) {\n const headers = new Headers()\n headers.append('Location', path)\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, {\n status: 302,\n headers,\n })\n }\n\n const activeOrgId = req.cookies.get(ACTIVE_ORG_ID_COOKIE_NAME)?.value\n const refreshResponse = await refreshTokenWithAccessAndRefreshToken(refreshToken, activeOrgId)\n if (refreshResponse.error === 'unexpected') {\n console.error('Unexpected error while refreshing access token')\n return new Response('Unexpected error', { status: 500 })\n } else if (refreshResponse.error === 'unauthorized') {\n const headers = new Headers()\n headers.append('Location', path)\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, {\n status: 302,\n headers,\n })\n } else {\n const headers = new Headers()\n headers.append('Location', path)\n return new Response(null, {\n status: 302,\n headers,\n })\n }\n }\n\n async function logoutPostHandler(req: NextRequest) {\n const sameSite = getSameSiteCookieValue()\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n if (!refreshToken) {\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, { status: 200, headers })\n }\n\n const authUrlOrigin = getAuthUrlOrigin()\n const integrationApiKey = getIntegrationApiKey()\n const logoutBody = { refresh_token: refreshToken }\n const url = `${authUrlOrigin}/api/backend/v1/logout`\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(logoutBody),\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + integrationApiKey,\n },\n })\n\n if (!response.ok) {\n console.warn(\n 'Unable to logout, clearing cookies and continuing anyway',\n response.status,\n response.statusText\n )\n }\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, { status: 200, headers })\n }\n\n async function setActiveOrgHandler(req: NextRequest) {\n const oldRefreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n const activeOrgId = req.nextUrl.searchParams.get('active_org_id')\n const sameSite = getSameSiteCookieValue()\n\n if (!oldRefreshToken) {\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, { status: 401, headers })\n }\n\n if (!activeOrgId) {\n return new Response(null, { status: 400 })\n }\n\n const refreshResponse = await refreshTokenWithAccessAndRefreshToken(oldRefreshToken, activeOrgId)\n if (refreshResponse.error === 'unexpected') {\n throw new Error('Unexpected error while setting active org id')\n } else if (refreshResponse.error === 'unauthorized') {\n return new Response('Unauthorized', { status: 401 })\n }\n\n const refreshToken = refreshResponse.refreshToken\n const accessToken = refreshResponse.accessToken\n\n const authUrlOrigin = getAuthUrlOrigin()\n const path = `${authUrlOrigin}/propelauth/oauth/userinfo`\n const response = await fetch(path, {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + accessToken,\n },\n })\n\n if (response.ok) {\n const userFromToken = await validateAccessToken(accessToken)\n const data = await response.json()\n const jsonResponse = {\n userinfo: data,\n accessToken,\n impersonatorUserId: userFromToken.impersonatorUserId,\n activeOrgId,\n }\n\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=${refreshToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=${activeOrgId}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append('Content-Type', 'application/json')\n return new Response(JSON.stringify(jsonResponse), {\n status: 200,\n headers,\n })\n } else if (response.status === 401) {\n return new Response(null, {\n status: 401,\n })\n } else {\n return new Response(null, { status: 500 })\n }\n }\n\n async function getRouteHandler(req: NextRequest, { params }: { params: { slug: string } }) {\n const { slug } = await params\n if (slug === 'login') {\n return loginGetHandler(req)\n } else if (slug === 'signup') {\n return signupGetHandler(req)\n } else if (slug === 'callback') {\n return callbackGetHandler(req)\n } else if (slug === 'userinfo') {\n return userinfoGetHandler(req)\n } else if (slug === 'logout') {\n return logoutGetHandler(req)\n } else {\n return new Response('', { status: 404 })\n }\n }\n\n async function postRouteHandler(req: NextRequest, { params }: { params: { slug: string } }) {\n const { slug } = await params\n if (slug === 'logout') {\n return logoutPostHandler(req)\n } else if (slug === 'set-active-org') {\n return setActiveOrgHandler(req)\n } else {\n return new Response('', { status: 404 })\n }\n }\n\n async function getRouteHandlerAsync(req: NextRequest, { params }: { params: Promise<{ slug: string }> }) {\n const awaitedParams = await params\n return getRouteHandler(req, { params: awaitedParams })\n }\n\n async function postRouteHandlerAsync(req: NextRequest, { params }: { params: Promise<{ slug: string }> }) {\n const awaitedParams = await params\n return postRouteHandler(req, { params: awaitedParams })\n }\n\n return {\n getRouteHandler,\n postRouteHandler,\n getRouteHandlerAsync,\n postRouteHandlerAsync,\n }\n}\n\nfunction randomState(): string {\n const randomBytes = crypto.getRandomValues(new Uint8Array(32))\n return Array.from(randomBytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\nasync function redirectToLogin(redirectOptions?: RedirectOptions) {\n if (!redirectOptions) {\n redirect(LOGIN_PATH)\n } else if (redirectOptions.returnToPath) {\n const loginPath = LOGIN_PATH + '?return_to_path=' + encodeURI(redirectOptions.returnToPath)\n redirect(loginPath)\n } else if (redirectOptions.returnToCurrentPath) {\n const encodedPath = await getUrlEncodedRedirectPathForCurrentPath()\n if (encodedPath) {\n const loginPath = LOGIN_PATH + '?return_to_path=' + encodedPath\n redirect(loginPath)\n } else {\n console.warn('Could not get current URL to redirect to')\n redirect(LOGIN_PATH)\n }\n }\n}\n\nexport async function getUrlEncodedRedirectPathForCurrentPath(): Promise<string | undefined> {\n const path = await getCurrentPathAsync()\n if (!path) {\n return undefined\n }\n\n return encodeURIComponent(path)\n}\n\n// We should keep the redirect path around for a short period in case multiple windows are racing\nfunction getCookieForReturnToPathInCallback(returnToPathFromCookie: string | undefined) {\n const sameSite = getSameSiteCookieValue()\n\n if (returnToPathFromCookie) {\n return `${RETURN_TO_PATH_COOKIE_NAME}=${returnToPathFromCookie}; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=15`\n } else {\n return `${RETURN_TO_PATH_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n }\n}\n\n// It's really common to want to redirect back to the exact location you are on\n// Next.js unfortunately makes this pretty hard, as server components don't have access to the path\n// The only good way to do this is to set up some middleware and pass the path down from the middleware\n// Since we have the requirement that people set up middleware with us anyway, it's easy for us to expose\n// this functionality\nexport function getCurrentPath(): string | undefined {\n const path = headers().get(CUSTOM_HEADER_FOR_PATH)\n if (!path) {\n console.warn(\n 'Attempting to redirect to the current path, but we could not find the current path in the headers. Is the middleware set up?'\n )\n return undefined\n } else {\n return path\n }\n}\n\nexport async function getCurrentPathAsync(): Promise<string | undefined> {\n const path = (await headers()).get(CUSTOM_HEADER_FOR_PATH)\n if (!path) {\n console.warn(\n 'Attempting to redirect to the current path, but we could not find the current path in the headers. Is the middleware set up?'\n )\n return undefined\n } else {\n return path\n }\n}\n\n/**\n * @deprecated since version 0.1.0\n * Use getCurrentPath instead\n */\nexport function getCurrentUrl(): string | undefined {\n console.warn('getCurrentUrl is deprecated in favor of getCurrentPath.')\n const url = headers().get(CUSTOM_HEADER_FOR_URL)\n if (!url) {\n console.warn(\n 'Attempting to redirect to the current URL, but we could not find the current URL in the headers. Is the middleware set up?'\n )\n return undefined\n } else {\n return url\n }\n}\n","import { NextRequest, NextResponse } from 'next/server'\nimport {\n ACCESS_TOKEN_COOKIE_NAME,\n CALLBACK_PATH,\n COOKIE_OPTIONS,\n LOGOUT_PATH,\n REFRESH_TOKEN_COOKIE_NAME,\n USERINFO_PATH,\n getSameSiteCookieValue,\n refreshTokenWithAccessAndRefreshToken,\n validateAccessToken,\n validateAccessTokenOrUndefined,\n} from '../shared'\nimport { ACTIVE_ORG_ID_COOKIE_NAME } from '../../shared'\nimport { getNextResponse } from '../app-router'\nimport { UserFromToken } from '../../user'\nimport { AuthHookResponse } from './auth-hook-response'\n\nexport type PropelAuthMiddlewareOptions = {\n afterAuthHook?: (req: NextRequest, res: NextResponse, user?: UserFromToken) => Promise<AuthHookResponse>\n}\n\n// Purpose of this middleware is just to keep the access token cookie alive\n// In an ideal world, this could be done in `getUser`, however, you can't\n// set a cookie in a server component.\n// There also doesn't seem to be any way right now to set a cookie in a\n// middleware and pass it forward (you can only set them on the response).\n// You CAN, however, pass in custom headers,\n// so we'll use CUSTOM_HEADER_FOR_ACCESS_TOKEN as a workaround\nexport function buildAuthMiddleware(options?: PropelAuthMiddlewareOptions): (req: NextRequest) => Promise<Response> {\n return async (req: NextRequest) => {\n if (\n req.nextUrl.pathname === CALLBACK_PATH ||\n req.nextUrl.pathname === LOGOUT_PATH ||\n req.nextUrl.pathname === USERINFO_PATH\n ) {\n // Don't do anything for the callback, logout, or userinfo paths, as they will modify the cookies themselves\n return getNextResponse(req)\n }\n\n const accessToken = req.cookies.get(ACCESS_TOKEN_COOKIE_NAME)?.value\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n const activeOrgId = req.cookies.get(ACTIVE_ORG_ID_COOKIE_NAME)?.value\n\n // If we are authenticated, we can continue\n if (accessToken) {\n const user = await validateAccessTokenOrUndefined(accessToken)\n if (user) {\n const nextResponse = getNextResponse(req)\n return await handlePostAuthHook(req, nextResponse, user, options)\n }\n }\n\n // Otherwise, we need to refresh the access token\n if (refreshToken) {\n const response = await refreshTokenWithAccessAndRefreshToken(refreshToken, activeOrgId)\n if (response.error === 'unexpected') {\n throw new Error('Unexpected error while refreshing access token')\n } else if (response.error === 'unauthorized') {\n const response = getNextResponse(req)\n response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME)\n response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME)\n return await handlePostAuthHook(req, response, undefined, options)\n } else {\n const sameSite = getSameSiteCookieValue()\n const nextResponse = getNextResponse(req, response.accessToken)\n nextResponse.cookies.set(ACCESS_TOKEN_COOKIE_NAME, response.accessToken, {\n ...COOKIE_OPTIONS,\n sameSite,\n })\n nextResponse.cookies.set(REFRESH_TOKEN_COOKIE_NAME, response.refreshToken, {\n ...COOKIE_OPTIONS,\n sameSite,\n })\n const user = await validateAccessToken(response.accessToken)\n return await handlePostAuthHook(req, nextResponse, user, options)\n }\n }\n\n const res = getNextResponse(req)\n return await handlePostAuthHook(req, res, undefined, options)\n }\n}\n\nconst handlePostAuthHook = async (\n req: NextRequest,\n res: NextResponse,\n user?: UserFromToken,\n options?: PropelAuthMiddlewareOptions\n): Promise<NextResponse> => {\n if (options?.afterAuthHook) {\n const hookResponse = await options.afterAuthHook(req, res, user)\n if (hookResponse instanceof AuthHookResponse) {\n if (!hookResponse.shouldContinue()) {\n return hookResponse.getResponse() ?? res\n }\n } else {\n console.warn('afterAuthHook did not return a AuthHookResponse, continuing')\n }\n }\n return res\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgHO,SAAS,cAAc,YAA+C;AACzE,MAAI,CAAC,YAAY;AACb,WAAO,EAAE,aAAa,UAAU;AAAA,EACpC;AAEA,UAAQ,WAAW,cAAc;AAAA,IAC7B,KAAK;AACD,aAAO,EAAE,aAAa,WAAW;AAAA,IACrC,KAAK;AACD,aAAO,EAAE,aAAa,aAAa;AAAA,IACvC,KAAK;AACD,aAAO,EAAE,aAAa,cAAc,UAAU,WAAW,SAAS;AAAA,IACtE,KAAK;AACD,aAAO,EAAE,aAAa,0BAA0B;AAAA,IACpD,KAAK;AACD,aAAO,EAAE,aAAa,YAAY,UAAU,WAAW,UAAU,OAAO,WAAW,OAAO;AAAA,IAC9F,KAAK;AACD,aAAO,EAAE,aAAa,gBAAgB;AAAA,IAC1C,KAAK;AACD,aAAO,EAAE,aAAa,6BAA6B;AAAA,IACvD;AACI,aAAO,EAAE,aAAa,UAAU;AAAA,EACxC;AACJ;;;ACrIO,IAAM,gBAAN,MAAoB;AAAA,EAmBvB,YACI,QACA,OACA,sBACA,WACA,UACA,UACA,cACA,oBACA,YACA,aACA,aACF;AACE,SAAK,SAAS;AAEd,SAAK,cAAc;AACnB,SAAK,uBAAuB;AAE5B,SAAK,QAAQ;AACb,SAAK,YAAY;AACjB,SAAK,WAAW;AAChB,SAAK,WAAW;AAEhB,SAAK,eAAe;AACpB,SAAK,qBAAqB;AAE1B,SAAK,aAAa;AAClB,SAAK,cAAc;AAAA,EACvB;AAAA,EAEO,eAA0C;AAC7C,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,sBAAsB;AACjD,aAAO;AAAA,IACX;AAEA,WAAO,KAAK,qBAAqB,KAAK,WAAW;AAAA,EACrD;AAAA,EAEO,iBAAqC;AACxC,WAAO,KAAK;AAAA,EAChB;AAAA,EAEO,OAAO,OAA0C;AACpD,QAAI,CAAC,KAAK,sBAAsB;AAC5B,aAAO;AAAA,IACX;AAEA,WAAO,KAAK,qBAAqB,KAAK;AAAA,EAC1C;AAAA,EAEO,aAAa,SAA4C;AAC5D,QAAI,CAAC,KAAK,sBAAsB;AAC5B,aAAO;AAAA,IACX;AAEA,UAAM,iBAAiB,QAAQ,YAAY,EAAE,QAAQ,MAAM,GAAG;AAC9D,eAAW,SAAS,KAAK,sBAAsB;AAC3C,YAAM,gBAAgB,KAAK,qBAAqB,KAAK;AACrD,UAAI,cAAc,mBAAmB,gBAAgB;AACjD,eAAO;AAAA,MACX;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEO,UAA2B;AAC9B,QAAI,CAAC,KAAK,sBAAsB;AAC5B,aAAO,CAAC;AAAA,IACZ;AAEA,WAAO,OAAO,OAAO,KAAK,oBAAoB;AAAA,EAClD;AAAA,EAEO,kBAA2B;AAC9B,WAAO,CAAC,CAAC,KAAK;AAAA,EAClB;AAAA,EAEA,OAAc,SAAS,MAA6B;AAChD,UAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,UAAM,uBAA6C,CAAC;AACpD,eAAW,SAAS,IAAI,sBAAsB;AAC1C,2BAAqB,KAAK,IAAI,cAAc,SAAS,KAAK,UAAU,IAAI,qBAAqB,KAAK,CAAC,CAAC;AAAA,IACxG;AACA,WAAO,IAAI;AAAA,MACP,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ;AAAA,MACA,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACR;AAAA,EACJ;AAAA,EAEA,OAAc,eAAe,SAAsC;AAC/D,QAAI;AACJ,QAAI;AAEJ,QAAI,QAAQ,iBAAiB;AACzB,oBAAc,QAAQ,gBAAgB;AACtC,6BAAuB,uBAAuB,EAAE,CAAC,WAAW,GAAG,QAAQ,gBAAgB,CAAC;AAAA,IAC5F,OAAO;AACH,oBAAc;AACd,6BAAuB,uBAAuB,QAAQ,yBAAyB;AAAA,IACnF;AAEA,UAAM,cAAc,cAAc,QAAQ,YAAY;AAEtD,WAAO,IAAI;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AACJ;AAWO,IAAM,gBAAN,MAAoB;AAAA,EAYvB,YACI,OACA,SACA,aACA,gBACA,kBACA,mCACA,iBACA,kBACA,6BACF;AACE,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,cAAc;AACnB,SAAK,iBAAiB;AACtB,SAAK,mBAAmB;AAExB,SAAK,mBAAmB;AACxB,SAAK,oCAAoC;AACzC,SAAK,kBAAkB;AACvB,SAAK,8BAA8B;AAAA,EACvC;AAAA;AAAA,EAIO,OAAO,MAAuB;AACjC,QAAI,KAAK,qBAAqB,8BAA4B;AACtD,aAAO,KAAK,qBAAqB,QAAQ,KAAK,4BAA4B,SAAS,IAAI;AAAA,IAC3F,OAAO;AACH,aAAO,KAAK,qBAAqB;AAAA,IACrC;AAAA,EACJ;AAAA,EAEO,cAAc,MAAuB;AACxC,QAAI,KAAK,qBAAqB,8BAA4B;AACtD,aAAO,KAAK,qBAAqB,QAAQ,KAAK,4BAA4B,SAAS,IAAI;AAAA,IAC3F,OAAO;AACH,aAAO,KAAK,kCAAkC,SAAS,IAAI;AAAA,IAC/D;AAAA,EACJ;AAAA,EAEO,cAAc,YAA6B;AAC9C,WAAO,KAAK,gBAAgB,SAAS,UAAU;AAAA,EACnD;AAAA,EAEO,kBAAkB,aAAgC;AACrD,WAAO,YAAY,MAAM,CAAC,eAAe,KAAK,cAAc,UAAU,CAAC;AAAA,EAC3E;AAAA,EAEA,OAAc,SAAS,MAA6B;AAChD,UAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,WAAO,IAAI;AAAA,MACP,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACR;AAAA,EACJ;AAAA;AAAA,EAIA,IAAI,eAAuB;AACvB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,gBAA0B;AAC1B,QAAI,KAAK,qBAAqB,8BAA4B;AACtD,aAAO,KAAK,4BAA4B,OAAO,KAAK,gBAAgB;AAAA,IACxE,OAAO;AACH,aAAO,CAAC,KAAK,gBAAgB;AAAA,IACjC;AAAA,EACJ;AAAA,EAEA,IAAI,gCAA0C;AAC1C,QAAI,KAAK,qBAAqB,8BAA4B;AACtD,aAAO,KAAK,4BAA4B,OAAO,KAAK,gBAAgB;AAAA,IACxE,OAAO;AACH,aAAO,KAAK;AAAA,IAChB;AAAA,EACJ;AAAA,EAEA,IAAI,cAAwB;AACxB,WAAO,KAAK;AAAA,EAChB;AACJ;AAkCO,SAAS,OAAO,YAAyC;AAC5D,SAAO,cAAc,eAAe,UAAU;AAClD;AAEO,SAAS,uBAAuB,YAEF;AACjC,MAAI,eAAe,QAAW;AAC1B,WAAO;AAAA,EACX;AACA,QAAM,YAAkC,CAAC;AAEzC,aAAW,OAAO,OAAO,KAAK,UAAU,GAAG;AACvC,UAAM,iBAAiB,WAAW,GAAG;AACrC,QAAI,gBAAgB;AAChB,gBAAU,GAAG,IAAI,IAAI;AAAA,QACjB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,MACnB;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX;;;ACpUO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAI7C,YAAY,SAAiB;AACzB,UAAM,OAAO;AACb,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,EAClB;AACJ;AAEO,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAI9C,YAAY,SAAiB;AACzB,UAAM,OAAO;AACb,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,EAClB;AACJ;;;ACjBA,WAAsB;AAsBf,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AACtB,IAAM,cAAc;AACpB,IAAM,2BAA2B;AACjC,IAAM,4BAA4B;AAElC,IAAM,iCAAiC;AACvC,IAAM,wBAAwB;AAC9B,IAAM,yBAAyB;AAG/B,IAAM,iBAA0C;AAAA,EACnD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAM;AACV;AAEO,SAAS,mBAAmB;AAC/B,SAAO,WAAW,EAAE;AACxB;AAEO,SAAS,aAAa;AACzB,QAAM,UAAU,QAAQ,IAAI,uBAAuB,QAAQ,IAAI;AAC/D,MAAI,CAAC,SAAS;AACV,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACrD;AACA,SAAO,IAAI,IAAI,OAAO;AAC1B;AAUO,SAAS,uBAAuB;AACnC,QAAM,oBAAoB,QAAQ,IAAI;AACtC,MAAI,CAAC,mBAAmB;AACpB,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACnD;AACA,SAAO;AACX;AAEO,SAAS,iBAAiB;AAC7B,QAAM,cAAc,QAAQ,IAAI;AAChC,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACxD;AACA,SAAO,YAAY,QAAQ,QAAQ,IAAI;AAC3C;AAEO,SAAS,yBAAoD;AAChE,QAAM,mBAAmB,QAAQ,IAAI;AACrC,MAAI,qBAAqB,QAAQ;AAC7B,WAAO;AAAA,EACX,WAAW,qBAAqB,OAAO;AACnC,WAAO;AAAA,EACX,WAAW,qBAAqB,UAAU;AACtC,WAAO;AAAA,EACX,WAAW,kBAAkB;AACzB,UAAM,IAAI;AAAA,MACN;AAAA,IACJ;AAAA,EACJ,OAAO;AACH,WAAO;AAAA,EACX;AACJ;AAEA,SAAsB,sCAClB,cACA,aAC6B;AAAA;AAC7B,UAAM,OAAO;AAAA,MACT,eAAe;AAAA,IACnB;AAEA,UAAM,cAAc,IAAI,gBAAgB;AACxC,QAAI,aAAa;AACb,kBAAY,IAAI,2BAA2B,MAAM;AACjD,kBAAY,IAAI,iBAAiB,WAAW;AAAA,IAChD;AAEA,UAAM,MAAM,GAAG,iBAAiB,kCAAkC,YAAY,SAAS;AACvF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAC9B,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,SAAS;AAAA,QACL,gBAAgB;AAAA,QAChB,eAAe,YAAY,qBAAqB;AAAA,MACpD;AAAA,IACJ,CAAC;AAED,QAAI,SAAS,IAAI;AACb,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,kBAAkB,KAAK;AAC7B,YAAM,EAAE,cAAc,aAAa,oBAAoB,iBAAiB,IAAI,KAAK;AAEjF,aAAO;AAAA,QACH,cAAc;AAAA,QACd;AAAA,QACA,OAAO;AAAA,MACX;AAAA,IACJ,WAAW,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AAC3D,aAAO,EAAE,OAAO,eAAe;AAAA,IACnC,OAAO;AACH,aAAO,EAAE,OAAO,aAAa;AAAA,IACjC;AAAA,EACJ;AAAA;AAEA,SAAsB,+BAClB,aACkC;AAAA;AAClC,QAAI;AACA,aAAO,MAAM,oBAAoB,WAAW;AAAA,IAChD,SAAS,KAAP;AACE,UAAI,eAAe,wBAAwB;AACvC,cAAM;AAAA,MACV,WAAW,eAAe,uBAAuB;AAC7C,eAAO;AAAA,MACX,OAAO;AACH,gBAAQ,KAAK,iCAAiC,GAAG;AACjD,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ;AAAA;AAEA,SAAsB,oBAAoB,aAAyD;AAAA;AAC/F,QAAI;AACJ,QAAI;AACA,kBAAY,MAAW,gBAAW,eAAe,GAAG,OAAO;AAAA,IAC/D,SAAS,KAAP;AACE,cAAQ,MAAM,wFAAwF,GAAG;AACzG,YAAM,IAAI,uBAAuB,sBAAsB;AAAA,IAC3D;AAEA,QAAI,CAAC,aAAa;AACd,YAAM,IAAI,sBAAsB,0BAA0B;AAAA,IAC9D;AAEA,QAAI,2BAA2B;AAC/B,QAAI,YAAY,YAAY,EAAE,WAAW,SAAS,GAAG;AACjD,iCAA2B,YAAY,UAAU,UAAU,MAAM;AAAA,IACrE;AAEA,QAAI;AACA,YAAM,EAAE,QAAQ,IAAI,MAAW,eAAU,0BAA0B,WAAW;AAAA,QAC1E,QAAQ,iBAAiB;AAAA,QACzB,YAAY,CAAC,OAAO;AAAA,MACxB,CAAC;AAED,aAAO,OAAqB,OAAO;AAAA,IACvC,SAAS,GAAP;AACE,UAAI,aAAa,OAAO;AACpB,cAAM,IAAI,sBAAsB,EAAE,OAAO;AAAA,MAC7C,OAAO;AACH,cAAM,IAAI,sBAAsB,sBAAsB;AAAA,MAC1D;AAAA,IACJ;AAAA,EACJ;AAAA;;;ACzLA,uBAAsB;AAGf,IAAM,oBAAoB,MAAM;AACnC,QAAM,UAAU,WAAW;AAC3B,QAAM,oBAAoB,qBAAqB;AAE/C,aAAO,0BAAQ,SAAS,iBAAiB;AAC7C;;;ACNO,IAAM,mBAAN,MAAuB;AAAA,EAClB,YACa,MACA,UACnB;AAFmB;AACA;AAAA,EAClB;AAAA,EAEH,OAAO,WAA6B;AAChC,WAAO,IAAI,iBAAiB,UAAU;AAAA,EAC1C;AAAA,EAEA,OAAO,OAAO,UAA0C;AACpD,WAAO,IAAI,iBAAiB,UAAU,QAAQ;AAAA,EAClD;AAAA,EAEA,iBAA0B;AACtB,WAAO,KAAK,SAAS;AAAA,EACzB;AAAA,EAEA,cAAwC;AACpC,WAAO,KAAK;AAAA,EAChB;AACJ;;;ACvBO,IAAM,4BAA4B;;;ACAzC,wBAAyB;AACzB,qBAAiC;AACjC,oBAA0C;AAuEnC,SAAS,gBAAgB,SAAsB,gBAAyB;AAC3E,QAAMA,WAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,EAAAA,SAAQ,IAAI,uBAAuB,QAAQ,QAAQ,SAAS,CAAC;AAC7D,EAAAA,SAAQ,IAAI,wBAAwB,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,MAAM;AACrF,MAAI,gBAAgB;AAChB,IAAAA,SAAQ,IAAI,gCAAgC,cAAc;AAAA,EAC9D;AACA,SAAO,2BAAa,KAAK;AAAA,IACrB,SAAS;AAAA,MACL,SAAAA;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;;;ACxDO,SAAS,oBAAoB,SAAgF;AAChH,SAAO,CAAO,QAAqB;AA9BvC;AA+BQ,QACI,IAAI,QAAQ,aAAa,iBACzB,IAAI,QAAQ,aAAa,eACzB,IAAI,QAAQ,aAAa,eAC3B;AAEE,aAAO,gBAAgB,GAAG;AAAA,IAC9B;AAEA,UAAM,eAAc,SAAI,QAAQ,IAAI,wBAAwB,MAAxC,mBAA2C;AAC/D,UAAM,gBAAe,SAAI,QAAQ,IAAI,yBAAyB,MAAzC,mBAA4C;AACjE,UAAM,eAAc,SAAI,QAAQ,IAAI,yBAAyB,MAAzC,mBAA4C;AAGhE,QAAI,aAAa;AACb,YAAM,OAAO,MAAM,+BAA+B,WAAW;AAC7D,UAAI,MAAM;AACN,cAAM,eAAe,gBAAgB,GAAG;AACxC,eAAO,MAAM,mBAAmB,KAAK,cAAc,MAAM,OAAO;AAAA,MACpE;AAAA,IACJ;AAGA,QAAI,cAAc;AACd,YAAM,WAAW,MAAM,sCAAsC,cAAc,WAAW;AACtF,UAAI,SAAS,UAAU,cAAc;AACjC,cAAM,IAAI,MAAM,gDAAgD;AAAA,MACpE,WAAW,SAAS,UAAU,gBAAgB;AAC1C,cAAMC,YAAW,gBAAgB,GAAG;AACpC,QAAAA,UAAS,QAAQ,OAAO,wBAAwB;AAChD,QAAAA,UAAS,QAAQ,OAAO,yBAAyB;AACjD,eAAO,MAAM,mBAAmB,KAAKA,WAAU,QAAW,OAAO;AAAA,MACrE,OAAO;AACH,cAAM,WAAW,uBAAuB;AACxC,cAAM,eAAe,gBAAgB,KAAK,SAAS,WAAW;AAC9D,qBAAa,QAAQ,IAAI,0BAA0B,SAAS,aAAa,iCAClE,iBADkE;AAAA,UAErE;AAAA,QACJ,EAAC;AACD,qBAAa,QAAQ,IAAI,2BAA2B,SAAS,cAAc,iCACpE,iBADoE;AAAA,UAEvE;AAAA,QACJ,EAAC;AACD,cAAM,OAAO,MAAM,oBAAoB,SAAS,WAAW;AAC3D,eAAO,MAAM,mBAAmB,KAAK,cAAc,MAAM,OAAO;AAAA,MACpE;AAAA,IACJ;AAEA,UAAM,MAAM,gBAAgB,GAAG;AAC/B,WAAO,MAAM,mBAAmB,KAAK,KAAK,QAAW,OAAO;AAAA,EAChE;AACJ;AAEA,IAAM,qBAAqB,CACvB,KACA,KACA,MACA,YACwB;AAzF5B;AA0FI,MAAI,mCAAS,eAAe;AACxB,UAAM,eAAe,MAAM,QAAQ,cAAc,KAAK,KAAK,IAAI;AAC/D,QAAI,wBAAwB,kBAAkB;AAC1C,UAAI,CAAC,aAAa,eAAe,GAAG;AAChC,gBAAO,kBAAa,YAAY,MAAzB,YAA8B;AAAA,MACzC;AAAA,IACJ,OAAO;AACH,cAAQ,KAAK,6DAA6D;AAAA,IAC9E;AAAA,EACJ;AACA,SAAO;AACX;","names":["headers","response"]}
1
+ {"version":3,"sources":["../../src/server/index.ts","../../src/loginMethod.ts","../../src/user.ts","../../src/server/exceptions.ts","../../src/server/shared.ts","../../src/server/api.ts","../../src/server/middleware/auth-hook-response.ts","../../src/shared.ts","../../src/server/app-router.ts","../../src/server/middleware/advanced-middleware.ts"],"sourcesContent":["export { validateAccessToken, validateAccessTokenOrUndefined } from './shared'\nexport type { OrgIdToOrgMemberInfo } from '../user'\nexport { UserFromToken, OrgMemberInfo } from '../user'\nexport { UnauthorizedException, ConfigurationException } from './exceptions'\nexport { getPropelAuthApis } from './api'\nexport { AuthHookResponse } from './middleware/auth-hook-response'\nexport { buildAuthMiddleware } from './middleware/advanced-middleware'\nexport type { PropelAuthMiddlewareOptions } from './middleware/advanced-middleware'\nexport type {\n AccessToken,\n AccessTokenCreationException,\n AddUserToOrgException,\n AddUserToOrgRequest,\n ApiKeyCreateException,\n ApiKeyDeleteException,\n ApiKeyFetchException,\n ApiKeyFull,\n ApiKeyNew,\n ApiKeyResultPage,\n ApiKeyUpdateException,\n ApiKeyUpdateRequest,\n ApiKeyValidateException,\n ApiKeyValidateRateLimitedException,\n ApiKeyValidation,\n ApiKeysCreateRequest,\n ApiKeysQueryRequest,\n ChangeUserRoleInOrgException,\n CreateAccessTokenRequest,\n CreateMagicLinkRequest,\n CreateOrgException,\n CreateOrgRequest,\n CreateUserException,\n CreateUserRequest,\n ForbiddenException,\n MagicLink,\n MagicLinkCreationException,\n MigrateUserException,\n MigrateUserFromExternalSourceRequest,\n MigrateUserPasswordException,\n MigrateUserPasswordRequest,\n Org,\n Organization,\n OrgApiKeyValidation,\n OrgQuery,\n OrgQueryResponse,\n PersonalApiKeyValidation,\n RateLimitedException,\n RemoveUserFromOrgException,\n RemoveUserFromOrgRequest,\n TokenVerificationMetadata,\n UnexpectedException,\n UpdateOrgException,\n UpdateOrgRequest,\n UpdateUserEmailException,\n UpdateUserEmailRequest,\n UpdateUserMetadataException,\n UpdateUserMetadataRequest,\n UpdateUserPasswordException,\n UpdateUserPasswordRequest,\n UserNotFoundException,\n UserInOrgMetadata,\n UsersInOrgQuery,\n UsersPagedResponse,\n UsersInOrgPagedResponse,\n UsersQuery,\n FetchPendingInvitesParams,\n PendingInvitesPage,\n PendingInvite,\n RevokePendingOrgInviteRequest,\n FetchSamlSpMetadataResponse,\n SetSamlIdpMetadataRequest,\n IdpProvider,\n} from '@propelauth/node-apis'\n","export enum SocialLoginProvider {\n Google = 'Google',\n GitHub = 'GitHub',\n Microsoft = 'Microsoft',\n Slack = 'Slack',\n LinkedIn = 'LinkedIn',\n Salesforce = 'Salesforce',\n Xero = 'Xero',\n QuickBooksOnline = 'QuickBooks Online',\n}\n\nexport enum SamlLoginProvider {\n Google = 'Google',\n Rippling = 'Rippling',\n OneLogin = 'OneLogin',\n JumpCloud = 'JumpCloud',\n Okta = 'Okta',\n Azure = 'Azure',\n Duo = 'Duo',\n Generic = 'Generic',\n}\n\ntype InternalPasswordLoginMethod = {\n login_method: 'password'\n}\n\ntype InternalMagicLinkLoginMethod = {\n login_method: 'magic_link'\n}\n\ntype InternalSocialSsoLoginMethod = {\n login_method: 'social_sso'\n provider: SocialLoginProvider\n}\n\ntype InternalEmailConfirmationLinkLoginMethod = {\n login_method: 'email_confirmation_link'\n}\n\ntype InternalSamlSsoLoginMethod = {\n login_method: 'saml_sso'\n provider: SamlLoginProvider\n org_id: string\n}\n\ntype InternalImpersonationLoginMethod = {\n login_method: 'impersonation'\n}\n\ntype InternalGeneratedFromBackendApiLoginMethod = {\n login_method: 'generated_from_backend_api'\n}\n\ntype InternalUnknownLoginMethod = {\n login_method: 'unknown'\n}\n\nexport type InternalLoginMethod =\n | InternalPasswordLoginMethod\n | InternalMagicLinkLoginMethod\n | InternalSocialSsoLoginMethod\n | InternalEmailConfirmationLinkLoginMethod\n | InternalSamlSsoLoginMethod\n | InternalImpersonationLoginMethod\n | InternalGeneratedFromBackendApiLoginMethod\n | InternalUnknownLoginMethod\n\ntype PasswordLoginMethod = {\n loginMethod: 'password'\n}\n\ntype MagicLinkLoginMethod = {\n loginMethod: 'magic_link'\n}\n\ntype SocialSsoLoginMethod = {\n loginMethod: 'social_sso'\n provider: SocialLoginProvider\n}\n\ntype EmailConfirmationLinkLoginMethod = {\n loginMethod: 'email_confirmation_link'\n}\n\ntype SamlSsoLoginMethod = {\n loginMethod: 'saml_sso'\n provider: SamlLoginProvider\n orgId: string\n}\n\ntype ImpersonationLoginMethod = {\n loginMethod: 'impersonation'\n}\n\ntype GeneratedFromBackendApiLoginMethod = {\n loginMethod: 'generated_from_backend_api'\n}\n\ntype UnknownLoginMethod = {\n loginMethod: 'unknown'\n}\n\nexport type LoginMethod =\n | PasswordLoginMethod\n | MagicLinkLoginMethod\n | SocialSsoLoginMethod\n | EmailConfirmationLinkLoginMethod\n | SamlSsoLoginMethod\n | ImpersonationLoginMethod\n | GeneratedFromBackendApiLoginMethod\n | UnknownLoginMethod\n\nexport function toLoginMethod(snake_case?: InternalLoginMethod): LoginMethod {\n if (!snake_case) {\n return { loginMethod: 'unknown' }\n }\n\n switch (snake_case.login_method) {\n case 'password':\n return { loginMethod: 'password' }\n case 'magic_link':\n return { loginMethod: 'magic_link' }\n case 'social_sso':\n return { loginMethod: 'social_sso', provider: snake_case.provider }\n case 'email_confirmation_link':\n return { loginMethod: 'email_confirmation_link' }\n case 'saml_sso':\n return { loginMethod: 'saml_sso', provider: snake_case.provider, orgId: snake_case.org_id }\n case 'impersonation':\n return { loginMethod: 'impersonation' }\n case 'generated_from_backend_api':\n return { loginMethod: 'generated_from_backend_api' }\n default:\n return { loginMethod: 'unknown' }\n }\n}\n","import { InternalLoginMethod, LoginMethod, toLoginMethod } from './loginMethod'\n\nexport class UserFromToken {\n public userId: string\n\n public activeOrgId?: string\n public orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo\n\n // Metadata about the user\n public email: string\n public firstName?: string\n public lastName?: string\n public username?: string\n public properties?: { [key: string]: unknown }\n public loginMethod?: LoginMethod\n\n // If you used our migration APIs to migrate this user from a different system,\n // this is their original ID from that system.\n public legacyUserId?: string\n public impersonatorUserId?: string\n\n constructor(\n userId: string,\n email: string,\n orgIdToOrgMemberInfo?: OrgIdToOrgMemberInfo,\n firstName?: string,\n lastName?: string,\n username?: string,\n legacyUserId?: string,\n impersonatorUserId?: string,\n properties?: { [key: string]: unknown },\n activeOrgId?: string,\n loginMethod?: LoginMethod\n ) {\n this.userId = userId\n\n this.activeOrgId = activeOrgId\n this.orgIdToOrgMemberInfo = orgIdToOrgMemberInfo\n\n this.email = email\n this.firstName = firstName\n this.lastName = lastName\n this.username = username\n\n this.legacyUserId = legacyUserId\n this.impersonatorUserId = impersonatorUserId\n\n this.properties = properties\n this.loginMethod = loginMethod\n }\n\n public getActiveOrg(): OrgMemberInfo | undefined {\n if (!this.activeOrgId || !this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n return this.orgIdToOrgMemberInfo[this.activeOrgId]\n }\n\n public getActiveOrgId(): string | undefined {\n return this.activeOrgId\n }\n\n public getOrg(orgId: string): OrgMemberInfo | undefined {\n if (!this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n return this.orgIdToOrgMemberInfo[orgId]\n }\n\n public getOrgByName(orgName: string): OrgMemberInfo | undefined {\n if (!this.orgIdToOrgMemberInfo) {\n return undefined\n }\n\n const urlSafeOrgName = orgName.toLowerCase().replace(/ /g, '-')\n for (const orgId in this.orgIdToOrgMemberInfo) {\n const orgMemberInfo = this.orgIdToOrgMemberInfo[orgId]\n if (orgMemberInfo.urlSafeOrgName === urlSafeOrgName) {\n return orgMemberInfo\n }\n }\n\n return undefined\n }\n\n public getOrgs(): OrgMemberInfo[] {\n if (!this.orgIdToOrgMemberInfo) {\n return []\n }\n\n return Object.values(this.orgIdToOrgMemberInfo)\n }\n\n public isImpersonating(): boolean {\n return !!this.impersonatorUserId\n }\n\n public static fromJSON(json: string): UserFromToken {\n const obj = JSON.parse(json)\n const orgIdToOrgMemberInfo: OrgIdToOrgMemberInfo = {}\n for (const orgId in obj.orgIdToOrgMemberInfo) {\n orgIdToOrgMemberInfo[orgId] = OrgMemberInfo.fromJSON(JSON.stringify(obj.orgIdToOrgMemberInfo[orgId]))\n }\n return new UserFromToken(\n obj.userId,\n obj.email,\n orgIdToOrgMemberInfo,\n obj.firstName,\n obj.lastName,\n obj.username,\n obj.legacyUserId,\n obj.impersonatorUserId,\n obj.properties,\n obj.activeOrgId,\n obj.loginMethod\n )\n }\n\n public static fromJwtPayload(payload: InternalUser): UserFromToken {\n let activeOrgId: string | undefined\n let orgIdToOrgMemberInfo: OrgIdToOrgMemberInfo | undefined\n\n if (payload.org_member_info) {\n activeOrgId = payload.org_member_info.org_id\n orgIdToOrgMemberInfo = toOrgIdToOrgMemberInfo({ [activeOrgId]: payload.org_member_info })\n } else {\n activeOrgId = undefined\n orgIdToOrgMemberInfo = toOrgIdToOrgMemberInfo(payload.org_id_to_org_member_info)\n }\n\n const loginMethod = toLoginMethod(payload.login_method)\n\n return new UserFromToken(\n payload.user_id,\n payload.email,\n orgIdToOrgMemberInfo,\n payload.first_name,\n payload.last_name,\n payload.username,\n payload.legacy_user_id,\n payload.impersonator_user_id,\n payload.properties,\n activeOrgId,\n loginMethod\n )\n }\n}\n\nexport type OrgIdToOrgMemberInfo = {\n [orgId: string]: OrgMemberInfo\n}\n\nexport enum OrgRoleStructure {\n SingleRole = \"single_role_in_hierarchy\",\n MultiRole = \"multi_role\",\n}\n\nexport class OrgMemberInfo {\n public orgId: string\n public orgName: string\n public orgMetadata: { [key: string]: any }\n public urlSafeOrgName: string\n public orgRoleStructure: OrgRoleStructure\n\n public userAssignedRole: string\n public userInheritedRolesPlusCurrentRole: string[]\n public userPermissions: string[]\n public userAssignedAdditionalRoles: string[]\n\n constructor(\n orgId: string,\n orgName: string,\n orgMetadata: { [key: string]: any },\n urlSafeOrgName: string,\n userAssignedRole: string,\n userInheritedRolesPlusCurrentRole: string[],\n userPermissions: string[],\n orgRoleStructure: OrgRoleStructure,\n userAssignedAdditionalRoles: string[]\n ) {\n this.orgId = orgId\n this.orgName = orgName\n this.orgMetadata = orgMetadata\n this.urlSafeOrgName = urlSafeOrgName\n this.orgRoleStructure = orgRoleStructure\n\n this.userAssignedRole = userAssignedRole\n this.userInheritedRolesPlusCurrentRole = userInheritedRolesPlusCurrentRole\n this.userPermissions = userPermissions\n this.userAssignedAdditionalRoles = userAssignedAdditionalRoles\n }\n\n // validation methods\n\n public isRole(role: string): boolean {\n if (this.orgRoleStructure === OrgRoleStructure.MultiRole) {\n return this.userAssignedRole === role || this.userAssignedAdditionalRoles.includes(role)\n } else {\n return this.userAssignedRole === role\n }\n }\n\n public isAtLeastRole(role: string): boolean {\n if (this.orgRoleStructure === OrgRoleStructure.MultiRole) {\n return this.userAssignedRole === role || this.userAssignedAdditionalRoles.includes(role)\n } else {\n return this.userInheritedRolesPlusCurrentRole.includes(role)\n }\n }\n\n public hasPermission(permission: string): boolean {\n return this.userPermissions.includes(permission)\n }\n\n public hasAllPermissions(permissions: string[]): boolean {\n return permissions.every((permission) => this.hasPermission(permission))\n }\n\n public static fromJSON(json: string): OrgMemberInfo {\n const obj = JSON.parse(json)\n return new OrgMemberInfo(\n obj.orgId,\n obj.orgName,\n obj.orgMetadata,\n obj.urlSafeOrgName,\n obj.userAssignedRole,\n obj.userInheritedRolesPlusCurrentRole,\n obj.userPermissions,\n obj.orgRoleStructure,\n obj.userAssignedAdditionalRoles\n )\n }\n\n // getters for the private fields\n\n get assignedRole(): string {\n return this.userAssignedRole\n }\n\n get assignedRoles(): string[] {\n if (this.orgRoleStructure === OrgRoleStructure.MultiRole) {\n return this.userAssignedAdditionalRoles.concat(this.userAssignedRole)\n } else {\n return [this.userAssignedRole]\n }\n }\n\n get inheritedRolesPlusCurrentRole(): string[] {\n if (this.orgRoleStructure === OrgRoleStructure.MultiRole) {\n return this.userAssignedAdditionalRoles.concat(this.userAssignedRole)\n } else {\n return this.userInheritedRolesPlusCurrentRole\n }\n }\n\n get permissions(): string[] {\n return this.userPermissions\n }\n}\n\n// These Internal types exist since the server returns snake case, but typescript/javascript\n// convention is camelCase.\nexport type InternalOrgMemberInfo = {\n org_id: string\n org_name: string\n org_metadata: { [key: string]: any }\n url_safe_org_name: string\n org_role_structure: OrgRoleStructure\n user_role: string\n inherited_user_roles_plus_current_role: string[]\n user_permissions: string[]\n additional_roles: string[]\n}\n\nexport type InternalUser = {\n user_id: string\n\n org_member_info?: InternalOrgMemberInfo\n org_id_to_org_member_info?: { [org_id: string]: InternalOrgMemberInfo }\n\n email: string\n first_name?: string\n last_name?: string\n username?: string\n properties?: { [key: string]: unknown }\n login_method?: InternalLoginMethod\n\n // If you used our migration APIs to migrate this user from a different system, this is their original ID from that system.\n legacy_user_id?: string\n impersonator_user_id?: string\n}\n\nexport function toUser(snake_case: InternalUser): UserFromToken {\n return UserFromToken.fromJwtPayload(snake_case)\n}\n\nexport function toOrgIdToOrgMemberInfo(snake_case?: {\n [org_id: string]: InternalOrgMemberInfo\n}): OrgIdToOrgMemberInfo | undefined {\n if (snake_case === undefined) {\n return undefined\n }\n const camelCase: OrgIdToOrgMemberInfo = {}\n\n for (const key of Object.keys(snake_case)) {\n const snakeCaseValue = snake_case[key]\n if (snakeCaseValue) {\n camelCase[key] = new OrgMemberInfo(\n snakeCaseValue.org_id,\n snakeCaseValue.org_name,\n snakeCaseValue.org_metadata,\n snakeCaseValue.url_safe_org_name,\n snakeCaseValue.user_role,\n snakeCaseValue.inherited_user_roles_plus_current_role,\n snakeCaseValue.user_permissions,\n snakeCaseValue.org_role_structure,\n snakeCaseValue.additional_roles\n )\n }\n }\n\n return camelCase\n}\n","export class UnauthorizedException extends Error {\n readonly message: string\n readonly status: number\n\n constructor(message: string) {\n super(message)\n this.message = message\n this.status = 401\n }\n}\n\nexport class ConfigurationException extends Error {\n readonly message: string\n readonly status: number\n\n constructor(message: string) {\n super(message)\n this.message = message\n this.status = 500\n }\n}\n","import { ResponseCookie } from 'next/dist/compiled/@edge-runtime/cookies'\nimport { InternalUser, toUser, UserFromToken } from '../user'\nimport { ConfigurationException, UnauthorizedException } from './exceptions'\nimport * as jose from 'jose'\n\ntype RefreshAndAccessTokens = {\n refreshToken: string\n accessToken: string\n error: 'none'\n}\n\ntype RefreshAndAccessTokensUnauthorizedError = {\n error: 'unauthorized'\n}\n\ntype RefreshAndAccessTokensUnexpectedError = {\n error: 'unexpected'\n}\n\nexport type RefreshTokenResponse =\n | RefreshAndAccessTokens\n | RefreshAndAccessTokensUnauthorizedError\n | RefreshAndAccessTokensUnexpectedError\n\nexport const LOGIN_PATH = '/api/auth/login'\nexport const CALLBACK_PATH = '/api/auth/callback'\nexport const USERINFO_PATH = '/api/auth/userinfo'\nexport const LOGOUT_PATH = '/api/auth/logout'\nexport const ACCESS_TOKEN_COOKIE_NAME = '__pa_at'\nexport const REFRESH_TOKEN_COOKIE_NAME = '__pa_rt'\nexport const STATE_COOKIE_NAME = '__pa_state'\nexport const CUSTOM_HEADER_FOR_ACCESS_TOKEN = 'x-propelauth-access-token'\nexport const CUSTOM_HEADER_FOR_URL = 'x-propelauth-current-url'\nexport const CUSTOM_HEADER_FOR_PATH = 'x-propelauth-current-path'\nexport const RETURN_TO_PATH_COOKIE_NAME = '__pa_return_to_path'\n\nexport const COOKIE_OPTIONS: Partial<ResponseCookie> = {\n httpOnly: true,\n secure: true,\n path: '/',\n}\n\nexport function getAuthUrlOrigin() {\n return getAuthUrl().origin\n}\n\nexport function getAuthUrl() {\n const authUrl = process.env.PROPELAUTH_AUTH_URL || process.env.NEXT_PUBLIC_AUTH_URL\n if (!authUrl) {\n throw new Error('NEXT_PUBLIC_AUTH_URL is not set')\n }\n return new URL(authUrl)\n}\n\nexport function getRedirectUri() {\n const redirectUri = process.env.PROPELAUTH_REDIRECT_URI\n if (!redirectUri) {\n throw new Error('PROPELAUTH_REDIRECT_URI is not set')\n }\n return redirectUri\n}\n\nexport function getIntegrationApiKey() {\n const integrationApiKey = process.env.PROPELAUTH_API_KEY\n if (!integrationApiKey) {\n throw new Error('PROPELAUTH_API_KEY is not set')\n }\n return integrationApiKey\n}\n\nexport function getVerifierKey() {\n const verifierKey = process.env.PROPELAUTH_VERIFIER_KEY\n if (!verifierKey) {\n throw new Error('PROPELAUTH_VERIFIER_KEY is not set')\n }\n return verifierKey.replace(/\\\\n/g, '\\n')\n}\n\nexport function getSameSiteCookieValue(): \"none\" | \"lax\" | \"strict\" {\n const sameSiteOverride = process.env.PROPELAUTH_SAME_SITE_COOKIE_OVERRIDE\n if (sameSiteOverride === 'none') {\n return 'none'\n } else if (sameSiteOverride === 'lax') {\n return 'lax'\n } else if (sameSiteOverride === 'strict') {\n return 'strict'\n } else if (sameSiteOverride) {\n throw new Error(\n 'Invalid value for PROPELAUTH_SAME_SITE_COOKIE_OVERRIDE, must be one of \"none\", \"lax\", or \"strict\"'\n )\n } else {\n return 'lax'\n }\n}\n\nexport async function refreshTokenWithAccessAndRefreshToken(\n refreshToken: string,\n activeOrgId?: string\n): Promise<RefreshTokenResponse> {\n const body = {\n refresh_token: refreshToken,\n }\n\n const queryParams = new URLSearchParams()\n if (activeOrgId) {\n queryParams.set('with_active_org_support', 'true')\n queryParams.set('active_org_id', activeOrgId)\n }\n\n const url = `${getAuthUrlOrigin()}/api/backend/v1/refresh_token?${queryParams.toString()}`\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + getIntegrationApiKey(),\n },\n })\n\n if (response.ok) {\n const data = await response.json()\n const newRefreshToken = data.refresh_token\n const { access_token: accessToken, expires_at_seconds: expiresAtSeconds } = data.access_token\n\n return {\n refreshToken: newRefreshToken,\n accessToken,\n error: 'none',\n }\n } else if (response.status === 400 || response.status === 401) {\n return { error: 'unauthorized' }\n } else {\n return { error: 'unexpected' }\n }\n}\n\nexport async function validateAccessTokenOrUndefined(\n accessToken: string | undefined\n): Promise<UserFromToken | undefined> {\n try {\n return await validateAccessToken(accessToken)\n } catch (err) {\n if (err instanceof ConfigurationException) {\n throw err\n } else if (err instanceof UnauthorizedException) {\n return undefined\n } else {\n console.info('Error validating access token', err)\n return undefined\n }\n }\n}\n\nexport async function validateAccessToken(accessToken: string | undefined): Promise<UserFromToken> {\n let publicKey\n try {\n publicKey = await jose.importSPKI(getVerifierKey(), 'RS256')\n } catch (err) {\n console.error(\"Verifier key is invalid. Make sure it's specified correctly, including the newlines.\", err)\n throw new ConfigurationException('Invalid verifier key')\n }\n\n if (!accessToken) {\n throw new UnauthorizedException('No access token provided')\n }\n\n let accessTokenWithoutBearer = accessToken\n if (accessToken.toLowerCase().startsWith('bearer ')) {\n accessTokenWithoutBearer = accessToken.substring('bearer '.length)\n }\n\n try {\n const { payload } = await jose.jwtVerify(accessTokenWithoutBearer, publicKey, {\n issuer: getAuthUrlOrigin(),\n algorithms: ['RS256'],\n })\n\n return toUser(<InternalUser>payload)\n } catch (e) {\n if (e instanceof Error) {\n throw new UnauthorizedException(e.message)\n } else {\n throw new UnauthorizedException('Unable to decode jwt')\n }\n }\n}\n","import {getApis} from \"@propelauth/node-apis\";\nimport {getAuthUrl, getIntegrationApiKey} from \"./shared\";\n\nexport const getPropelAuthApis = () => {\n const authUrl = getAuthUrl()\n const integrationApiKey = getIntegrationApiKey()\n\n return getApis(authUrl, integrationApiKey)\n}","import { NextResponse } from 'next/server'\n\nexport class AuthHookResponse {\n private constructor(\n private readonly type: 'continue' | 'reject',\n private readonly response?: NextResponse\n ) {}\n\n static continue(): AuthHookResponse {\n return new AuthHookResponse('continue')\n }\n\n static reject(response: NextResponse): AuthHookResponse {\n return new AuthHookResponse('reject', response)\n }\n\n shouldContinue(): boolean {\n return this.type === 'continue'\n }\n\n getResponse(): NextResponse | undefined {\n return this.response\n }\n}\n","export const ACTIVE_ORG_ID_COOKIE_NAME = '__pa_org_id'\n","import { redirect } from 'next/navigation'\nimport { cookies, headers } from 'next/headers'\nimport { NextRequest, NextResponse } from 'next/server'\nimport {\n ACCESS_TOKEN_COOKIE_NAME,\n CALLBACK_PATH,\n COOKIE_OPTIONS,\n CUSTOM_HEADER_FOR_ACCESS_TOKEN,\n CUSTOM_HEADER_FOR_PATH,\n CUSTOM_HEADER_FOR_URL,\n getAuthUrlOrigin,\n getIntegrationApiKey,\n getRedirectUri,\n getSameSiteCookieValue,\n LOGIN_PATH,\n LOGOUT_PATH,\n REFRESH_TOKEN_COOKIE_NAME,\n refreshTokenWithAccessAndRefreshToken,\n RETURN_TO_PATH_COOKIE_NAME,\n STATE_COOKIE_NAME,\n USERINFO_PATH,\n validateAccessToken,\n validateAccessTokenOrUndefined,\n} from './shared'\nimport { UserFromToken } from './index'\nimport { ACTIVE_ORG_ID_COOKIE_NAME } from '../shared'\nimport { buildAuthMiddleware } from './middleware/advanced-middleware'\n\nexport type RedirectOptions =\n | {\n returnToPath: string\n returnToCurrentPath?: never\n }\n | {\n returnToPath?: never\n returnToCurrentPath: boolean\n }\n\nexport async function getUserOrRedirect(redirectOptions?: RedirectOptions): Promise<UserFromToken> {\n const user = await getUser()\n if (user) {\n return user\n } else {\n await redirectToLogin(redirectOptions)\n throw new Error('Redirecting to login')\n }\n}\n\nexport async function getUser(): Promise<UserFromToken | undefined> {\n const accessToken = await getAccessTokenAsync()\n if (accessToken) {\n const user = await validateAccessTokenOrUndefined(accessToken)\n if (user) {\n return user\n }\n }\n return undefined\n}\n\nexport function getAccessToken(): string | undefined {\n return headers().get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || cookies().get(ACCESS_TOKEN_COOKIE_NAME)?.value\n}\n\nexport async function getAccessTokenAsync(): Promise<string | undefined> {\n return (\n (await headers()).get(CUSTOM_HEADER_FOR_ACCESS_TOKEN) || (await cookies()).get(ACCESS_TOKEN_COOKIE_NAME)?.value\n )\n}\n\nexport async function authMiddleware(req: NextRequest): Promise<Response> {\n return buildAuthMiddleware()(req)\n}\n\nexport function getNextResponse(request: NextRequest, newAccessToken?: string) {\n const headers = new Headers(request.headers)\n headers.set(CUSTOM_HEADER_FOR_URL, request.nextUrl.toString())\n headers.set(CUSTOM_HEADER_FOR_PATH, request.nextUrl.pathname + request.nextUrl.search)\n if (newAccessToken) {\n headers.set(CUSTOM_HEADER_FOR_ACCESS_TOKEN, newAccessToken)\n }\n return NextResponse.next({\n request: {\n headers,\n },\n })\n}\n\nexport type RouteHandlerArgs = {\n postLoginRedirectPathFn?: (req: NextRequest) => string\n getDefaultActiveOrgId?: (req: NextRequest, user: UserFromToken) => string | undefined\n}\n\nexport function getRouteHandlers(args?: RouteHandlerArgs) {\n function loginGetHandler(req: NextRequest) {\n return signupOrLoginHandler(req, false)\n }\n\n function signupGetHandler(req: NextRequest) {\n return signupOrLoginHandler(req, true)\n }\n\n function signupOrLoginHandler(req: NextRequest, isSignup: boolean) {\n const returnToPath = req.nextUrl.searchParams.get('return_to_path')\n const state = randomState()\n const redirectUri = getRedirectUri()\n const sameSite = getSameSiteCookieValue()\n\n const authorizeUrlSearchParams = req.nextUrl.searchParams\n authorizeUrlSearchParams.set('redirect_uri', redirectUri)\n authorizeUrlSearchParams.set('state', state)\n authorizeUrlSearchParams.set('signup', isSignup ? 'true' : 'false')\n const authorize_url = getAuthUrlOrigin() + '/propelauth/ssr/authorize?' + authorizeUrlSearchParams.toString()\n\n const headers = new Headers()\n headers.append('Location', authorize_url)\n headers.append('Set-Cookie', `${STATE_COOKIE_NAME}=${state}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`)\n if (returnToPath) {\n if (returnToPath.startsWith('/')) {\n headers.append(\n 'Set-Cookie',\n `${RETURN_TO_PATH_COOKIE_NAME}=${returnToPath}; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=600`\n )\n } else {\n console.warn('return_to_path must start with /')\n }\n }\n\n return new Response(null, {\n status: 302,\n headers,\n })\n }\n\n async function callbackGetHandler(req: NextRequest) {\n const sameSite = getSameSiteCookieValue()\n const oauthState = req.cookies.get(STATE_COOKIE_NAME)?.value\n if (!oauthState || oauthState.length !== 64) {\n return new Response(null, { status: 302, headers: { Location: LOGIN_PATH } })\n }\n\n const queryParams = req.nextUrl.searchParams\n const state = queryParams.get('state')\n const code = queryParams.get('code')\n if (state !== oauthState) {\n return new Response(null, { status: 302, headers: { Location: LOGIN_PATH } })\n }\n\n const authUrlOrigin = getAuthUrlOrigin()\n const redirectUri = getRedirectUri()\n const integrationApiKey = getIntegrationApiKey()\n const oauth_token_body = {\n redirect_uri: redirectUri,\n code,\n }\n const url = `${authUrlOrigin}/propelauth/ssr/token`\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(oauth_token_body),\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + integrationApiKey,\n },\n })\n\n if (response.ok) {\n const data = await response.json()\n\n const accessToken = data.access_token\n\n // If we have a return_to_path cookie, we'll use that\n // Otherwise, we'll use the postLoginRedirectPathFn\n const returnToPathFromCookie = req.cookies.get(RETURN_TO_PATH_COOKIE_NAME)?.value\n const returnToPath =\n returnToPathFromCookie ?? (args?.postLoginRedirectPathFn ? args.postLoginRedirectPathFn(req) : '/')\n if (!returnToPath) {\n console.error('postLoginRedirectPathFn returned undefined')\n return new Response('Unexpected error', { status: 500 })\n }\n\n // For Active Org, if there is one set, we need to issue a new access token\n // We start by checking if there's an existing cookie AND the user is in that org\n // Otherwise, we'll use the default active org function to get the active org\n // If none of that, we'll just use the access token as is\n const currentActiveOrgId = req.cookies.get(ACTIVE_ORG_ID_COOKIE_NAME)?.value\n\n const user = await validateAccessToken(accessToken)\n const isUserInCurrentActiveOrg = !!currentActiveOrgId && !!user.getOrg(currentActiveOrgId)\n\n let activeOrgId = undefined\n if (isUserInCurrentActiveOrg) {\n activeOrgId = currentActiveOrgId\n } else if (args?.getDefaultActiveOrgId) {\n activeOrgId = args.getDefaultActiveOrgId(req, user)\n }\n\n // If there's an active org, we need to re-issue a new access token for the active org\n if (activeOrgId) {\n const response = await refreshTokenWithAccessAndRefreshToken(data.refresh_token, activeOrgId)\n if (response.error === 'unexpected') {\n throw new Error('Unexpected error while setting active org')\n } else if (response.error === 'unauthorized') {\n console.error(\n 'Unauthorized error while setting active org. Your user may not have access to this org'\n )\n return new Response('Unauthorized', { status: 401 })\n } else {\n const headers = new Headers()\n headers.append('Location', returnToPath)\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=${response.accessToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=${response.refreshToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=${activeOrgId}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append('Set-Cookie', getCookieForReturnToPathInCallback(returnToPathFromCookie))\n return new Response(null, {\n status: 302,\n headers,\n })\n }\n }\n\n const headers = new Headers()\n headers.append('Location', returnToPath)\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=${data.refresh_token}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append('Set-Cookie', getCookieForReturnToPathInCallback(returnToPathFromCookie))\n return new Response(null, {\n status: 302,\n headers,\n })\n } else if (response.status === 401) {\n const apiKey = getIntegrationApiKey()\n const firstFourChars = apiKey.substring(0, 4)\n console.error(\n `Couldn't finish the login process for this user. This is most likely caused by an incorrect PROPELAUTH_API_KEY. Your API key starts with ${firstFourChars}... double check that that matches the API key in the PropelAuth dashboard for this environment.`\n )\n return new Response('Unexpected error', { status: 500 })\n } else {\n return new Response('Unexpected error', { status: 500 })\n }\n }\n\n async function userinfoGetHandler(req: NextRequest) {\n const oldRefreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n const activeOrgId = req.cookies.get(ACTIVE_ORG_ID_COOKIE_NAME)?.value\n const sameSite = getSameSiteCookieValue()\n\n // For the userinfo endpoint, we want to get the most up-to-date info, so we'll refresh the access token\n if (oldRefreshToken) {\n const refreshResponse = await refreshTokenWithAccessAndRefreshToken(oldRefreshToken, activeOrgId)\n if (refreshResponse.error === 'unexpected') {\n throw new Error('Unexpected error while refreshing access token')\n } else if (refreshResponse.error === 'unauthorized') {\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response('Unauthorized', { status: 401, headers })\n }\n\n const refreshToken = refreshResponse.refreshToken\n const accessToken = refreshResponse.accessToken\n\n const authUrlOrigin = getAuthUrlOrigin()\n const path = `${authUrlOrigin}/propelauth/oauth/userinfo`\n const response = await fetch(path, {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + accessToken,\n },\n })\n if (response.ok) {\n const userFromToken = await validateAccessToken(accessToken)\n const data = await response.json()\n const jsonResponse = {\n userinfo: data,\n accessToken,\n impersonatorUserId: userFromToken.impersonatorUserId,\n activeOrgId,\n }\n\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=${refreshToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append('Content-Type', 'application/json')\n return new Response(JSON.stringify(jsonResponse), {\n status: 200,\n headers,\n })\n } else if (response.status === 401) {\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, {\n status: 401,\n headers,\n })\n } else {\n return new Response(null, { status: 500 })\n }\n }\n\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, { status: 401 })\n }\n\n async function logoutGetHandler(req: NextRequest) {\n // Real logout requests will go to the logout POST handler\n // This endpoint is a landing page for when people logout from the hosted UIs\n // Instead of doing a logout we'll check the refresh token.\n // If it's invalid, we'll clear the cookies and redirect using the postLoginRedirectPathFn\n const path = args?.postLoginRedirectPathFn ? args.postLoginRedirectPathFn(req) : '/'\n if (!path) {\n console.error('postLoginPathFn returned undefined')\n return new Response('Unexpected error', { status: 500 })\n }\n const sameSite = getSameSiteCookieValue()\n\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n if (!refreshToken) {\n const headers = new Headers()\n headers.append('Location', path)\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, {\n status: 302,\n headers,\n })\n }\n\n const activeOrgId = req.cookies.get(ACTIVE_ORG_ID_COOKIE_NAME)?.value\n const refreshResponse = await refreshTokenWithAccessAndRefreshToken(refreshToken, activeOrgId)\n if (refreshResponse.error === 'unexpected') {\n console.error('Unexpected error while refreshing access token')\n return new Response('Unexpected error', { status: 500 })\n } else if (refreshResponse.error === 'unauthorized') {\n const headers = new Headers()\n headers.append('Location', path)\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, {\n status: 302,\n headers,\n })\n } else {\n const headers = new Headers()\n headers.append('Location', path)\n return new Response(null, {\n status: 302,\n headers,\n })\n }\n }\n\n async function logoutPostHandler(req: NextRequest) {\n const sameSite = getSameSiteCookieValue()\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n if (!refreshToken) {\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, { status: 200, headers })\n }\n\n const authUrlOrigin = getAuthUrlOrigin()\n const integrationApiKey = getIntegrationApiKey()\n const logoutBody = { refresh_token: refreshToken }\n const url = `${authUrlOrigin}/api/backend/v1/logout`\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify(logoutBody),\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + integrationApiKey,\n },\n })\n\n if (!response.ok) {\n console.warn(\n 'Unable to logout, clearing cookies and continuing anyway',\n response.status,\n response.statusText\n )\n }\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, { status: 200, headers })\n }\n\n async function setActiveOrgHandler(req: NextRequest) {\n const oldRefreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n const activeOrgId = req.nextUrl.searchParams.get('active_org_id')\n const sameSite = getSameSiteCookieValue()\n\n if (!oldRefreshToken) {\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n )\n return new Response(null, { status: 401, headers })\n }\n\n if (!activeOrgId) {\n return new Response(null, { status: 400 })\n }\n\n const refreshResponse = await refreshTokenWithAccessAndRefreshToken(oldRefreshToken, activeOrgId)\n if (refreshResponse.error === 'unexpected') {\n throw new Error('Unexpected error while setting active org id')\n } else if (refreshResponse.error === 'unauthorized') {\n return new Response('Unauthorized', { status: 401 })\n }\n\n const refreshToken = refreshResponse.refreshToken\n const accessToken = refreshResponse.accessToken\n\n const authUrlOrigin = getAuthUrlOrigin()\n const path = `${authUrlOrigin}/propelauth/oauth/userinfo`\n const response = await fetch(path, {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: 'Bearer ' + accessToken,\n },\n })\n\n if (response.ok) {\n const userFromToken = await validateAccessToken(accessToken)\n const data = await response.json()\n const jsonResponse = {\n userinfo: data,\n accessToken,\n impersonatorUserId: userFromToken.impersonatorUserId,\n activeOrgId,\n }\n\n const headers = new Headers()\n headers.append(\n 'Set-Cookie',\n `${ACCESS_TOKEN_COOKIE_NAME}=${accessToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${REFRESH_TOKEN_COOKIE_NAME}=${refreshToken}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append(\n 'Set-Cookie',\n `${ACTIVE_ORG_ID_COOKIE_NAME}=${activeOrgId}; Path=/; HttpOnly; Secure; SameSite=${sameSite}`\n )\n headers.append('Content-Type', 'application/json')\n return new Response(JSON.stringify(jsonResponse), {\n status: 200,\n headers,\n })\n } else if (response.status === 401) {\n return new Response(null, {\n status: 401,\n })\n } else {\n return new Response(null, { status: 500 })\n }\n }\n\n async function getRouteHandler(req: NextRequest, { params }: { params: { slug: string } }) {\n const { slug } = await params\n if (slug === 'login') {\n return loginGetHandler(req)\n } else if (slug === 'signup') {\n return signupGetHandler(req)\n } else if (slug === 'callback') {\n return callbackGetHandler(req)\n } else if (slug === 'userinfo') {\n return userinfoGetHandler(req)\n } else if (slug === 'logout') {\n return logoutGetHandler(req)\n } else {\n return new Response('', { status: 404 })\n }\n }\n\n async function postRouteHandler(req: NextRequest, { params }: { params: { slug: string } }) {\n const { slug } = await params\n if (slug === 'logout') {\n return logoutPostHandler(req)\n } else if (slug === 'set-active-org') {\n return setActiveOrgHandler(req)\n } else {\n return new Response('', { status: 404 })\n }\n }\n\n async function getRouteHandlerAsync(req: NextRequest, { params }: { params: Promise<{ slug: string }> }) {\n const awaitedParams = await params\n return getRouteHandler(req, { params: awaitedParams })\n }\n\n async function postRouteHandlerAsync(req: NextRequest, { params }: { params: Promise<{ slug: string }> }) {\n const awaitedParams = await params\n return postRouteHandler(req, { params: awaitedParams })\n }\n\n return {\n getRouteHandler,\n postRouteHandler,\n getRouteHandlerAsync,\n postRouteHandlerAsync,\n }\n}\n\nfunction randomState(): string {\n const randomBytes = crypto.getRandomValues(new Uint8Array(32))\n return Array.from(randomBytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\nasync function redirectToLogin(redirectOptions?: RedirectOptions) {\n if (!redirectOptions) {\n redirect(LOGIN_PATH)\n } else if (redirectOptions.returnToPath) {\n const loginPath = LOGIN_PATH + '?return_to_path=' + encodeURI(redirectOptions.returnToPath)\n redirect(loginPath)\n } else if (redirectOptions.returnToCurrentPath) {\n const encodedPath = await getUrlEncodedRedirectPathForCurrentPath()\n if (encodedPath) {\n const loginPath = LOGIN_PATH + '?return_to_path=' + encodedPath\n redirect(loginPath)\n } else {\n console.warn('Could not get current URL to redirect to')\n redirect(LOGIN_PATH)\n }\n }\n}\n\nexport async function getUrlEncodedRedirectPathForCurrentPath(): Promise<string | undefined> {\n const path = await getCurrentPathAsync()\n if (!path) {\n return undefined\n }\n\n return encodeURIComponent(path)\n}\n\n// We should keep the redirect path around for a short period in case multiple windows are racing\nfunction getCookieForReturnToPathInCallback(returnToPathFromCookie: string | undefined) {\n const sameSite = getSameSiteCookieValue()\n\n if (returnToPathFromCookie) {\n return `${RETURN_TO_PATH_COOKIE_NAME}=${returnToPathFromCookie}; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=15`\n } else {\n return `${RETURN_TO_PATH_COOKIE_NAME}=; Path=/; HttpOnly; Secure; SameSite=${sameSite}; Max-Age=0`\n }\n}\n\n// It's really common to want to redirect back to the exact location you are on\n// Next.js unfortunately makes this pretty hard, as server components don't have access to the path\n// The only good way to do this is to set up some middleware and pass the path down from the middleware\n// Since we have the requirement that people set up middleware with us anyway, it's easy for us to expose\n// this functionality\nexport function getCurrentPath(): string | undefined {\n const path = headers().get(CUSTOM_HEADER_FOR_PATH)\n if (!path) {\n console.warn(\n 'Attempting to redirect to the current path, but we could not find the current path in the headers. Is the middleware set up?'\n )\n return undefined\n } else {\n return path\n }\n}\n\nexport async function getCurrentPathAsync(): Promise<string | undefined> {\n const path = (await headers()).get(CUSTOM_HEADER_FOR_PATH)\n if (!path) {\n console.warn(\n 'Attempting to redirect to the current path, but we could not find the current path in the headers. Is the middleware set up?'\n )\n return undefined\n } else {\n return path\n }\n}\n\n/**\n * @deprecated since version 0.1.0\n * Use getCurrentPath instead\n */\nexport function getCurrentUrl(): string | undefined {\n console.warn('getCurrentUrl is deprecated in favor of getCurrentPath.')\n const url = headers().get(CUSTOM_HEADER_FOR_URL)\n if (!url) {\n console.warn(\n 'Attempting to redirect to the current URL, but we could not find the current URL in the headers. Is the middleware set up?'\n )\n return undefined\n } else {\n return url\n }\n}\n","import { NextRequest, NextResponse } from 'next/server'\nimport {\n ACCESS_TOKEN_COOKIE_NAME,\n CALLBACK_PATH,\n COOKIE_OPTIONS,\n LOGOUT_PATH,\n REFRESH_TOKEN_COOKIE_NAME,\n USERINFO_PATH,\n getSameSiteCookieValue,\n refreshTokenWithAccessAndRefreshToken,\n validateAccessToken,\n validateAccessTokenOrUndefined,\n} from '../shared'\nimport { ACTIVE_ORG_ID_COOKIE_NAME } from '../../shared'\nimport { getNextResponse } from '../app-router'\nimport { UserFromToken } from '../../user'\nimport { AuthHookResponse } from './auth-hook-response'\n\nexport type PropelAuthMiddlewareOptions = {\n afterAuthHook?: (req: NextRequest, res: NextResponse, user?: UserFromToken) => Promise<AuthHookResponse>\n}\n\n// Purpose of this middleware is just to keep the access token cookie alive\n// In an ideal world, this could be done in `getUser`, however, you can't\n// set a cookie in a server component.\n// There also doesn't seem to be any way right now to set a cookie in a\n// middleware and pass it forward (you can only set them on the response).\n// You CAN, however, pass in custom headers,\n// so we'll use CUSTOM_HEADER_FOR_ACCESS_TOKEN as a workaround\nexport function buildAuthMiddleware(options?: PropelAuthMiddlewareOptions): (req: NextRequest) => Promise<Response> {\n return async (req: NextRequest) => {\n if (\n req.nextUrl.pathname === CALLBACK_PATH ||\n req.nextUrl.pathname === LOGOUT_PATH ||\n req.nextUrl.pathname === USERINFO_PATH\n ) {\n // Don't do anything for the callback, logout, or userinfo paths, as they will modify the cookies themselves\n return getNextResponse(req)\n }\n\n const accessToken = req.cookies.get(ACCESS_TOKEN_COOKIE_NAME)?.value\n const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value\n const activeOrgId = req.cookies.get(ACTIVE_ORG_ID_COOKIE_NAME)?.value\n\n // If we are authenticated, we can continue\n if (accessToken) {\n const user = await validateAccessTokenOrUndefined(accessToken)\n if (user) {\n const nextResponse = getNextResponse(req)\n return await handlePostAuthHook(req, nextResponse, user, options)\n }\n }\n\n // Otherwise, we need to refresh the access token\n if (refreshToken) {\n const response = await refreshTokenWithAccessAndRefreshToken(refreshToken, activeOrgId)\n if (response.error === 'unexpected') {\n throw new Error('Unexpected error while refreshing access token')\n } else if (response.error === 'unauthorized') {\n const response = getNextResponse(req)\n response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME)\n response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME)\n return await handlePostAuthHook(req, response, undefined, options)\n } else {\n const sameSite = getSameSiteCookieValue()\n const nextResponse = getNextResponse(req, response.accessToken)\n nextResponse.cookies.set(ACCESS_TOKEN_COOKIE_NAME, response.accessToken, {\n ...COOKIE_OPTIONS,\n sameSite,\n })\n nextResponse.cookies.set(REFRESH_TOKEN_COOKIE_NAME, response.refreshToken, {\n ...COOKIE_OPTIONS,\n sameSite,\n })\n const user = await validateAccessToken(response.accessToken)\n return await handlePostAuthHook(req, nextResponse, user, options)\n }\n }\n\n const res = getNextResponse(req)\n return await handlePostAuthHook(req, res, undefined, options)\n }\n}\n\nconst handlePostAuthHook = async (\n req: NextRequest,\n res: NextResponse,\n user?: UserFromToken,\n options?: PropelAuthMiddlewareOptions\n): Promise<NextResponse> => {\n if (options?.afterAuthHook) {\n const hookResponse = await options.afterAuthHook(req, res, user)\n if (hookResponse instanceof AuthHookResponse) {\n if (!hookResponse.shouldContinue()) {\n return hookResponse.getResponse() ?? res\n }\n } else {\n console.warn('afterAuthHook did not return a AuthHookResponse, continuing')\n }\n }\n return res\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgHO,SAAS,cAAc,YAA+C;AACzE,MAAI,CAAC,YAAY;AACb,WAAO,EAAE,aAAa,UAAU;AAAA,EACpC;AAEA,UAAQ,WAAW,cAAc;AAAA,IAC7B,KAAK;AACD,aAAO,EAAE,aAAa,WAAW;AAAA,IACrC,KAAK;AACD,aAAO,EAAE,aAAa,aAAa;AAAA,IACvC,KAAK;AACD,aAAO,EAAE,aAAa,cAAc,UAAU,WAAW,SAAS;AAAA,IACtE,KAAK;AACD,aAAO,EAAE,aAAa,0BAA0B;AAAA,IACpD,KAAK;AACD,aAAO,EAAE,aAAa,YAAY,UAAU,WAAW,UAAU,OAAO,WAAW,OAAO;AAAA,IAC9F,KAAK;AACD,aAAO,EAAE,aAAa,gBAAgB;AAAA,IAC1C,KAAK;AACD,aAAO,EAAE,aAAa,6BAA6B;AAAA,IACvD;AACI,aAAO,EAAE,aAAa,UAAU;AAAA,EACxC;AACJ;;;ACrIO,IAAM,gBAAN,MAAoB;AAAA,EAmBvB,YACI,QACA,OACA,sBACA,WACA,UACA,UACA,cACA,oBACA,YACA,aACA,aACF;AACE,SAAK,SAAS;AAEd,SAAK,cAAc;AACnB,SAAK,uBAAuB;AAE5B,SAAK,QAAQ;AACb,SAAK,YAAY;AACjB,SAAK,WAAW;AAChB,SAAK,WAAW;AAEhB,SAAK,eAAe;AACpB,SAAK,qBAAqB;AAE1B,SAAK,aAAa;AAClB,SAAK,cAAc;AAAA,EACvB;AAAA,EAEO,eAA0C;AAC7C,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,sBAAsB;AACjD,aAAO;AAAA,IACX;AAEA,WAAO,KAAK,qBAAqB,KAAK,WAAW;AAAA,EACrD;AAAA,EAEO,iBAAqC;AACxC,WAAO,KAAK;AAAA,EAChB;AAAA,EAEO,OAAO,OAA0C;AACpD,QAAI,CAAC,KAAK,sBAAsB;AAC5B,aAAO;AAAA,IACX;AAEA,WAAO,KAAK,qBAAqB,KAAK;AAAA,EAC1C;AAAA,EAEO,aAAa,SAA4C;AAC5D,QAAI,CAAC,KAAK,sBAAsB;AAC5B,aAAO;AAAA,IACX;AAEA,UAAM,iBAAiB,QAAQ,YAAY,EAAE,QAAQ,MAAM,GAAG;AAC9D,eAAW,SAAS,KAAK,sBAAsB;AAC3C,YAAM,gBAAgB,KAAK,qBAAqB,KAAK;AACrD,UAAI,cAAc,mBAAmB,gBAAgB;AACjD,eAAO;AAAA,MACX;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEO,UAA2B;AAC9B,QAAI,CAAC,KAAK,sBAAsB;AAC5B,aAAO,CAAC;AAAA,IACZ;AAEA,WAAO,OAAO,OAAO,KAAK,oBAAoB;AAAA,EAClD;AAAA,EAEO,kBAA2B;AAC9B,WAAO,CAAC,CAAC,KAAK;AAAA,EAClB;AAAA,EAEA,OAAc,SAAS,MAA6B;AAChD,UAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,UAAM,uBAA6C,CAAC;AACpD,eAAW,SAAS,IAAI,sBAAsB;AAC1C,2BAAqB,KAAK,IAAI,cAAc,SAAS,KAAK,UAAU,IAAI,qBAAqB,KAAK,CAAC,CAAC;AAAA,IACxG;AACA,WAAO,IAAI;AAAA,MACP,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ;AAAA,MACA,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACR;AAAA,EACJ;AAAA,EAEA,OAAc,eAAe,SAAsC;AAC/D,QAAI;AACJ,QAAI;AAEJ,QAAI,QAAQ,iBAAiB;AACzB,oBAAc,QAAQ,gBAAgB;AACtC,6BAAuB,uBAAuB,EAAE,CAAC,WAAW,GAAG,QAAQ,gBAAgB,CAAC;AAAA,IAC5F,OAAO;AACH,oBAAc;AACd,6BAAuB,uBAAuB,QAAQ,yBAAyB;AAAA,IACnF;AAEA,UAAM,cAAc,cAAc,QAAQ,YAAY;AAEtD,WAAO,IAAI;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AACJ;AAWO,IAAM,gBAAN,MAAoB;AAAA,EAYvB,YACI,OACA,SACA,aACA,gBACA,kBACA,mCACA,iBACA,kBACA,6BACF;AACE,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,cAAc;AACnB,SAAK,iBAAiB;AACtB,SAAK,mBAAmB;AAExB,SAAK,mBAAmB;AACxB,SAAK,oCAAoC;AACzC,SAAK,kBAAkB;AACvB,SAAK,8BAA8B;AAAA,EACvC;AAAA;AAAA,EAIO,OAAO,MAAuB;AACjC,QAAI,KAAK,qBAAqB,8BAA4B;AACtD,aAAO,KAAK,qBAAqB,QAAQ,KAAK,4BAA4B,SAAS,IAAI;AAAA,IAC3F,OAAO;AACH,aAAO,KAAK,qBAAqB;AAAA,IACrC;AAAA,EACJ;AAAA,EAEO,cAAc,MAAuB;AACxC,QAAI,KAAK,qBAAqB,8BAA4B;AACtD,aAAO,KAAK,qBAAqB,QAAQ,KAAK,4BAA4B,SAAS,IAAI;AAAA,IAC3F,OAAO;AACH,aAAO,KAAK,kCAAkC,SAAS,IAAI;AAAA,IAC/D;AAAA,EACJ;AAAA,EAEO,cAAc,YAA6B;AAC9C,WAAO,KAAK,gBAAgB,SAAS,UAAU;AAAA,EACnD;AAAA,EAEO,kBAAkB,aAAgC;AACrD,WAAO,YAAY,MAAM,CAAC,eAAe,KAAK,cAAc,UAAU,CAAC;AAAA,EAC3E;AAAA,EAEA,OAAc,SAAS,MAA6B;AAChD,UAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,WAAO,IAAI;AAAA,MACP,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACR;AAAA,EACJ;AAAA;AAAA,EAIA,IAAI,eAAuB;AACvB,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,IAAI,gBAA0B;AAC1B,QAAI,KAAK,qBAAqB,8BAA4B;AACtD,aAAO,KAAK,4BAA4B,OAAO,KAAK,gBAAgB;AAAA,IACxE,OAAO;AACH,aAAO,CAAC,KAAK,gBAAgB;AAAA,IACjC;AAAA,EACJ;AAAA,EAEA,IAAI,gCAA0C;AAC1C,QAAI,KAAK,qBAAqB,8BAA4B;AACtD,aAAO,KAAK,4BAA4B,OAAO,KAAK,gBAAgB;AAAA,IACxE,OAAO;AACH,aAAO,KAAK;AAAA,IAChB;AAAA,EACJ;AAAA,EAEA,IAAI,cAAwB;AACxB,WAAO,KAAK;AAAA,EAChB;AACJ;AAkCO,SAAS,OAAO,YAAyC;AAC5D,SAAO,cAAc,eAAe,UAAU;AAClD;AAEO,SAAS,uBAAuB,YAEF;AACjC,MAAI,eAAe,QAAW;AAC1B,WAAO;AAAA,EACX;AACA,QAAM,YAAkC,CAAC;AAEzC,aAAW,OAAO,OAAO,KAAK,UAAU,GAAG;AACvC,UAAM,iBAAiB,WAAW,GAAG;AACrC,QAAI,gBAAgB;AAChB,gBAAU,GAAG,IAAI,IAAI;AAAA,QACjB,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe;AAAA,MACnB;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX;;;ACpUO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAI7C,YAAY,SAAiB;AACzB,UAAM,OAAO;AACb,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,EAClB;AACJ;AAEO,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAI9C,YAAY,SAAiB;AACzB,UAAM,OAAO;AACb,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,EAClB;AACJ;;;ACjBA,WAAsB;AAsBf,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AACtB,IAAM,cAAc;AACpB,IAAM,2BAA2B;AACjC,IAAM,4BAA4B;AAElC,IAAM,iCAAiC;AACvC,IAAM,wBAAwB;AAC9B,IAAM,yBAAyB;AAG/B,IAAM,iBAA0C;AAAA,EACnD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,MAAM;AACV;AAEO,SAAS,mBAAmB;AAC/B,SAAO,WAAW,EAAE;AACxB;AAEO,SAAS,aAAa;AACzB,QAAM,UAAU,QAAQ,IAAI,uBAAuB,QAAQ,IAAI;AAC/D,MAAI,CAAC,SAAS;AACV,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACrD;AACA,SAAO,IAAI,IAAI,OAAO;AAC1B;AAUO,SAAS,uBAAuB;AACnC,QAAM,oBAAoB,QAAQ,IAAI;AACtC,MAAI,CAAC,mBAAmB;AACpB,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACnD;AACA,SAAO;AACX;AAEO,SAAS,iBAAiB;AAC7B,QAAM,cAAc,QAAQ,IAAI;AAChC,MAAI,CAAC,aAAa;AACd,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACxD;AACA,SAAO,YAAY,QAAQ,QAAQ,IAAI;AAC3C;AAEO,SAAS,yBAAoD;AAChE,QAAM,mBAAmB,QAAQ,IAAI;AACrC,MAAI,qBAAqB,QAAQ;AAC7B,WAAO;AAAA,EACX,WAAW,qBAAqB,OAAO;AACnC,WAAO;AAAA,EACX,WAAW,qBAAqB,UAAU;AACtC,WAAO;AAAA,EACX,WAAW,kBAAkB;AACzB,UAAM,IAAI;AAAA,MACN;AAAA,IACJ;AAAA,EACJ,OAAO;AACH,WAAO;AAAA,EACX;AACJ;AAEA,SAAsB,sCAClB,cACA,aAC6B;AAAA;AAC7B,UAAM,OAAO;AAAA,MACT,eAAe;AAAA,IACnB;AAEA,UAAM,cAAc,IAAI,gBAAgB;AACxC,QAAI,aAAa;AACb,kBAAY,IAAI,2BAA2B,MAAM;AACjD,kBAAY,IAAI,iBAAiB,WAAW;AAAA,IAChD;AAEA,UAAM,MAAM,GAAG,iBAAiB,kCAAkC,YAAY,SAAS;AACvF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAC9B,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,SAAS;AAAA,QACL,gBAAgB;AAAA,QAChB,eAAe,YAAY,qBAAqB;AAAA,MACpD;AAAA,IACJ,CAAC;AAED,QAAI,SAAS,IAAI;AACb,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,kBAAkB,KAAK;AAC7B,YAAM,EAAE,cAAc,aAAa,oBAAoB,iBAAiB,IAAI,KAAK;AAEjF,aAAO;AAAA,QACH,cAAc;AAAA,QACd;AAAA,QACA,OAAO;AAAA,MACX;AAAA,IACJ,WAAW,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AAC3D,aAAO,EAAE,OAAO,eAAe;AAAA,IACnC,OAAO;AACH,aAAO,EAAE,OAAO,aAAa;AAAA,IACjC;AAAA,EACJ;AAAA;AAEA,SAAsB,+BAClB,aACkC;AAAA;AAClC,QAAI;AACA,aAAO,MAAM,oBAAoB,WAAW;AAAA,IAChD,SAAS,KAAP;AACE,UAAI,eAAe,wBAAwB;AACvC,cAAM;AAAA,MACV,WAAW,eAAe,uBAAuB;AAC7C,eAAO;AAAA,MACX,OAAO;AACH,gBAAQ,KAAK,iCAAiC,GAAG;AACjD,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ;AAAA;AAEA,SAAsB,oBAAoB,aAAyD;AAAA;AAC/F,QAAI;AACJ,QAAI;AACA,kBAAY,MAAW,gBAAW,eAAe,GAAG,OAAO;AAAA,IAC/D,SAAS,KAAP;AACE,cAAQ,MAAM,wFAAwF,GAAG;AACzG,YAAM,IAAI,uBAAuB,sBAAsB;AAAA,IAC3D;AAEA,QAAI,CAAC,aAAa;AACd,YAAM,IAAI,sBAAsB,0BAA0B;AAAA,IAC9D;AAEA,QAAI,2BAA2B;AAC/B,QAAI,YAAY,YAAY,EAAE,WAAW,SAAS,GAAG;AACjD,iCAA2B,YAAY,UAAU,UAAU,MAAM;AAAA,IACrE;AAEA,QAAI;AACA,YAAM,EAAE,QAAQ,IAAI,MAAW,eAAU,0BAA0B,WAAW;AAAA,QAC1E,QAAQ,iBAAiB;AAAA,QACzB,YAAY,CAAC,OAAO;AAAA,MACxB,CAAC;AAED,aAAO,OAAqB,OAAO;AAAA,IACvC,SAAS,GAAP;AACE,UAAI,aAAa,OAAO;AACpB,cAAM,IAAI,sBAAsB,EAAE,OAAO;AAAA,MAC7C,OAAO;AACH,cAAM,IAAI,sBAAsB,sBAAsB;AAAA,MAC1D;AAAA,IACJ;AAAA,EACJ;AAAA;;;ACzLA,uBAAsB;AAGf,IAAM,oBAAoB,MAAM;AACnC,QAAM,UAAU,WAAW;AAC3B,QAAM,oBAAoB,qBAAqB;AAE/C,aAAO,0BAAQ,SAAS,iBAAiB;AAC7C;;;ACNO,IAAM,mBAAN,MAAuB;AAAA,EAClB,YACa,MACA,UACnB;AAFmB;AACA;AAAA,EAClB;AAAA,EAEH,OAAO,WAA6B;AAChC,WAAO,IAAI,iBAAiB,UAAU;AAAA,EAC1C;AAAA,EAEA,OAAO,OAAO,UAA0C;AACpD,WAAO,IAAI,iBAAiB,UAAU,QAAQ;AAAA,EAClD;AAAA,EAEA,iBAA0B;AACtB,WAAO,KAAK,SAAS;AAAA,EACzB;AAAA,EAEA,cAAwC;AACpC,WAAO,KAAK;AAAA,EAChB;AACJ;;;ACvBO,IAAM,4BAA4B;;;ACAzC,wBAAyB;AACzB,qBAAiC;AACjC,oBAA0C;AAuEnC,SAAS,gBAAgB,SAAsB,gBAAyB;AAC3E,QAAMA,WAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,EAAAA,SAAQ,IAAI,uBAAuB,QAAQ,QAAQ,SAAS,CAAC;AAC7D,EAAAA,SAAQ,IAAI,wBAAwB,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,MAAM;AACrF,MAAI,gBAAgB;AAChB,IAAAA,SAAQ,IAAI,gCAAgC,cAAc;AAAA,EAC9D;AACA,SAAO,2BAAa,KAAK;AAAA,IACrB,SAAS;AAAA,MACL,SAAAA;AAAA,IACJ;AAAA,EACJ,CAAC;AACL;;;ACxDO,SAAS,oBAAoB,SAAgF;AAChH,SAAO,CAAO,QAAqB;AA9BvC;AA+BQ,QACI,IAAI,QAAQ,aAAa,iBACzB,IAAI,QAAQ,aAAa,eACzB,IAAI,QAAQ,aAAa,eAC3B;AAEE,aAAO,gBAAgB,GAAG;AAAA,IAC9B;AAEA,UAAM,eAAc,SAAI,QAAQ,IAAI,wBAAwB,MAAxC,mBAA2C;AAC/D,UAAM,gBAAe,SAAI,QAAQ,IAAI,yBAAyB,MAAzC,mBAA4C;AACjE,UAAM,eAAc,SAAI,QAAQ,IAAI,yBAAyB,MAAzC,mBAA4C;AAGhE,QAAI,aAAa;AACb,YAAM,OAAO,MAAM,+BAA+B,WAAW;AAC7D,UAAI,MAAM;AACN,cAAM,eAAe,gBAAgB,GAAG;AACxC,eAAO,MAAM,mBAAmB,KAAK,cAAc,MAAM,OAAO;AAAA,MACpE;AAAA,IACJ;AAGA,QAAI,cAAc;AACd,YAAM,WAAW,MAAM,sCAAsC,cAAc,WAAW;AACtF,UAAI,SAAS,UAAU,cAAc;AACjC,cAAM,IAAI,MAAM,gDAAgD;AAAA,MACpE,WAAW,SAAS,UAAU,gBAAgB;AAC1C,cAAMC,YAAW,gBAAgB,GAAG;AACpC,QAAAA,UAAS,QAAQ,OAAO,wBAAwB;AAChD,QAAAA,UAAS,QAAQ,OAAO,yBAAyB;AACjD,eAAO,MAAM,mBAAmB,KAAKA,WAAU,QAAW,OAAO;AAAA,MACrE,OAAO;AACH,cAAM,WAAW,uBAAuB;AACxC,cAAM,eAAe,gBAAgB,KAAK,SAAS,WAAW;AAC9D,qBAAa,QAAQ,IAAI,0BAA0B,SAAS,aAAa,iCAClE,iBADkE;AAAA,UAErE;AAAA,QACJ,EAAC;AACD,qBAAa,QAAQ,IAAI,2BAA2B,SAAS,cAAc,iCACpE,iBADoE;AAAA,UAEvE;AAAA,QACJ,EAAC;AACD,cAAM,OAAO,MAAM,oBAAoB,SAAS,WAAW;AAC3D,eAAO,MAAM,mBAAmB,KAAK,cAAc,MAAM,OAAO;AAAA,MACpE;AAAA,IACJ;AAEA,UAAM,MAAM,gBAAgB,GAAG;AAC/B,WAAO,MAAM,mBAAmB,KAAK,KAAK,QAAW,OAAO;AAAA,EAChE;AACJ;AAEA,IAAM,qBAAqB,CACvB,KACA,KACA,MACA,YACwB;AAzF5B;AA0FI,MAAI,mCAAS,eAAe;AACxB,UAAM,eAAe,MAAM,QAAQ,cAAc,KAAK,KAAK,IAAI;AAC/D,QAAI,wBAAwB,kBAAkB;AAC1C,UAAI,CAAC,aAAa,eAAe,GAAG;AAChC,gBAAO,kBAAa,YAAY,MAAzB,YAA8B;AAAA,MACzC;AAAA,IACJ,OAAO;AACH,cAAQ,KAAK,6DAA6D;AAAA,IAC9E;AAAA,EACJ;AACA,SAAO;AACX;","names":["headers","response"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@propelauth/nextjs",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "exports": {
5
5
  "./server": {
6
6
  "browser": "./dist/server/index.mjs",
@@ -68,7 +68,7 @@
68
68
  "react": "^18.2.0 || ^19.0.0"
69
69
  },
70
70
  "dependencies": {
71
- "@propelauth/node-apis": "^2.1.31",
71
+ "@propelauth/node-apis": "^2.1.32",
72
72
  "jose": "^5.10.0"
73
73
  }
74
74
  }