@unidir/unidir-nextjs 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +3 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +16 -0
- package/dist/client.d.ts +16 -0
- package/dist/client.mjs +3 -0
- package/dist/client.mjs.map +1 -0
- package/dist/server.cjs +3 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +13 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.mjs +3 -0
- package/dist/server.mjs.map +1 -0
- package/dist/types.cjs +3 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +22 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +14 -9
- package/dist/index.cjs +0 -3
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -44
- package/dist/index.d.ts +0 -44
- package/dist/index.mjs +0 -3
- package/dist/index.mjs.map +0 -1
package/dist/client.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";"use client";var c=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var v=(e,t)=>{for(var o in t)c(e,o,{get:t[o],enumerable:!0})},R=(e,t,o,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of w(t))!T.call(e,s)&&s!==o&&c(e,s,{get:()=>t[s],enumerable:!(i=k(t,s))||i.enumerable});return e};var h=e=>R(c({},"__esModule",{value:!0}),e);var _={};v(_,{UserProvider:()=>C,getDeviceId:()=>x,useUser:()=>S});module.exports=h(_);var n=require("react");var r=require("jose");async function a(e,t,o={}){let i=(0,r.createRemoteJWKSet)(new URL(t)),{payload:s}=await(0,r.jwtVerify)(e,i,{issuer:o.issuer,audience:o.audience});return s}var u=require("react/jsx-runtime"),l=(0,n.createContext)({user:null,isLoading:!0,config:null});function C({children:e,config:t}){let[o,i]=(0,n.useState)(null),[s,d]=(0,n.useState)(!0),[D,E]=(0,n.useState)(null),[L,P]=(0,n.useState)(null),[j,A]=(0,n.useState)(null),[J,W]=(0,n.useState)(null),[N,K]=(0,n.useState)(null),[O,Y]=(0,n.useState)(null);return(0,n.useEffect)(()=>{async function f(){try{let m=await(await fetch("/api/auth/me")).json(),{companyId:p,domainId:g,email:U,email_verified:y,name:I}=await a(m.id_token,t.jwks||"https://oauth.igoodworks.com/jwks.json",{issuer:t.issuer||"http://oauth.unidir.igoodworks.com/",audience:t.clientId});i({companyId:p,domainId:g,email:U,email_verified:y,name:I})}finally{d(!1)}}f()},[]),(0,u.jsx)(l.Provider,{value:{user:o,isLoading:s,config:t},children:e})}function x(){if(typeof window>"u")return"server-default";let e=localStorage.getItem("unidir_device_id");return e||(e=crypto.randomUUID(),localStorage.setItem("unidir_device_id",e)),e}var S=()=>(0,n.useContext)(l);0&&(module.exports={UserProvider,getDeviceId,useUser});
|
|
3
|
+
//# sourceMappingURL=client.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.tsx","../src/jwks.ts"],"sourcesContent":["\"use client\";\r\nimport React, { createContext, useContext, useState, useEffect } from \"react\";\r\nimport { verifyAccessToken } from \"./jwks\";\r\nimport { JWTPayload } from \"jose\";\r\nimport { type UniDirConfig } from \"./types\";\r\n\r\nconst UserContext = createContext<{\r\n user: any;\r\n isLoading: boolean;\r\n config: UniDirConfig | null;\r\n}>({ user: null, isLoading: true, config: null });\r\n\r\nexport function UserProvider({\r\n children,\r\n config,\r\n}: {\r\n children: React.ReactNode;\r\n config: UniDirConfig;\r\n}) {\r\n const [user, setUser] = useState<JWTPayload | null>(null);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [token, setToken] = useState(null);\r\n const [accessToken, setAccessToken] = useState(null);\r\n const [refreshToken, setRefreshToken] = useState(null);\r\n const [idToken, setIdToken] = useState(null);\r\n const [client, setClient] = useState(null);\r\n const [expiresIn, setExpiresIn] = useState(null);\r\n\r\n // useEffect(() => {\r\n // fetch(\"/api/auth/me\")\r\n // .then((res) => res.json())\r\n // .then((data) => {\r\n // if (data) {\r\n // setUser(data.client);\r\n // setToken(data);\r\n // setAccessToken(data.access_token);\r\n // setRefreshToken(data.refresh_token);\r\n // const idTokenAll = await jwtVerify(\r\n // data.id_token,\r\n // config.jwks || \"https://oauth.biocloud.pro/jwks.json\"\r\n // );\r\n // setIdToken(data.id_token);\r\n // setClient(data.client);\r\n // setExpiresIn(data.expres_in);\r\n // }\r\n // })\r\n // .catch(() => setUser(null));\r\n // }, []);\r\n useEffect(() => {\r\n async function loadUser() {\r\n try {\r\n const res = await fetch(\"/api/auth/me\");\r\n const data = await res.json();\r\n //setUser(data.user);\r\n const { companyId, domainId, email, email_verified, name } =\r\n await verifyAccessToken(\r\n data.id_token,\r\n config.jwks || \"https://oauth.igoodworks.com/jwks.json\",\r\n {\r\n issuer: config.issuer || \"http://oauth.unidir.igoodworks.com/\",\r\n audience: config.clientId,\r\n }\r\n );\r\n setUser({ companyId, domainId, email, email_verified, name });\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }\r\n loadUser();\r\n }, []);\r\n return (\r\n <UserContext.Provider\r\n value={{\r\n user,\r\n isLoading,\r\n config,\r\n // token,\r\n // expiresIn,\r\n // accessToken,\r\n // refreshToken,\r\n // client,\r\n // idToken,\r\n }}\r\n >\r\n {children}\r\n </UserContext.Provider>\r\n );\r\n}\r\n\r\nexport function getDeviceId(): string {\r\n if (typeof window === \"undefined\") return \"server-default\";\r\n\r\n let id = localStorage.getItem(\"unidir_device_id\");\r\n if (!id) {\r\n id = crypto.randomUUID();\r\n localStorage.setItem(\"unidir_device_id\", id);\r\n }\r\n return id;\r\n}\r\n\r\nexport const useUser = () => useContext(UserContext);\r\n","import { jwtVerify, createRemoteJWKSet } from \"jose\";\r\n\r\n// Replace with your IdP issuer and audience\r\nconst ISSUER = \"https://YOUR_ISSUER/\";\r\nconst AUDIENCE = \"YOUR_CLIENT_ID\";\r\n\r\nexport async function verifyAccessToken(\r\n token: string,\r\n jwksUrl: string,\r\n options: Record<string, any> = {}\r\n) {\r\n const JWKS = createRemoteJWKSet(new URL(jwksUrl));\r\n const { payload } = await jwtVerify(token, JWKS, {\r\n issuer: options.issuer,\r\n audience: options.audience,\r\n });\r\n // Optionally apply custom claims checks here (e.g., roles, scopes)\r\n return payload;\r\n}\r\n"],"mappings":";sbAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,kBAAAE,EAAA,gBAAAC,EAAA,YAAAC,IAAA,eAAAC,EAAAL,GACA,IAAAM,EAAsE,iBCDtE,IAAAC,EAA8C,gBAM9C,eAAsBC,EACpBC,EACAC,EACAC,EAA+B,CAAC,EAChC,CACA,IAAMC,KAAO,sBAAmB,IAAI,IAAIF,CAAO,CAAC,EAC1C,CAAE,QAAAG,CAAQ,EAAI,QAAM,aAAUJ,EAAOG,EAAM,CAC/C,OAAQD,EAAQ,OAChB,SAAUA,EAAQ,QACpB,CAAC,EAED,OAAOE,CACT,CDqDI,IAAAC,EAAA,6BAjEEC,KAAc,iBAIjB,CAAE,KAAM,KAAM,UAAW,GAAM,OAAQ,IAAK,CAAC,EAEzC,SAASC,EAAa,CAC3B,SAAAC,EACA,OAAAC,CACF,EAGG,CACD,GAAM,CAACC,EAAMC,CAAO,KAAI,YAA4B,IAAI,EAClD,CAACC,EAAWC,CAAY,KAAI,YAAS,EAAI,EACzC,CAACC,EAAOC,CAAQ,KAAI,YAAS,IAAI,EACjC,CAACC,EAAaC,CAAc,KAAI,YAAS,IAAI,EAC7C,CAACC,EAAcC,CAAe,KAAI,YAAS,IAAI,EAC/C,CAACC,EAASC,CAAU,KAAI,YAAS,IAAI,EACrC,CAACC,EAAQC,CAAS,KAAI,YAAS,IAAI,EACnC,CAACC,EAAWC,CAAY,KAAI,YAAS,IAAI,EAsB/C,sBAAU,IAAM,CACd,eAAeC,GAAW,CACxB,GAAI,CAEF,IAAMC,EAAO,MADD,MAAM,MAAM,cAAc,GACf,KAAK,EAEtB,CAAE,UAAAC,EAAW,SAAAC,EAAU,MAAAC,EAAO,eAAAC,EAAgB,KAAAC,CAAK,EACvD,MAAMC,EACJN,EAAK,SACLlB,EAAO,MAAQ,yCACf,CACE,OAAQA,EAAO,QAAU,sCACzB,SAAUA,EAAO,QACnB,CACF,EACFE,EAAQ,CAAE,UAAAiB,EAAW,SAAAC,EAAU,MAAAC,EAAO,eAAAC,EAAgB,KAAAC,CAAK,CAAC,CAC9D,QAAE,CACAnB,EAAa,EAAK,CACpB,CACF,CACAa,EAAS,CACX,EAAG,CAAC,CAAC,KAEH,OAACpB,EAAY,SAAZ,CACC,MAAO,CACL,KAAAI,EACA,UAAAE,EACA,OAAAH,CAOF,EAEC,SAAAD,EACH,CAEJ,CAEO,SAAS0B,GAAsB,CACpC,GAAI,OAAO,OAAW,IAAa,MAAO,iBAE1C,IAAIC,EAAK,aAAa,QAAQ,kBAAkB,EAChD,OAAKA,IACHA,EAAK,OAAO,WAAW,EACvB,aAAa,QAAQ,mBAAoBA,CAAE,GAEtCA,CACT,CAEO,IAAMC,EAAU,OAAM,cAAW9B,CAAW","names":["client_exports","__export","UserProvider","getDeviceId","useUser","__toCommonJS","import_react","import_jose","verifyAccessToken","token","jwksUrl","options","JWKS","payload","import_jsx_runtime","UserContext","UserProvider","children","config","user","setUser","isLoading","setIsLoading","token","setToken","accessToken","setAccessToken","refreshToken","setRefreshToken","idToken","setIdToken","client","setClient","expiresIn","setExpiresIn","loadUser","data","companyId","domainId","email","email_verified","name","verifyAccessToken","getDeviceId","id","useUser"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { UniDirConfig } from './types.cjs';
|
|
4
|
+
|
|
5
|
+
declare function UserProvider({ children, config, }: {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
config: UniDirConfig;
|
|
8
|
+
}): react_jsx_runtime.JSX.Element;
|
|
9
|
+
declare function getDeviceId(): string;
|
|
10
|
+
declare const useUser: () => {
|
|
11
|
+
user: any;
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
config: UniDirConfig | null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { UserProvider, getDeviceId, useUser };
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { UniDirConfig } from './types.js';
|
|
4
|
+
|
|
5
|
+
declare function UserProvider({ children, config, }: {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
config: UniDirConfig;
|
|
8
|
+
}): react_jsx_runtime.JSX.Element;
|
|
9
|
+
declare function getDeviceId(): string;
|
|
10
|
+
declare const useUser: () => {
|
|
11
|
+
user: any;
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
config: UniDirConfig | null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { UserProvider, getDeviceId, useUser };
|
package/dist/client.mjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";import{createContext as I,useContext as k,useState as t,useEffect as w}from"react";import{jwtVerify as U,createRemoteJWKSet as y}from"jose";async function r(e,n,o={}){let s=y(new URL(n)),{payload:i}=await U(e,s,{issuer:o.issuer,audience:o.audience});return i}import{jsx as T}from"react/jsx-runtime";var c=I({user:null,isLoading:!0,config:null});function Y({children:e,config:n}){let[o,s]=t(null),[i,a]=t(!0),[v,R]=t(null),[h,C]=t(null),[x,S]=t(null),[_,D]=t(null),[E,L]=t(null),[P,j]=t(null);return w(()=>{async function l(){try{let u=await(await fetch("/api/auth/me")).json(),{companyId:d,domainId:f,email:m,email_verified:p,name:g}=await r(u.id_token,n.jwks||"https://oauth.igoodworks.com/jwks.json",{issuer:n.issuer||"http://oauth.unidir.igoodworks.com/",audience:n.clientId});s({companyId:d,domainId:f,email:m,email_verified:p,name:g})}finally{a(!1)}}l()},[]),T(c.Provider,{value:{user:o,isLoading:i,config:n},children:e})}function b(){if(typeof window>"u")return"server-default";let e=localStorage.getItem("unidir_device_id");return e||(e=crypto.randomUUID(),localStorage.setItem("unidir_device_id",e)),e}var V=()=>k(c);export{Y as UserProvider,b as getDeviceId,V as useUser};
|
|
3
|
+
//# sourceMappingURL=client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.tsx","../src/jwks.ts"],"sourcesContent":["\"use client\";\r\nimport React, { createContext, useContext, useState, useEffect } from \"react\";\r\nimport { verifyAccessToken } from \"./jwks\";\r\nimport { JWTPayload } from \"jose\";\r\nimport { type UniDirConfig } from \"./types\";\r\n\r\nconst UserContext = createContext<{\r\n user: any;\r\n isLoading: boolean;\r\n config: UniDirConfig | null;\r\n}>({ user: null, isLoading: true, config: null });\r\n\r\nexport function UserProvider({\r\n children,\r\n config,\r\n}: {\r\n children: React.ReactNode;\r\n config: UniDirConfig;\r\n}) {\r\n const [user, setUser] = useState<JWTPayload | null>(null);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [token, setToken] = useState(null);\r\n const [accessToken, setAccessToken] = useState(null);\r\n const [refreshToken, setRefreshToken] = useState(null);\r\n const [idToken, setIdToken] = useState(null);\r\n const [client, setClient] = useState(null);\r\n const [expiresIn, setExpiresIn] = useState(null);\r\n\r\n // useEffect(() => {\r\n // fetch(\"/api/auth/me\")\r\n // .then((res) => res.json())\r\n // .then((data) => {\r\n // if (data) {\r\n // setUser(data.client);\r\n // setToken(data);\r\n // setAccessToken(data.access_token);\r\n // setRefreshToken(data.refresh_token);\r\n // const idTokenAll = await jwtVerify(\r\n // data.id_token,\r\n // config.jwks || \"https://oauth.biocloud.pro/jwks.json\"\r\n // );\r\n // setIdToken(data.id_token);\r\n // setClient(data.client);\r\n // setExpiresIn(data.expres_in);\r\n // }\r\n // })\r\n // .catch(() => setUser(null));\r\n // }, []);\r\n useEffect(() => {\r\n async function loadUser() {\r\n try {\r\n const res = await fetch(\"/api/auth/me\");\r\n const data = await res.json();\r\n //setUser(data.user);\r\n const { companyId, domainId, email, email_verified, name } =\r\n await verifyAccessToken(\r\n data.id_token,\r\n config.jwks || \"https://oauth.igoodworks.com/jwks.json\",\r\n {\r\n issuer: config.issuer || \"http://oauth.unidir.igoodworks.com/\",\r\n audience: config.clientId,\r\n }\r\n );\r\n setUser({ companyId, domainId, email, email_verified, name });\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }\r\n loadUser();\r\n }, []);\r\n return (\r\n <UserContext.Provider\r\n value={{\r\n user,\r\n isLoading,\r\n config,\r\n // token,\r\n // expiresIn,\r\n // accessToken,\r\n // refreshToken,\r\n // client,\r\n // idToken,\r\n }}\r\n >\r\n {children}\r\n </UserContext.Provider>\r\n );\r\n}\r\n\r\nexport function getDeviceId(): string {\r\n if (typeof window === \"undefined\") return \"server-default\";\r\n\r\n let id = localStorage.getItem(\"unidir_device_id\");\r\n if (!id) {\r\n id = crypto.randomUUID();\r\n localStorage.setItem(\"unidir_device_id\", id);\r\n }\r\n return id;\r\n}\r\n\r\nexport const useUser = () => useContext(UserContext);\r\n","import { jwtVerify, createRemoteJWKSet } from \"jose\";\r\n\r\n// Replace with your IdP issuer and audience\r\nconst ISSUER = \"https://YOUR_ISSUER/\";\r\nconst AUDIENCE = \"YOUR_CLIENT_ID\";\r\n\r\nexport async function verifyAccessToken(\r\n token: string,\r\n jwksUrl: string,\r\n options: Record<string, any> = {}\r\n) {\r\n const JWKS = createRemoteJWKSet(new URL(jwksUrl));\r\n const { payload } = await jwtVerify(token, JWKS, {\r\n issuer: options.issuer,\r\n audience: options.audience,\r\n });\r\n // Optionally apply custom claims checks here (e.g., roles, scopes)\r\n return payload;\r\n}\r\n"],"mappings":";aACA,OAAgB,iBAAAA,EAAe,cAAAC,EAAY,YAAAC,EAAU,aAAAC,MAAiB,QCDtE,OAAS,aAAAC,EAAW,sBAAAC,MAA0B,OAM9C,eAAsBC,EACpBC,EACAC,EACAC,EAA+B,CAAC,EAChC,CACA,IAAMC,EAAOC,EAAmB,IAAI,IAAIH,CAAO,CAAC,EAC1C,CAAE,QAAAI,CAAQ,EAAI,MAAMC,EAAUN,EAAOG,EAAM,CAC/C,OAAQD,EAAQ,OAChB,SAAUA,EAAQ,QACpB,CAAC,EAED,OAAOG,CACT,CDqDI,cAAAE,MAAA,oBAjEJ,IAAMC,EAAcC,EAIjB,CAAE,KAAM,KAAM,UAAW,GAAM,OAAQ,IAAK,CAAC,EAEzC,SAASC,EAAa,CAC3B,SAAAC,EACA,OAAAC,CACF,EAGG,CACD,GAAM,CAACC,EAAMC,CAAO,EAAIC,EAA4B,IAAI,EAClD,CAACC,EAAWC,CAAY,EAAIF,EAAS,EAAI,EACzC,CAACG,EAAOC,CAAQ,EAAIJ,EAAS,IAAI,EACjC,CAACK,EAAaC,CAAc,EAAIN,EAAS,IAAI,EAC7C,CAACO,EAAcC,CAAe,EAAIR,EAAS,IAAI,EAC/C,CAACS,EAASC,CAAU,EAAIV,EAAS,IAAI,EACrC,CAACW,EAAQC,CAAS,EAAIZ,EAAS,IAAI,EACnC,CAACa,EAAWC,CAAY,EAAId,EAAS,IAAI,EAsB/C,OAAAe,EAAU,IAAM,CACd,eAAeC,GAAW,CACxB,GAAI,CAEF,IAAMC,EAAO,MADD,MAAM,MAAM,cAAc,GACf,KAAK,EAEtB,CAAE,UAAAC,EAAW,SAAAC,EAAU,MAAAC,EAAO,eAAAC,EAAgB,KAAAC,CAAK,EACvD,MAAMC,EACJN,EAAK,SACLpB,EAAO,MAAQ,yCACf,CACE,OAAQA,EAAO,QAAU,sCACzB,SAAUA,EAAO,QACnB,CACF,EACFE,EAAQ,CAAE,UAAAmB,EAAW,SAAAC,EAAU,MAAAC,EAAO,eAAAC,EAAgB,KAAAC,CAAK,CAAC,CAC9D,QAAE,CACApB,EAAa,EAAK,CACpB,CACF,CACAc,EAAS,CACX,EAAG,CAAC,CAAC,EAEHxB,EAACC,EAAY,SAAZ,CACC,MAAO,CACL,KAAAK,EACA,UAAAG,EACA,OAAAJ,CAOF,EAEC,SAAAD,EACH,CAEJ,CAEO,SAAS4B,GAAsB,CACpC,GAAI,OAAO,OAAW,IAAa,MAAO,iBAE1C,IAAIC,EAAK,aAAa,QAAQ,kBAAkB,EAChD,OAAKA,IACHA,EAAK,OAAO,WAAW,EACvB,aAAa,QAAQ,mBAAoBA,CAAE,GAEtCA,CACT,CAEO,IAAMC,EAAU,IAAMC,EAAWlC,CAAW","names":["createContext","useContext","useState","useEffect","jwtVerify","createRemoteJWKSet","verifyAccessToken","token","jwksUrl","options","JWKS","createRemoteJWKSet","payload","jwtVerify","jsx","UserContext","createContext","UserProvider","children","config","user","setUser","useState","isLoading","setIsLoading","token","setToken","accessToken","setAccessToken","refreshToken","setRefreshToken","idToken","setIdToken","client","setClient","expiresIn","setExpiresIn","useEffect","loadUser","data","companyId","domainId","email","email_verified","name","verifyAccessToken","getDeviceId","id","useUser","useContext"]}
|
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";var D=Object.create;var g=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var O=(e,n)=>{for(var r in n)g(e,r,{get:n[r],enumerable:!0})},w=(e,n,r,d)=>{if(n&&typeof n=="object"||typeof n=="function")for(let t of I(n))!N.call(e,t)&&t!==r&&g(e,t,{get:()=>n[t],enumerable:!(d=R(n,t))||d.enumerable});return e};var j=(e,n,r)=>(r=e!=null?D(b(e)):{},w(n||!e||!e.__esModule?g(r,"default",{value:e,enumerable:!0}):r,e)),E=e=>w(g({},"__esModule",{value:!0}),e);var H={};O(H,{initUniDir:()=>$});module.exports=E(H);var U=require("cookie");var m=require("jose"),v=e=>new TextEncoder().encode(e.padEnd(32,"0").slice(0,32));async function x(e,n){return new m.EncryptJWT(e).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setIssuedAt().setExpirationTime("24h").encrypt(v(n))}async function _(e,n){try{let{payload:r}=await(0,m.jwtDecrypt)(e,v(n));return r}catch{return null}}var a=require("next/server"),A=require("next/navigation");function k(){let e=new Uint8Array(32);return crypto.getRandomValues(e),btoa(String.fromCharCode(...e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function P(e){let r=new TextEncoder().encode(e),d=await crypto.subtle.digest("SHA-256",r);return btoa(String.fromCharCode(...new Uint8Array(d))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}var C=require("react/jsx-runtime"),L={login:"login",loginPath:"/api/auth/login",logout:"logout",callback:"callback",me:"me"};function $(e,n){let r={...L,...n},d=async t=>{let o=t.headers.get("cookie")||"",i=(0,U.parse)(o).unidir_session;return i?await _(i,e.secret):null};return{handleAuth:()=>async t=>{let o=t.nextUrl.pathname.split("/").pop(),i=t.nextUrl.searchParams.get("device_id")||e.deviceId||"unknown-device";if(o===r.login){let s=t.nextUrl.searchParams.get("returnTo")||"/",u=k(),f=await P(u),c=new URL(`${e.domain}/authorize`);c.searchParams.set("client_id",e.clientId),c.searchParams.set("response_type","code"),c.searchParams.set("redirect_uri",e.redirectUri),c.searchParams.set("scope","openid profile email"),c.searchParams.set("code_challenge",f),c.searchParams.set("code_challenge_method","S256"),i&&c.searchParams.set("device_id",i);let l=a.NextResponse.redirect(c.toString());return l.cookies.set("unidir_pkce_verifier",u,{httpOnly:!0,secure:!0,sameSite:"lax",maxAge:300}),l.cookies.set("unidir_device_id",i,{httpOnly:!0,secure:!0,maxAge:600}),l.cookies.set("unidir_return_to",s,{httpOnly:!0,maxAge:300}),l}if(o===r.me){let s=await d(t);return s?a.NextResponse.json(s):new a.NextResponse(JSON.stringify({user:null}),{status:401})}if(o===r.logout){let s=a.NextResponse.redirect(new URL("/",t.url));return s.cookies.delete("unidir_session"),s}if(o==="callback"){let s=t.nextUrl.searchParams.get("code"),u=t.cookies.get("unidir_pkce_verifier")?.value;if(!s||!u)return new a.NextResponse("Missing code or verifier",{status:400});let c=t.cookies.get("unidir_device_id")?.value||i,h=await(await fetch(`${e.domain}/token`,{method:"POST",headers:{"Content-Type":"application/json","x-device-id":c},body:JSON.stringify({grant_type:"authorization_code",client_id:e.clientId,client_secret:e.clientSecret,code:s,code_verifier:u,redirect_uri:e.redirectUri,device_id:c})})).json();if(h.error)return a.NextResponse.json(h,{status:400});let S=await x(h,e.secret),T=t.cookies.get("unidir_return_to")?.value||"/",y=a.NextResponse.redirect(new URL(T,t.url));return y.cookies.delete("unidir_pkce_verifier"),y.cookies.set("unidir_session",S,{httpOnly:!0,secure:!0,sameSite:"lax",maxAge:3600*24}),y}return new a.NextResponse("Not Found",{status:404})},getSession:d,withPageAuthRequired:t=>async o=>{let{headers:p}=await import("next/headers"),i=await d({headers:await p()});return i||(0,A.redirect)(r.loginPath),(0,C.jsx)(t,{...o,user:i})},withMiddlewareAuth:()=>async t=>{let o=t.cookies.get("unidir_session")?.value;if(!(o?await _(o,e.secret):null)){let{pathname:i,search:s}=t.nextUrl,u=new URL(r.loginPath,t.url);return u.searchParams.set("returnTo",`${i}${s}`),a.NextResponse.redirect(u)}return a.NextResponse.next()}}}0&&(module.exports={initUniDir});
|
|
3
|
+
//# sourceMappingURL=server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.tsx","../src/session.ts","../src/pkce.ts"],"sourcesContent":["import { parse } from \"cookie\";\r\nimport { encrypt, decrypt } from \"./session\";\r\nimport { NextRequest, NextResponse } from \"next/server\";\r\nimport { redirect } from \"next/navigation\";\r\nimport { generateCodeVerifier, generateCodeChallenge } from \"./pkce\";\r\nimport { type UniDirConfig, type UniDirAction } from \"./types\";\r\n\r\nconst defaultActions: UniDirAction = {\r\n login: \"login\",\r\n loginPath: \"/api/auth/login\",\r\n logout: \"logout\",\r\n callback: \"callback\",\r\n me: \"me\",\r\n};\r\n\r\nexport function initUniDir(config: UniDirConfig, actions?: UniDirAction) {\r\n const uniDirActions = { ...defaultActions, ...actions };\r\n\r\n const getSession = async (req: Request | NextRequest) => {\r\n const cookieHeader = req.headers.get(\"cookie\") || \"\";\r\n const cookies = parse(cookieHeader);\r\n const sessionToken = cookies[\"unidir_session\"];\r\n if (!sessionToken) return null;\r\n return await decrypt(sessionToken, config.secret);\r\n };\r\n\r\n return {\r\n handleAuth: () => async (req: NextRequest) => {\r\n const action = req.nextUrl.pathname.split(\"/\").pop();\r\n // Capture the deviceId from the query param sent by the LoginButton\r\n const queryDeviceId = req.nextUrl.searchParams.get(\"device_id\");\r\n const effectiveDeviceId =\r\n queryDeviceId || config.deviceId || \"unknown-device\";\r\n //const deviceId = req.headers.get(\"x-device-id\");\r\n\r\n if (action === uniDirActions.login) {\r\n const returnTo = req.nextUrl.searchParams.get(\"returnTo\") || \"/\";\r\n const verifier = generateCodeVerifier();\r\n const challenge = await generateCodeChallenge(verifier);\r\n\r\n const url = new URL(`${config.domain}/authorize`);\r\n url.searchParams.set(\"client_id\", config.clientId);\r\n url.searchParams.set(\"response_type\", \"code\");\r\n url.searchParams.set(\"redirect_uri\", config.redirectUri);\r\n url.searchParams.set(\"scope\", \"openid profile email\");\r\n url.searchParams.set(\"code_challenge\", challenge);\r\n url.searchParams.set(\"code_challenge_method\", \"S256\");\r\n if (effectiveDeviceId) {\r\n url.searchParams.set(\"device_id\", effectiveDeviceId);\r\n }\r\n const response = NextResponse.redirect(url.toString());\r\n\r\n // Store verifier in a short-lived, secure cookie\r\n response.cookies.set(\"unidir_pkce_verifier\", verifier, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n maxAge: 60 * 5, // 5 minutes\r\n });\r\n response.cookies.set(\"unidir_device_id\", effectiveDeviceId, {\r\n httpOnly: true,\r\n secure: true,\r\n maxAge: 60 * 10, // 10 minutes\r\n });\r\n response.cookies.set(\"unidir_return_to\", returnTo, {\r\n httpOnly: true,\r\n maxAge: 60 * 5,\r\n });\r\n return response;\r\n }\r\n // Profile Handler (for useUser hook)\r\n if (action === uniDirActions.me) {\r\n const session = await getSession(req);\r\n if (!session)\r\n return new NextResponse(JSON.stringify({ user: null }), {\r\n status: 401,\r\n });\r\n return NextResponse.json(session);\r\n }\r\n\r\n // Logout Handler\r\n if (action === uniDirActions.logout) {\r\n const response = NextResponse.redirect(new URL(\"/\", req.url));\r\n response.cookies.delete(\"unidir_session\");\r\n return response;\r\n }\r\n if (action === \"callback\") {\r\n const code = req.nextUrl.searchParams.get(\"code\");\r\n const verifier = req.cookies.get(\"unidir_pkce_verifier\")?.value;\r\n\r\n if (!code || !verifier) {\r\n return new NextResponse(\"Missing code or verifier\", { status: 400 });\r\n }\r\n\r\n const storedDeviceId = req.cookies.get(\"unidir_device_id\")?.value;\r\n const deviceIdToUse = storedDeviceId || effectiveDeviceId;\r\n\r\n const res = await fetch(`${config.domain}/token`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-device-id\": deviceIdToUse, // Added to header\r\n },\r\n body: JSON.stringify({\r\n grant_type: \"authorization_code\",\r\n client_id: config.clientId,\r\n client_secret: config.clientSecret,\r\n code,\r\n code_verifier: verifier, // Pass the verifier back\r\n redirect_uri: config.redirectUri,\r\n device_id: deviceIdToUse,\r\n }),\r\n });\r\n\r\n const tokens = await res.json();\r\n if (tokens.error) return NextResponse.json(tokens, { status: 400 });\r\n\r\n const encryptedSession = await encrypt(tokens, config.secret);\r\n // const response = NextResponse.redirect(new URL(\"/\", req.url));\r\n const returnTo = req.cookies.get(\"unidir_return_to\")?.value || \"/\";\r\n const response = NextResponse.redirect(new URL(returnTo, req.url));\r\n\r\n // Clean up PKCE cookie and set session\r\n response.cookies.delete(\"unidir_pkce_verifier\");\r\n response.cookies.set(\"unidir_session\", encryptedSession, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n maxAge: 60 * 60 * 24,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n return new NextResponse(\"Not Found\", { status: 404 });\r\n },\r\n\r\n getSession,\r\n\r\n withPageAuthRequired: <P extends object>(\r\n Component: React.ComponentType<P>\r\n ) => {\r\n return async (props: P) => {\r\n // Import headers dynamically to avoid issues in non-server environments\r\n const { headers } = await import(\"next/headers\");\r\n const session = await getSession({ headers: await headers() } as any);\r\n\r\n if (!session) {\r\n redirect(uniDirActions.loginPath);\r\n }\r\n\r\n // Return the component as JSX\r\n return <Component {...props} user={session} />;\r\n };\r\n },\r\n\r\n withMiddlewareAuth: () => {\r\n return async (req: NextRequest) => {\r\n const sessionToken = req.cookies.get(\"unidir_session\")?.value;\r\n const session = sessionToken\r\n ? await decrypt(sessionToken, config.secret)\r\n : null;\r\n\r\n if (!session) {\r\n // Redirect to login but save the current URL to return back later\r\n const { pathname, search } = req.nextUrl;\r\n const url = new URL(uniDirActions.loginPath, req.url);\r\n url.searchParams.set(\"returnTo\", `${pathname}${search}`);\r\n return NextResponse.redirect(url);\r\n }\r\n\r\n return NextResponse.next();\r\n };\r\n },\r\n };\r\n}\r\n","import { EncryptJWT, jwtDecrypt } from \"jose\";\r\n\r\nconst getSecretKey = (secret: string) =>\r\n new TextEncoder().encode(secret.padEnd(32, \"0\").slice(0, 32));\r\n\r\nexport async function encrypt(payload: any, secret: string) {\r\n return new EncryptJWT(payload)\r\n .setProtectedHeader({ alg: \"dir\", enc: \"A256GCM\" })\r\n .setIssuedAt()\r\n .setExpirationTime(\"24h\")\r\n .encrypt(getSecretKey(secret));\r\n}\r\n\r\nexport async function decrypt(token: string, secret: string) {\r\n try {\r\n const { payload } = await jwtDecrypt(token, getSecretKey(secret));\r\n return payload;\r\n } catch (e) {\r\n return null;\r\n }\r\n}\r\n","export function generateCodeVerifier(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return btoa(String.fromCharCode(...array))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n}\r\n\r\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\r\n return btoa(String.fromCharCode(...new Uint8Array(digest)))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n}\r\n"],"mappings":"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","names":["server_exports","__export","initUniDir","__toCommonJS","import_cookie","import_jose","getSecretKey","secret","encrypt","payload","decrypt","token","import_server","import_navigation","generateCodeVerifier","array","generateCodeChallenge","verifier","data","digest","import_jsx_runtime","defaultActions","initUniDir","config","actions","uniDirActions","getSession","req","cookieHeader","sessionToken","decrypt","action","effectiveDeviceId","returnTo","verifier","generateCodeVerifier","challenge","generateCodeChallenge","url","response","session","code","deviceIdToUse","tokens","encryptedSession","encrypt","Component","props","headers","pathname","search"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as jose from 'jose';
|
|
3
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
+
import { UniDirConfig, UniDirAction } from './types.cjs';
|
|
5
|
+
|
|
6
|
+
declare function initUniDir(config: UniDirConfig, actions?: UniDirAction): {
|
|
7
|
+
handleAuth: () => (req: NextRequest) => Promise<NextResponse<any>>;
|
|
8
|
+
getSession: (req: Request | NextRequest) => Promise<jose.JWTPayload | null>;
|
|
9
|
+
withPageAuthRequired: <P extends object>(Component: React.ComponentType<P>) => (props: P) => Promise<react_jsx_runtime.JSX.Element>;
|
|
10
|
+
withMiddlewareAuth: () => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { initUniDir };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as jose from 'jose';
|
|
3
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
+
import { UniDirConfig, UniDirAction } from './types.js';
|
|
5
|
+
|
|
6
|
+
declare function initUniDir(config: UniDirConfig, actions?: UniDirAction): {
|
|
7
|
+
handleAuth: () => (req: NextRequest) => Promise<NextResponse<any>>;
|
|
8
|
+
getSession: (req: Request | NextRequest) => Promise<jose.JWTPayload | null>;
|
|
9
|
+
withPageAuthRequired: <P extends object>(Component: React.ComponentType<P>) => (props: P) => Promise<react_jsx_runtime.JSX.Element>;
|
|
10
|
+
withMiddlewareAuth: () => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { initUniDir };
|
package/dist/server.mjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import{parse as A}from"cookie";import{EncryptJWT as P,jwtDecrypt as U}from"jose";var _=e=>new TextEncoder().encode(e.padEnd(32,"0").slice(0,32));async function f(e,d){return new P(e).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setIssuedAt().setExpirationTime("24h").encrypt(_(d))}async function h(e,d){try{let{payload:o}=await U(e,_(d));return o}catch{return null}}import{NextResponse as c}from"next/server";import{redirect as C}from"next/navigation";function w(){let e=new Uint8Array(32);return crypto.getRandomValues(e),btoa(String.fromCharCode(...e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function v(e){let o=new TextEncoder().encode(e),u=await crypto.subtle.digest("SHA-256",o);return btoa(String.fromCharCode(...new Uint8Array(u))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}import{jsx as T}from"react/jsx-runtime";var S={login:"login",loginPath:"/api/auth/login",logout:"logout",callback:"callback",me:"me"};function $(e,d){let o={...S,...d},u=async t=>{let i=t.headers.get("cookie")||"",r=A(i).unidir_session;return r?await h(r,e.secret):null};return{handleAuth:()=>async t=>{let i=t.nextUrl.pathname.split("/").pop(),r=t.nextUrl.searchParams.get("device_id")||e.deviceId||"unknown-device";if(i===o.login){let n=t.nextUrl.searchParams.get("returnTo")||"/",a=w(),y=await v(a),s=new URL(`${e.domain}/authorize`);s.searchParams.set("client_id",e.clientId),s.searchParams.set("response_type","code"),s.searchParams.set("redirect_uri",e.redirectUri),s.searchParams.set("scope","openid profile email"),s.searchParams.set("code_challenge",y),s.searchParams.set("code_challenge_method","S256"),r&&s.searchParams.set("device_id",r);let l=c.redirect(s.toString());return l.cookies.set("unidir_pkce_verifier",a,{httpOnly:!0,secure:!0,sameSite:"lax",maxAge:300}),l.cookies.set("unidir_device_id",r,{httpOnly:!0,secure:!0,maxAge:600}),l.cookies.set("unidir_return_to",n,{httpOnly:!0,maxAge:300}),l}if(i===o.me){let n=await u(t);return n?c.json(n):new c(JSON.stringify({user:null}),{status:401})}if(i===o.logout){let n=c.redirect(new URL("/",t.url));return n.cookies.delete("unidir_session"),n}if(i==="callback"){let n=t.nextUrl.searchParams.get("code"),a=t.cookies.get("unidir_pkce_verifier")?.value;if(!n||!a)return new c("Missing code or verifier",{status:400});let s=t.cookies.get("unidir_device_id")?.value||r,g=await(await fetch(`${e.domain}/token`,{method:"POST",headers:{"Content-Type":"application/json","x-device-id":s},body:JSON.stringify({grant_type:"authorization_code",client_id:e.clientId,client_secret:e.clientSecret,code:n,code_verifier:a,redirect_uri:e.redirectUri,device_id:s})})).json();if(g.error)return c.json(g,{status:400});let x=await f(g,e.secret),k=t.cookies.get("unidir_return_to")?.value||"/",m=c.redirect(new URL(k,t.url));return m.cookies.delete("unidir_pkce_verifier"),m.cookies.set("unidir_session",x,{httpOnly:!0,secure:!0,sameSite:"lax",maxAge:3600*24}),m}return new c("Not Found",{status:404})},getSession:u,withPageAuthRequired:t=>async i=>{let{headers:p}=await import("next/headers"),r=await u({headers:await p()});return r||C(o.loginPath),T(t,{...i,user:r})},withMiddlewareAuth:()=>async t=>{let i=t.cookies.get("unidir_session")?.value;if(!(i?await h(i,e.secret):null)){let{pathname:r,search:n}=t.nextUrl,a=new URL(o.loginPath,t.url);return a.searchParams.set("returnTo",`${r}${n}`),c.redirect(a)}return c.next()}}}export{$ as initUniDir};
|
|
3
|
+
//# sourceMappingURL=server.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.tsx","../src/session.ts","../src/pkce.ts"],"sourcesContent":["import { parse } from \"cookie\";\r\nimport { encrypt, decrypt } from \"./session\";\r\nimport { NextRequest, NextResponse } from \"next/server\";\r\nimport { redirect } from \"next/navigation\";\r\nimport { generateCodeVerifier, generateCodeChallenge } from \"./pkce\";\r\nimport { type UniDirConfig, type UniDirAction } from \"./types\";\r\n\r\nconst defaultActions: UniDirAction = {\r\n login: \"login\",\r\n loginPath: \"/api/auth/login\",\r\n logout: \"logout\",\r\n callback: \"callback\",\r\n me: \"me\",\r\n};\r\n\r\nexport function initUniDir(config: UniDirConfig, actions?: UniDirAction) {\r\n const uniDirActions = { ...defaultActions, ...actions };\r\n\r\n const getSession = async (req: Request | NextRequest) => {\r\n const cookieHeader = req.headers.get(\"cookie\") || \"\";\r\n const cookies = parse(cookieHeader);\r\n const sessionToken = cookies[\"unidir_session\"];\r\n if (!sessionToken) return null;\r\n return await decrypt(sessionToken, config.secret);\r\n };\r\n\r\n return {\r\n handleAuth: () => async (req: NextRequest) => {\r\n const action = req.nextUrl.pathname.split(\"/\").pop();\r\n // Capture the deviceId from the query param sent by the LoginButton\r\n const queryDeviceId = req.nextUrl.searchParams.get(\"device_id\");\r\n const effectiveDeviceId =\r\n queryDeviceId || config.deviceId || \"unknown-device\";\r\n //const deviceId = req.headers.get(\"x-device-id\");\r\n\r\n if (action === uniDirActions.login) {\r\n const returnTo = req.nextUrl.searchParams.get(\"returnTo\") || \"/\";\r\n const verifier = generateCodeVerifier();\r\n const challenge = await generateCodeChallenge(verifier);\r\n\r\n const url = new URL(`${config.domain}/authorize`);\r\n url.searchParams.set(\"client_id\", config.clientId);\r\n url.searchParams.set(\"response_type\", \"code\");\r\n url.searchParams.set(\"redirect_uri\", config.redirectUri);\r\n url.searchParams.set(\"scope\", \"openid profile email\");\r\n url.searchParams.set(\"code_challenge\", challenge);\r\n url.searchParams.set(\"code_challenge_method\", \"S256\");\r\n if (effectiveDeviceId) {\r\n url.searchParams.set(\"device_id\", effectiveDeviceId);\r\n }\r\n const response = NextResponse.redirect(url.toString());\r\n\r\n // Store verifier in a short-lived, secure cookie\r\n response.cookies.set(\"unidir_pkce_verifier\", verifier, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n maxAge: 60 * 5, // 5 minutes\r\n });\r\n response.cookies.set(\"unidir_device_id\", effectiveDeviceId, {\r\n httpOnly: true,\r\n secure: true,\r\n maxAge: 60 * 10, // 10 minutes\r\n });\r\n response.cookies.set(\"unidir_return_to\", returnTo, {\r\n httpOnly: true,\r\n maxAge: 60 * 5,\r\n });\r\n return response;\r\n }\r\n // Profile Handler (for useUser hook)\r\n if (action === uniDirActions.me) {\r\n const session = await getSession(req);\r\n if (!session)\r\n return new NextResponse(JSON.stringify({ user: null }), {\r\n status: 401,\r\n });\r\n return NextResponse.json(session);\r\n }\r\n\r\n // Logout Handler\r\n if (action === uniDirActions.logout) {\r\n const response = NextResponse.redirect(new URL(\"/\", req.url));\r\n response.cookies.delete(\"unidir_session\");\r\n return response;\r\n }\r\n if (action === \"callback\") {\r\n const code = req.nextUrl.searchParams.get(\"code\");\r\n const verifier = req.cookies.get(\"unidir_pkce_verifier\")?.value;\r\n\r\n if (!code || !verifier) {\r\n return new NextResponse(\"Missing code or verifier\", { status: 400 });\r\n }\r\n\r\n const storedDeviceId = req.cookies.get(\"unidir_device_id\")?.value;\r\n const deviceIdToUse = storedDeviceId || effectiveDeviceId;\r\n\r\n const res = await fetch(`${config.domain}/token`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-device-id\": deviceIdToUse, // Added to header\r\n },\r\n body: JSON.stringify({\r\n grant_type: \"authorization_code\",\r\n client_id: config.clientId,\r\n client_secret: config.clientSecret,\r\n code,\r\n code_verifier: verifier, // Pass the verifier back\r\n redirect_uri: config.redirectUri,\r\n device_id: deviceIdToUse,\r\n }),\r\n });\r\n\r\n const tokens = await res.json();\r\n if (tokens.error) return NextResponse.json(tokens, { status: 400 });\r\n\r\n const encryptedSession = await encrypt(tokens, config.secret);\r\n // const response = NextResponse.redirect(new URL(\"/\", req.url));\r\n const returnTo = req.cookies.get(\"unidir_return_to\")?.value || \"/\";\r\n const response = NextResponse.redirect(new URL(returnTo, req.url));\r\n\r\n // Clean up PKCE cookie and set session\r\n response.cookies.delete(\"unidir_pkce_verifier\");\r\n response.cookies.set(\"unidir_session\", encryptedSession, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n maxAge: 60 * 60 * 24,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n return new NextResponse(\"Not Found\", { status: 404 });\r\n },\r\n\r\n getSession,\r\n\r\n withPageAuthRequired: <P extends object>(\r\n Component: React.ComponentType<P>\r\n ) => {\r\n return async (props: P) => {\r\n // Import headers dynamically to avoid issues in non-server environments\r\n const { headers } = await import(\"next/headers\");\r\n const session = await getSession({ headers: await headers() } as any);\r\n\r\n if (!session) {\r\n redirect(uniDirActions.loginPath);\r\n }\r\n\r\n // Return the component as JSX\r\n return <Component {...props} user={session} />;\r\n };\r\n },\r\n\r\n withMiddlewareAuth: () => {\r\n return async (req: NextRequest) => {\r\n const sessionToken = req.cookies.get(\"unidir_session\")?.value;\r\n const session = sessionToken\r\n ? await decrypt(sessionToken, config.secret)\r\n : null;\r\n\r\n if (!session) {\r\n // Redirect to login but save the current URL to return back later\r\n const { pathname, search } = req.nextUrl;\r\n const url = new URL(uniDirActions.loginPath, req.url);\r\n url.searchParams.set(\"returnTo\", `${pathname}${search}`);\r\n return NextResponse.redirect(url);\r\n }\r\n\r\n return NextResponse.next();\r\n };\r\n },\r\n };\r\n}\r\n","import { EncryptJWT, jwtDecrypt } from \"jose\";\r\n\r\nconst getSecretKey = (secret: string) =>\r\n new TextEncoder().encode(secret.padEnd(32, \"0\").slice(0, 32));\r\n\r\nexport async function encrypt(payload: any, secret: string) {\r\n return new EncryptJWT(payload)\r\n .setProtectedHeader({ alg: \"dir\", enc: \"A256GCM\" })\r\n .setIssuedAt()\r\n .setExpirationTime(\"24h\")\r\n .encrypt(getSecretKey(secret));\r\n}\r\n\r\nexport async function decrypt(token: string, secret: string) {\r\n try {\r\n const { payload } = await jwtDecrypt(token, getSecretKey(secret));\r\n return payload;\r\n } catch (e) {\r\n return null;\r\n }\r\n}\r\n","export function generateCodeVerifier(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return btoa(String.fromCharCode(...array))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n}\r\n\r\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\r\n return btoa(String.fromCharCode(...new Uint8Array(digest)))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n}\r\n"],"mappings":"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","names":["parse","EncryptJWT","jwtDecrypt","getSecretKey","secret","encrypt","payload","decrypt","token","NextResponse","redirect","generateCodeVerifier","array","generateCodeChallenge","verifier","data","digest","jsx","defaultActions","initUniDir","config","actions","uniDirActions","getSession","req","cookieHeader","sessionToken","parse","decrypt","action","effectiveDeviceId","returnTo","verifier","generateCodeVerifier","challenge","generateCodeChallenge","url","response","NextResponse","session","code","deviceIdToUse","tokens","encryptedSession","encrypt","Component","props","headers","redirect","pathname","search"]}
|
package/dist/types.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";var e=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var o=Object.prototype.hasOwnProperty;var l=(r,i,g,n)=>{if(i&&typeof i=="object"||typeof i=="function")for(let t of c(i))!o.call(r,t)&&t!==g&&e(r,t,{get:()=>i[t],enumerable:!(n=s(i,t))||n.enumerable});return r};var a=r=>l(e({},"__esModule",{value:!0}),r);var d={};module.exports=a(d);
|
|
3
|
+
//# sourceMappingURL=types.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export interface UniDirConfig {\r\n domain: string;\r\n clientId: string;\r\n clientSecret: string;\r\n secret: string;\r\n redirectUri: string;\r\n logoutRedirectUri?: string;\r\n deviceId?: string;\r\n scope?: string;\r\n audience?: string;\r\n jwks?: string;\r\n issuer?: string;\r\n}\r\n\r\nexport interface UniDirAction {\r\n login: string;\r\n loginPath: string;\r\n logout: string;\r\n callback: string;\r\n me: string;\r\n}\r\n"],"mappings":";+WAAA,IAAAA,EAAA,kBAAAC,EAAAD","names":["types_exports","__toCommonJS"]}
|
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface UniDirConfig {
|
|
2
|
+
domain: string;
|
|
3
|
+
clientId: string;
|
|
4
|
+
clientSecret: string;
|
|
5
|
+
secret: string;
|
|
6
|
+
redirectUri: string;
|
|
7
|
+
logoutRedirectUri?: string;
|
|
8
|
+
deviceId?: string;
|
|
9
|
+
scope?: string;
|
|
10
|
+
audience?: string;
|
|
11
|
+
jwks?: string;
|
|
12
|
+
issuer?: string;
|
|
13
|
+
}
|
|
14
|
+
interface UniDirAction {
|
|
15
|
+
login: string;
|
|
16
|
+
loginPath: string;
|
|
17
|
+
logout: string;
|
|
18
|
+
callback: string;
|
|
19
|
+
me: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type { UniDirAction, UniDirConfig };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface UniDirConfig {
|
|
2
|
+
domain: string;
|
|
3
|
+
clientId: string;
|
|
4
|
+
clientSecret: string;
|
|
5
|
+
secret: string;
|
|
6
|
+
redirectUri: string;
|
|
7
|
+
logoutRedirectUri?: string;
|
|
8
|
+
deviceId?: string;
|
|
9
|
+
scope?: string;
|
|
10
|
+
audience?: string;
|
|
11
|
+
jwks?: string;
|
|
12
|
+
issuer?: string;
|
|
13
|
+
}
|
|
14
|
+
interface UniDirAction {
|
|
15
|
+
login: string;
|
|
16
|
+
loginPath: string;
|
|
17
|
+
logout: string;
|
|
18
|
+
callback: string;
|
|
19
|
+
me: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type { UniDirAction, UniDirConfig };
|
package/dist/types.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unidir/unidir-nextjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "./dist/index.cjs",
|
|
6
|
-
"module": "./dist/index.mjs",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
5
|
"files": [
|
|
9
6
|
"dist"
|
|
10
7
|
],
|
|
@@ -12,14 +9,22 @@
|
|
|
12
9
|
"access": "public"
|
|
13
10
|
},
|
|
14
11
|
"exports": {
|
|
15
|
-
"
|
|
16
|
-
"types": "./dist/
|
|
17
|
-
"import": "./dist/
|
|
18
|
-
"require": "./dist/
|
|
12
|
+
"./server": {
|
|
13
|
+
"types": "./dist/server.d.ts",
|
|
14
|
+
"import": "./dist/server.mjs",
|
|
15
|
+
"require": "./dist/server.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./client": {
|
|
18
|
+
"types": "./dist/client.d.ts",
|
|
19
|
+
"import": "./dist/client.mjs",
|
|
20
|
+
"require": "./dist/client.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./types": {
|
|
23
|
+
"types": "./dist/types.d.ts"
|
|
19
24
|
}
|
|
20
25
|
},
|
|
21
26
|
"scripts": {
|
|
22
|
-
"build": "tsup
|
|
27
|
+
"build": "tsup",
|
|
23
28
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch --external react,next"
|
|
24
29
|
},
|
|
25
30
|
"peerDependencies": {
|
package/dist/index.cjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";var M=Object.create;var h=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var F=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var B=(e,r)=>{for(var n in r)h(e,n,{get:r[n],enumerable:!0})},x=(e,r,n,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let t of Y(r))!G.call(e,t)&&t!==n&&h(e,t,{get:()=>r[t],enumerable:!(a=z(r,t))||a.enumerable});return e};var Q=(e,r,n)=>(n=e!=null?M(F(e)):{},x(r||!e||!e.__esModule?h(n,"default",{value:e,enumerable:!0}):n,e)),X=e=>x(h({},"__esModule",{value:!0}),e);var ee={};B(ee,{UserProvider:()=>N,getDeviceId:()=>b,initUniDir:()=>q,useUser:()=>j});module.exports=X(ee);var R=require("cookie");var y=require("jose"),I=e=>new TextEncoder().encode(e.padEnd(32,"0").slice(0,32));async function P(e,r){return new y.EncryptJWT(e).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setIssuedAt().setExpirationTime("24h").encrypt(I(r))}async function w(e,r){try{let{payload:n}=await(0,y.jwtDecrypt)(e,I(r));return n}catch{return null}}var u=require("next/server"),S=require("next/navigation");function T(){let e=new Uint8Array(32);return crypto.getRandomValues(e),btoa(String.fromCharCode(...e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function C(e){let n=new TextEncoder().encode(e),a=await crypto.subtle.digest("SHA-256",n);return btoa(String.fromCharCode(...new Uint8Array(a))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}var A=require("react/jsx-runtime"),Z={login:"login",loginPath:"/api/auth/login",logout:"logout",callback:"callback",me:"me"};function q(e,r){let n={...Z,...r},a=async t=>{let s=t.headers.get("cookie")||"",o=(0,R.parse)(s).unidir_session;return o?await w(o,e.secret):null};return{handleAuth:()=>async t=>{let s=t.nextUrl.pathname.split("/").pop(),o=t.nextUrl.searchParams.get("device_id")||e.deviceId||"unknown-device";if(s===n.login){let c=t.nextUrl.searchParams.get("returnTo")||"/",l=T(),k=await C(l),d=new URL(`${e.domain}/authorize`);d.searchParams.set("client_id",e.clientId),d.searchParams.set("response_type","code"),d.searchParams.set("redirect_uri",e.redirectUri),d.searchParams.set("scope","openid profile email"),d.searchParams.set("code_challenge",k),d.searchParams.set("code_challenge_method","S256"),o&&d.searchParams.set("device_id",o);let g=u.NextResponse.redirect(d.toString());return g.cookies.set("unidir_pkce_verifier",l,{httpOnly:!0,secure:!0,sameSite:"lax",maxAge:300}),g.cookies.set("unidir_device_id",o,{httpOnly:!0,secure:!0,maxAge:600}),g.cookies.set("unidir_return_to",c,{httpOnly:!0,maxAge:300}),g}if(s===n.me){let c=await a(t);return c?u.NextResponse.json(c):new u.NextResponse(JSON.stringify({user:null}),{status:401})}if(s===n.logout){let c=u.NextResponse.redirect(new URL("/",t.url));return c.cookies.delete("unidir_session"),c}if(s==="callback"){let c=t.nextUrl.searchParams.get("code"),l=t.cookies.get("unidir_pkce_verifier")?.value;if(!c||!l)return new u.NextResponse("Missing code or verifier",{status:400});let d=t.cookies.get("unidir_device_id")?.value||o,m=await(await fetch(`${e.domain}/token`,{method:"POST",headers:{"Content-Type":"application/json","x-device-id":d},body:JSON.stringify({grant_type:"authorization_code",client_id:e.clientId,client_secret:e.clientSecret,code:c,code_verifier:l,redirect_uri:e.redirectUri,device_id:d})})).json();if(m.error)return u.NextResponse.json(m,{status:400});let U=await P(m,e.secret),v=t.cookies.get("unidir_return_to")?.value||"/",f=u.NextResponse.redirect(new URL(v,t.url));return f.cookies.delete("unidir_pkce_verifier"),f.cookies.set("unidir_session",U,{httpOnly:!0,secure:!0,sameSite:"lax",maxAge:3600*24}),f}return new u.NextResponse("Not Found",{status:404})},getSession:a,withPageAuthRequired:t=>async s=>{let{headers:p}=await import("next/headers"),o=await a({headers:await p()});return o||(0,S.redirect)(n.loginPath),(0,A.jsx)(t,{...s,user:o})},withMiddlewareAuth:()=>async t=>{let s=t.cookies.get("unidir_session")?.value;if(!(s?await w(s,e.secret):null)){let{pathname:o,search:c}=t.nextUrl,l=new URL(n.loginPath,t.url);return l.searchParams.set("returnTo",`${o}${c}`),u.NextResponse.redirect(l)}return u.NextResponse.next()}}}var i=require("react");var _=require("jose");async function D(e,r,n={}){let a=(0,_.createRemoteJWKSet)(new URL(r)),{payload:t}=await(0,_.jwtVerify)(e,a,{issuer:n.issuer,audience:n.audience});return t}var L=require("react/jsx-runtime"),E=(0,i.createContext)({user:null,isLoading:!0,config:null});function N({children:e,config:r}){let[n,a]=(0,i.useState)(null),[t,s]=(0,i.useState)(!0),[p,o]=(0,i.useState)(null),[c,l]=(0,i.useState)(null),[k,d]=(0,i.useState)(null),[g,m]=(0,i.useState)(null),[U,v]=(0,i.useState)(null),[f,te]=(0,i.useState)(null);return(0,i.useEffect)(()=>{async function O(){try{let J=await(await fetch("/api/auth/me")).json(),{companyId:W,domainId:V,email:$,email_verified:H,name:K}=await D(J.id_token,r.jwks||"https://oauth.igoodworks.com/jwks.json",{issuer:r.issuer||"http://oauth.unidir.igoodworks.com/",audience:r.clientId});a({companyId:W,domainId:V,email:$,email_verified:H,name:K})}finally{s(!1)}}O()},[]),(0,L.jsx)(E.Provider,{value:{user:n,isLoading:t,config:r},children:e})}function b(){if(typeof window>"u")return"server-default";let e=localStorage.getItem("unidir_device_id");return e||(e=crypto.randomUUID(),localStorage.setItem("unidir_device_id",e)),e}var j=()=>(0,i.useContext)(E);0&&(module.exports={UserProvider,getDeviceId,initUniDir,useUser});
|
|
3
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/server.tsx","../src/session.ts","../src/pkce.ts","../src/client.tsx","../src/jwks.ts"],"sourcesContent":["export * from \"./server\";\r\nexport { UserProvider, useUser, getDeviceId } from \"./client\";\r\n","import { parse } from \"cookie\";\r\nimport { encrypt, decrypt } from \"./session\";\r\nimport { NextRequest, NextResponse } from \"next/server\";\r\nimport { redirect } from \"next/navigation\";\r\nimport { generateCodeVerifier, generateCodeChallenge } from \"./pkce\";\r\n\r\nexport interface UniDirConfig {\r\n domain: string;\r\n clientId: string;\r\n clientSecret: string;\r\n secret: string;\r\n redirectUri: string;\r\n logoutRedirectUri?: string;\r\n deviceId?: string;\r\n scope?: string;\r\n audience?: string;\r\n jwks?: string;\r\n issuer?: string;\r\n}\r\n\r\nexport interface UniDirAction {\r\n login: string;\r\n loginPath: string;\r\n logout: string;\r\n callback: string;\r\n me: string;\r\n}\r\nconst defaultActions: UniDirAction = {\r\n login: \"login\",\r\n loginPath: \"/api/auth/login\",\r\n logout: \"logout\",\r\n callback: \"callback\",\r\n me: \"me\",\r\n};\r\n\r\nexport function initUniDir(config: UniDirConfig, actions?: UniDirAction) {\r\n const uniDirActions = { ...defaultActions, ...actions };\r\n\r\n const getSession = async (req: Request | NextRequest) => {\r\n const cookieHeader = req.headers.get(\"cookie\") || \"\";\r\n const cookies = parse(cookieHeader);\r\n const sessionToken = cookies[\"unidir_session\"];\r\n if (!sessionToken) return null;\r\n return await decrypt(sessionToken, config.secret);\r\n };\r\n\r\n return {\r\n handleAuth: () => async (req: NextRequest) => {\r\n const action = req.nextUrl.pathname.split(\"/\").pop();\r\n // Capture the deviceId from the query param sent by the LoginButton\r\n const queryDeviceId = req.nextUrl.searchParams.get(\"device_id\");\r\n const effectiveDeviceId =\r\n queryDeviceId || config.deviceId || \"unknown-device\";\r\n //const deviceId = req.headers.get(\"x-device-id\");\r\n\r\n if (action === uniDirActions.login) {\r\n const returnTo = req.nextUrl.searchParams.get(\"returnTo\") || \"/\";\r\n const verifier = generateCodeVerifier();\r\n const challenge = await generateCodeChallenge(verifier);\r\n\r\n const url = new URL(`${config.domain}/authorize`);\r\n url.searchParams.set(\"client_id\", config.clientId);\r\n url.searchParams.set(\"response_type\", \"code\");\r\n url.searchParams.set(\"redirect_uri\", config.redirectUri);\r\n url.searchParams.set(\"scope\", \"openid profile email\");\r\n url.searchParams.set(\"code_challenge\", challenge);\r\n url.searchParams.set(\"code_challenge_method\", \"S256\");\r\n if (effectiveDeviceId) {\r\n url.searchParams.set(\"device_id\", effectiveDeviceId);\r\n }\r\n const response = NextResponse.redirect(url.toString());\r\n\r\n // Store verifier in a short-lived, secure cookie\r\n response.cookies.set(\"unidir_pkce_verifier\", verifier, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n maxAge: 60 * 5, // 5 minutes\r\n });\r\n response.cookies.set(\"unidir_device_id\", effectiveDeviceId, {\r\n httpOnly: true,\r\n secure: true,\r\n maxAge: 60 * 10, // 10 minutes\r\n });\r\n response.cookies.set(\"unidir_return_to\", returnTo, {\r\n httpOnly: true,\r\n maxAge: 60 * 5,\r\n });\r\n return response;\r\n }\r\n // Profile Handler (for useUser hook)\r\n if (action === uniDirActions.me) {\r\n const session = await getSession(req);\r\n if (!session)\r\n return new NextResponse(JSON.stringify({ user: null }), {\r\n status: 401,\r\n });\r\n return NextResponse.json(session);\r\n }\r\n\r\n // Logout Handler\r\n if (action === uniDirActions.logout) {\r\n const response = NextResponse.redirect(new URL(\"/\", req.url));\r\n response.cookies.delete(\"unidir_session\");\r\n return response;\r\n }\r\n if (action === \"callback\") {\r\n const code = req.nextUrl.searchParams.get(\"code\");\r\n const verifier = req.cookies.get(\"unidir_pkce_verifier\")?.value;\r\n\r\n if (!code || !verifier) {\r\n return new NextResponse(\"Missing code or verifier\", { status: 400 });\r\n }\r\n\r\n const storedDeviceId = req.cookies.get(\"unidir_device_id\")?.value;\r\n const deviceIdToUse = storedDeviceId || effectiveDeviceId;\r\n\r\n const res = await fetch(`${config.domain}/token`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-device-id\": deviceIdToUse, // Added to header\r\n },\r\n body: JSON.stringify({\r\n grant_type: \"authorization_code\",\r\n client_id: config.clientId,\r\n client_secret: config.clientSecret,\r\n code,\r\n code_verifier: verifier, // Pass the verifier back\r\n redirect_uri: config.redirectUri,\r\n device_id: deviceIdToUse,\r\n }),\r\n });\r\n\r\n const tokens = await res.json();\r\n if (tokens.error) return NextResponse.json(tokens, { status: 400 });\r\n\r\n const encryptedSession = await encrypt(tokens, config.secret);\r\n // const response = NextResponse.redirect(new URL(\"/\", req.url));\r\n const returnTo = req.cookies.get(\"unidir_return_to\")?.value || \"/\";\r\n const response = NextResponse.redirect(new URL(returnTo, req.url));\r\n\r\n // Clean up PKCE cookie and set session\r\n response.cookies.delete(\"unidir_pkce_verifier\");\r\n response.cookies.set(\"unidir_session\", encryptedSession, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n maxAge: 60 * 60 * 24,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n return new NextResponse(\"Not Found\", { status: 404 });\r\n },\r\n\r\n getSession,\r\n\r\n withPageAuthRequired: <P extends object>(\r\n Component: React.ComponentType<P>\r\n ) => {\r\n return async (props: P) => {\r\n // Import headers dynamically to avoid issues in non-server environments\r\n const { headers } = await import(\"next/headers\");\r\n const session = await getSession({ headers: await headers() } as any);\r\n\r\n if (!session) {\r\n redirect(uniDirActions.loginPath);\r\n }\r\n\r\n // Return the component as JSX\r\n return <Component {...props} user={session} />;\r\n };\r\n },\r\n\r\n withMiddlewareAuth: () => {\r\n return async (req: NextRequest) => {\r\n const sessionToken = req.cookies.get(\"unidir_session\")?.value;\r\n const session = sessionToken\r\n ? await decrypt(sessionToken, config.secret)\r\n : null;\r\n\r\n if (!session) {\r\n // Redirect to login but save the current URL to return back later\r\n const { pathname, search } = req.nextUrl;\r\n const url = new URL(uniDirActions.loginPath, req.url);\r\n url.searchParams.set(\"returnTo\", `${pathname}${search}`);\r\n return NextResponse.redirect(url);\r\n }\r\n\r\n return NextResponse.next();\r\n };\r\n },\r\n };\r\n}\r\n","import { EncryptJWT, jwtDecrypt } from \"jose\";\r\n\r\nconst getSecretKey = (secret: string) =>\r\n new TextEncoder().encode(secret.padEnd(32, \"0\").slice(0, 32));\r\n\r\nexport async function encrypt(payload: any, secret: string) {\r\n return new EncryptJWT(payload)\r\n .setProtectedHeader({ alg: \"dir\", enc: \"A256GCM\" })\r\n .setIssuedAt()\r\n .setExpirationTime(\"24h\")\r\n .encrypt(getSecretKey(secret));\r\n}\r\n\r\nexport async function decrypt(token: string, secret: string) {\r\n try {\r\n const { payload } = await jwtDecrypt(token, getSecretKey(secret));\r\n return payload;\r\n } catch (e) {\r\n return null;\r\n }\r\n}\r\n","export function generateCodeVerifier(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return btoa(String.fromCharCode(...array))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n}\r\n\r\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\r\n return btoa(String.fromCharCode(...new Uint8Array(digest)))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n}\r\n","\"use client\";\r\nimport React, { createContext, useContext, useState, useEffect } from \"react\";\r\nimport { verifyAccessToken } from \"./jwks\";\r\nimport { JWTPayload } from \"jose\";\r\nimport { UniDirConfig } from \"./server\";\r\n\r\nconst UserContext = createContext<{\r\n user: any;\r\n isLoading: boolean;\r\n config: UniDirConfig | null;\r\n}>({ user: null, isLoading: true, config: null });\r\n\r\nexport function UserProvider({\r\n children,\r\n config,\r\n}: {\r\n children: React.ReactNode;\r\n config: UniDirConfig;\r\n}) {\r\n const [user, setUser] = useState<JWTPayload | null>(null);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [token, setToken] = useState(null);\r\n const [accessToken, setAccessToken] = useState(null);\r\n const [refreshToken, setRefreshToken] = useState(null);\r\n const [idToken, setIdToken] = useState(null);\r\n const [client, setClient] = useState(null);\r\n const [expiresIn, setExpiresIn] = useState(null);\r\n\r\n // useEffect(() => {\r\n // fetch(\"/api/auth/me\")\r\n // .then((res) => res.json())\r\n // .then((data) => {\r\n // if (data) {\r\n // setUser(data.client);\r\n // setToken(data);\r\n // setAccessToken(data.access_token);\r\n // setRefreshToken(data.refresh_token);\r\n // const idTokenAll = await jwtVerify(\r\n // data.id_token,\r\n // config.jwks || \"https://oauth.biocloud.pro/jwks.json\"\r\n // );\r\n // setIdToken(data.id_token);\r\n // setClient(data.client);\r\n // setExpiresIn(data.expres_in);\r\n // }\r\n // })\r\n // .catch(() => setUser(null));\r\n // }, []);\r\n useEffect(() => {\r\n async function loadUser() {\r\n try {\r\n const res = await fetch(\"/api/auth/me\");\r\n const data = await res.json();\r\n //setUser(data.user);\r\n const { companyId, domainId, email, email_verified, name } =\r\n await verifyAccessToken(\r\n data.id_token,\r\n config.jwks || \"https://oauth.igoodworks.com/jwks.json\",\r\n {\r\n issuer: config.issuer || \"http://oauth.unidir.igoodworks.com/\",\r\n audience: config.clientId,\r\n }\r\n );\r\n setUser({ companyId, domainId, email, email_verified, name });\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }\r\n loadUser();\r\n }, []);\r\n return (\r\n <UserContext.Provider\r\n value={{\r\n user,\r\n isLoading,\r\n config,\r\n // token,\r\n // expiresIn,\r\n // accessToken,\r\n // refreshToken,\r\n // client,\r\n // idToken,\r\n }}\r\n >\r\n {children}\r\n </UserContext.Provider>\r\n );\r\n}\r\n\r\nexport function getDeviceId(): string {\r\n if (typeof window === \"undefined\") return \"server-default\";\r\n\r\n let id = localStorage.getItem(\"unidir_device_id\");\r\n if (!id) {\r\n id = crypto.randomUUID();\r\n localStorage.setItem(\"unidir_device_id\", id);\r\n }\r\n return id;\r\n}\r\n\r\nexport const useUser = () => useContext(UserContext);\r\n","import { jwtVerify, createRemoteJWKSet } from \"jose\";\r\n\r\n// Replace with your IdP issuer and audience\r\nconst ISSUER = \"https://YOUR_ISSUER/\";\r\nconst AUDIENCE = \"YOUR_CLIENT_ID\";\r\n\r\nexport async function verifyAccessToken(\r\n token: string,\r\n jwksUrl: string,\r\n options: Record<string, any> = {}\r\n) {\r\n const JWKS = createRemoteJWKSet(new URL(jwksUrl));\r\n const { payload } = await jwtVerify(token, JWKS, {\r\n issuer: options.issuer,\r\n audience: options.audience,\r\n });\r\n // Optionally apply custom claims checks here (e.g., roles, scopes)\r\n return payload;\r\n}\r\n"],"mappings":"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","names":["index_exports","__export","UserProvider","getDeviceId","initUniDir","useUser","__toCommonJS","import_cookie","import_jose","getSecretKey","secret","encrypt","payload","decrypt","token","import_server","import_navigation","generateCodeVerifier","array","generateCodeChallenge","verifier","data","digest","import_jsx_runtime","defaultActions","initUniDir","config","actions","uniDirActions","getSession","req","cookieHeader","sessionToken","decrypt","action","effectiveDeviceId","returnTo","verifier","generateCodeVerifier","challenge","generateCodeChallenge","url","response","session","code","deviceIdToUse","tokens","encryptedSession","encrypt","Component","props","headers","pathname","search","import_react","import_jose","verifyAccessToken","token","jwksUrl","options","JWKS","payload","import_jsx_runtime","UserContext","UserProvider","children","config","user","setUser","isLoading","setIsLoading","token","setToken","accessToken","setAccessToken","refreshToken","setRefreshToken","idToken","setIdToken","client","setClient","expiresIn","setExpiresIn","loadUser","data","companyId","domainId","email","email_verified","name","verifyAccessToken","getDeviceId","id","useUser"]}
|
package/dist/index.d.cts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import * as jose from 'jose';
|
|
3
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
-
import React$1 from 'react';
|
|
5
|
-
|
|
6
|
-
interface UniDirConfig {
|
|
7
|
-
domain: string;
|
|
8
|
-
clientId: string;
|
|
9
|
-
clientSecret: string;
|
|
10
|
-
secret: string;
|
|
11
|
-
redirectUri: string;
|
|
12
|
-
logoutRedirectUri?: string;
|
|
13
|
-
deviceId?: string;
|
|
14
|
-
scope?: string;
|
|
15
|
-
audience?: string;
|
|
16
|
-
jwks?: string;
|
|
17
|
-
issuer?: string;
|
|
18
|
-
}
|
|
19
|
-
interface UniDirAction {
|
|
20
|
-
login: string;
|
|
21
|
-
loginPath: string;
|
|
22
|
-
logout: string;
|
|
23
|
-
callback: string;
|
|
24
|
-
me: string;
|
|
25
|
-
}
|
|
26
|
-
declare function initUniDir(config: UniDirConfig, actions?: UniDirAction): {
|
|
27
|
-
handleAuth: () => (req: NextRequest) => Promise<NextResponse<any>>;
|
|
28
|
-
getSession: (req: Request | NextRequest) => Promise<jose.JWTPayload | null>;
|
|
29
|
-
withPageAuthRequired: <P extends object>(Component: React.ComponentType<P>) => (props: P) => Promise<react_jsx_runtime.JSX.Element>;
|
|
30
|
-
withMiddlewareAuth: () => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
declare function UserProvider({ children, config, }: {
|
|
34
|
-
children: React$1.ReactNode;
|
|
35
|
-
config: UniDirConfig;
|
|
36
|
-
}): react_jsx_runtime.JSX.Element;
|
|
37
|
-
declare function getDeviceId(): string;
|
|
38
|
-
declare const useUser: () => {
|
|
39
|
-
user: any;
|
|
40
|
-
isLoading: boolean;
|
|
41
|
-
config: UniDirConfig | null;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export { type UniDirAction, type UniDirConfig, UserProvider, getDeviceId, initUniDir, useUser };
|
package/dist/index.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import * as jose from 'jose';
|
|
3
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
-
import React$1 from 'react';
|
|
5
|
-
|
|
6
|
-
interface UniDirConfig {
|
|
7
|
-
domain: string;
|
|
8
|
-
clientId: string;
|
|
9
|
-
clientSecret: string;
|
|
10
|
-
secret: string;
|
|
11
|
-
redirectUri: string;
|
|
12
|
-
logoutRedirectUri?: string;
|
|
13
|
-
deviceId?: string;
|
|
14
|
-
scope?: string;
|
|
15
|
-
audience?: string;
|
|
16
|
-
jwks?: string;
|
|
17
|
-
issuer?: string;
|
|
18
|
-
}
|
|
19
|
-
interface UniDirAction {
|
|
20
|
-
login: string;
|
|
21
|
-
loginPath: string;
|
|
22
|
-
logout: string;
|
|
23
|
-
callback: string;
|
|
24
|
-
me: string;
|
|
25
|
-
}
|
|
26
|
-
declare function initUniDir(config: UniDirConfig, actions?: UniDirAction): {
|
|
27
|
-
handleAuth: () => (req: NextRequest) => Promise<NextResponse<any>>;
|
|
28
|
-
getSession: (req: Request | NextRequest) => Promise<jose.JWTPayload | null>;
|
|
29
|
-
withPageAuthRequired: <P extends object>(Component: React.ComponentType<P>) => (props: P) => Promise<react_jsx_runtime.JSX.Element>;
|
|
30
|
-
withMiddlewareAuth: () => (req: NextRequest) => Promise<NextResponse<unknown>>;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
declare function UserProvider({ children, config, }: {
|
|
34
|
-
children: React$1.ReactNode;
|
|
35
|
-
config: UniDirConfig;
|
|
36
|
-
}): react_jsx_runtime.JSX.Element;
|
|
37
|
-
declare function getDeviceId(): string;
|
|
38
|
-
declare const useUser: () => {
|
|
39
|
-
user: any;
|
|
40
|
-
isLoading: boolean;
|
|
41
|
-
config: UniDirConfig | null;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export { type UniDirAction, type UniDirConfig, UserProvider, getDeviceId, initUniDir, useUser };
|
package/dist/index.mjs
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import{parse as j}from"cookie";import{EncryptJWT as N,jwtDecrypt as b}from"jose";var w=e=>new TextEncoder().encode(e.padEnd(32,"0").slice(0,32));async function U(e,n){return new N(e).setProtectedHeader({alg:"dir",enc:"A256GCM"}).setIssuedAt().setExpirationTime("24h").encrypt(w(n))}async function y(e,n){try{let{payload:r}=await b(e,w(n));return r}catch{return null}}import{NextResponse as a}from"next/server";import{redirect as L}from"next/navigation";function v(){let e=new Uint8Array(32);return crypto.getRandomValues(e),btoa(String.fromCharCode(...e)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function x(e){let r=new TextEncoder().encode(e),d=await crypto.subtle.digest("SHA-256",r);return btoa(String.fromCharCode(...new Uint8Array(d))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}import{jsx as J}from"react/jsx-runtime";var O={login:"login",loginPath:"/api/auth/login",logout:"logout",callback:"callback",me:"me"};function se(e,n){let r={...O,...n},d=async t=>{let i=t.headers.get("cookie")||"",s=j(i).unidir_session;return s?await y(s,e.secret):null};return{handleAuth:()=>async t=>{let i=t.nextUrl.pathname.split("/").pop(),s=t.nextUrl.searchParams.get("device_id")||e.deviceId||"unknown-device";if(i===r.login){let o=t.nextUrl.searchParams.get("returnTo")||"/",u=v(),h=await x(u),c=new URL(`${e.domain}/authorize`);c.searchParams.set("client_id",e.clientId),c.searchParams.set("response_type","code"),c.searchParams.set("redirect_uri",e.redirectUri),c.searchParams.set("scope","openid profile email"),c.searchParams.set("code_challenge",h),c.searchParams.set("code_challenge_method","S256"),s&&c.searchParams.set("device_id",s);let g=a.redirect(c.toString());return g.cookies.set("unidir_pkce_verifier",u,{httpOnly:!0,secure:!0,sameSite:"lax",maxAge:300}),g.cookies.set("unidir_device_id",s,{httpOnly:!0,secure:!0,maxAge:600}),g.cookies.set("unidir_return_to",o,{httpOnly:!0,maxAge:300}),g}if(i===r.me){let o=await d(t);return o?a.json(o):new a(JSON.stringify({user:null}),{status:401})}if(i===r.logout){let o=a.redirect(new URL("/",t.url));return o.cookies.delete("unidir_session"),o}if(i==="callback"){let o=t.nextUrl.searchParams.get("code"),u=t.cookies.get("unidir_pkce_verifier")?.value;if(!o||!u)return new a("Missing code or verifier",{status:400});let c=t.cookies.get("unidir_device_id")?.value||s,m=await(await fetch(`${e.domain}/token`,{method:"POST",headers:{"Content-Type":"application/json","x-device-id":c},body:JSON.stringify({grant_type:"authorization_code",client_id:e.clientId,client_secret:e.clientSecret,code:o,code_verifier:u,redirect_uri:e.redirectUri,device_id:c})})).json();if(m.error)return a.json(m,{status:400});let _=await U(m,e.secret),k=t.cookies.get("unidir_return_to")?.value||"/",f=a.redirect(new URL(k,t.url));return f.cookies.delete("unidir_pkce_verifier"),f.cookies.set("unidir_session",_,{httpOnly:!0,secure:!0,sameSite:"lax",maxAge:3600*24}),f}return new a("Not Found",{status:404})},getSession:d,withPageAuthRequired:t=>async i=>{let{headers:p}=await import("next/headers"),s=await d({headers:await p()});return s||L(r.loginPath),J(t,{...i,user:s})},withMiddlewareAuth:()=>async t=>{let i=t.cookies.get("unidir_session")?.value;if(!(i?await y(i,e.secret):null)){let{pathname:s,search:o}=t.nextUrl,u=new URL(r.loginPath,t.url);return u.searchParams.set("returnTo",`${s}${o}`),a.redirect(u)}return a.next()}}}import{createContext as $,useContext as H,useState as l,useEffect as K}from"react";import{jwtVerify as W,createRemoteJWKSet as V}from"jose";async function I(e,n,r={}){let d=V(new URL(n)),{payload:t}=await W(e,d,{issuer:r.issuer,audience:r.audience});return t}import{jsx as F}from"react/jsx-runtime";var P=$({user:null,isLoading:!0,config:null});function M({children:e,config:n}){let[r,d]=l(null),[t,i]=l(!0),[p,s]=l(null),[o,u]=l(null),[h,c]=l(null),[g,m]=l(null),[_,k]=l(null),[f,G]=l(null);return K(()=>{async function T(){try{let C=await(await fetch("/api/auth/me")).json(),{companyId:R,domainId:S,email:A,email_verified:D,name:E}=await I(C.id_token,n.jwks||"https://oauth.igoodworks.com/jwks.json",{issuer:n.issuer||"http://oauth.unidir.igoodworks.com/",audience:n.clientId});d({companyId:R,domainId:S,email:A,email_verified:D,name:E})}finally{i(!1)}}T()},[]),F(P.Provider,{value:{user:r,isLoading:t,config:n},children:e})}function z(){if(typeof window>"u")return"server-default";let e=localStorage.getItem("unidir_device_id");return e||(e=crypto.randomUUID(),localStorage.setItem("unidir_device_id",e)),e}var Y=()=>H(P);export{M as UserProvider,z as getDeviceId,se as initUniDir,Y as useUser};
|
|
3
|
-
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.tsx","../src/session.ts","../src/pkce.ts","../src/client.tsx","../src/jwks.ts"],"sourcesContent":["import { parse } from \"cookie\";\r\nimport { encrypt, decrypt } from \"./session\";\r\nimport { NextRequest, NextResponse } from \"next/server\";\r\nimport { redirect } from \"next/navigation\";\r\nimport { generateCodeVerifier, generateCodeChallenge } from \"./pkce\";\r\n\r\nexport interface UniDirConfig {\r\n domain: string;\r\n clientId: string;\r\n clientSecret: string;\r\n secret: string;\r\n redirectUri: string;\r\n logoutRedirectUri?: string;\r\n deviceId?: string;\r\n scope?: string;\r\n audience?: string;\r\n jwks?: string;\r\n issuer?: string;\r\n}\r\n\r\nexport interface UniDirAction {\r\n login: string;\r\n loginPath: string;\r\n logout: string;\r\n callback: string;\r\n me: string;\r\n}\r\nconst defaultActions: UniDirAction = {\r\n login: \"login\",\r\n loginPath: \"/api/auth/login\",\r\n logout: \"logout\",\r\n callback: \"callback\",\r\n me: \"me\",\r\n};\r\n\r\nexport function initUniDir(config: UniDirConfig, actions?: UniDirAction) {\r\n const uniDirActions = { ...defaultActions, ...actions };\r\n\r\n const getSession = async (req: Request | NextRequest) => {\r\n const cookieHeader = req.headers.get(\"cookie\") || \"\";\r\n const cookies = parse(cookieHeader);\r\n const sessionToken = cookies[\"unidir_session\"];\r\n if (!sessionToken) return null;\r\n return await decrypt(sessionToken, config.secret);\r\n };\r\n\r\n return {\r\n handleAuth: () => async (req: NextRequest) => {\r\n const action = req.nextUrl.pathname.split(\"/\").pop();\r\n // Capture the deviceId from the query param sent by the LoginButton\r\n const queryDeviceId = req.nextUrl.searchParams.get(\"device_id\");\r\n const effectiveDeviceId =\r\n queryDeviceId || config.deviceId || \"unknown-device\";\r\n //const deviceId = req.headers.get(\"x-device-id\");\r\n\r\n if (action === uniDirActions.login) {\r\n const returnTo = req.nextUrl.searchParams.get(\"returnTo\") || \"/\";\r\n const verifier = generateCodeVerifier();\r\n const challenge = await generateCodeChallenge(verifier);\r\n\r\n const url = new URL(`${config.domain}/authorize`);\r\n url.searchParams.set(\"client_id\", config.clientId);\r\n url.searchParams.set(\"response_type\", \"code\");\r\n url.searchParams.set(\"redirect_uri\", config.redirectUri);\r\n url.searchParams.set(\"scope\", \"openid profile email\");\r\n url.searchParams.set(\"code_challenge\", challenge);\r\n url.searchParams.set(\"code_challenge_method\", \"S256\");\r\n if (effectiveDeviceId) {\r\n url.searchParams.set(\"device_id\", effectiveDeviceId);\r\n }\r\n const response = NextResponse.redirect(url.toString());\r\n\r\n // Store verifier in a short-lived, secure cookie\r\n response.cookies.set(\"unidir_pkce_verifier\", verifier, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n maxAge: 60 * 5, // 5 minutes\r\n });\r\n response.cookies.set(\"unidir_device_id\", effectiveDeviceId, {\r\n httpOnly: true,\r\n secure: true,\r\n maxAge: 60 * 10, // 10 minutes\r\n });\r\n response.cookies.set(\"unidir_return_to\", returnTo, {\r\n httpOnly: true,\r\n maxAge: 60 * 5,\r\n });\r\n return response;\r\n }\r\n // Profile Handler (for useUser hook)\r\n if (action === uniDirActions.me) {\r\n const session = await getSession(req);\r\n if (!session)\r\n return new NextResponse(JSON.stringify({ user: null }), {\r\n status: 401,\r\n });\r\n return NextResponse.json(session);\r\n }\r\n\r\n // Logout Handler\r\n if (action === uniDirActions.logout) {\r\n const response = NextResponse.redirect(new URL(\"/\", req.url));\r\n response.cookies.delete(\"unidir_session\");\r\n return response;\r\n }\r\n if (action === \"callback\") {\r\n const code = req.nextUrl.searchParams.get(\"code\");\r\n const verifier = req.cookies.get(\"unidir_pkce_verifier\")?.value;\r\n\r\n if (!code || !verifier) {\r\n return new NextResponse(\"Missing code or verifier\", { status: 400 });\r\n }\r\n\r\n const storedDeviceId = req.cookies.get(\"unidir_device_id\")?.value;\r\n const deviceIdToUse = storedDeviceId || effectiveDeviceId;\r\n\r\n const res = await fetch(`${config.domain}/token`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-device-id\": deviceIdToUse, // Added to header\r\n },\r\n body: JSON.stringify({\r\n grant_type: \"authorization_code\",\r\n client_id: config.clientId,\r\n client_secret: config.clientSecret,\r\n code,\r\n code_verifier: verifier, // Pass the verifier back\r\n redirect_uri: config.redirectUri,\r\n device_id: deviceIdToUse,\r\n }),\r\n });\r\n\r\n const tokens = await res.json();\r\n if (tokens.error) return NextResponse.json(tokens, { status: 400 });\r\n\r\n const encryptedSession = await encrypt(tokens, config.secret);\r\n // const response = NextResponse.redirect(new URL(\"/\", req.url));\r\n const returnTo = req.cookies.get(\"unidir_return_to\")?.value || \"/\";\r\n const response = NextResponse.redirect(new URL(returnTo, req.url));\r\n\r\n // Clean up PKCE cookie and set session\r\n response.cookies.delete(\"unidir_pkce_verifier\");\r\n response.cookies.set(\"unidir_session\", encryptedSession, {\r\n httpOnly: true,\r\n secure: true,\r\n sameSite: \"lax\",\r\n maxAge: 60 * 60 * 24,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n return new NextResponse(\"Not Found\", { status: 404 });\r\n },\r\n\r\n getSession,\r\n\r\n withPageAuthRequired: <P extends object>(\r\n Component: React.ComponentType<P>\r\n ) => {\r\n return async (props: P) => {\r\n // Import headers dynamically to avoid issues in non-server environments\r\n const { headers } = await import(\"next/headers\");\r\n const session = await getSession({ headers: await headers() } as any);\r\n\r\n if (!session) {\r\n redirect(uniDirActions.loginPath);\r\n }\r\n\r\n // Return the component as JSX\r\n return <Component {...props} user={session} />;\r\n };\r\n },\r\n\r\n withMiddlewareAuth: () => {\r\n return async (req: NextRequest) => {\r\n const sessionToken = req.cookies.get(\"unidir_session\")?.value;\r\n const session = sessionToken\r\n ? await decrypt(sessionToken, config.secret)\r\n : null;\r\n\r\n if (!session) {\r\n // Redirect to login but save the current URL to return back later\r\n const { pathname, search } = req.nextUrl;\r\n const url = new URL(uniDirActions.loginPath, req.url);\r\n url.searchParams.set(\"returnTo\", `${pathname}${search}`);\r\n return NextResponse.redirect(url);\r\n }\r\n\r\n return NextResponse.next();\r\n };\r\n },\r\n };\r\n}\r\n","import { EncryptJWT, jwtDecrypt } from \"jose\";\r\n\r\nconst getSecretKey = (secret: string) =>\r\n new TextEncoder().encode(secret.padEnd(32, \"0\").slice(0, 32));\r\n\r\nexport async function encrypt(payload: any, secret: string) {\r\n return new EncryptJWT(payload)\r\n .setProtectedHeader({ alg: \"dir\", enc: \"A256GCM\" })\r\n .setIssuedAt()\r\n .setExpirationTime(\"24h\")\r\n .encrypt(getSecretKey(secret));\r\n}\r\n\r\nexport async function decrypt(token: string, secret: string) {\r\n try {\r\n const { payload } = await jwtDecrypt(token, getSecretKey(secret));\r\n return payload;\r\n } catch (e) {\r\n return null;\r\n }\r\n}\r\n","export function generateCodeVerifier(): string {\r\n const array = new Uint8Array(32);\r\n crypto.getRandomValues(array);\r\n return btoa(String.fromCharCode(...array))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n}\r\n\r\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(verifier);\r\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\r\n return btoa(String.fromCharCode(...new Uint8Array(digest)))\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n .replace(/=/g, \"\");\r\n}\r\n","\"use client\";\r\nimport React, { createContext, useContext, useState, useEffect } from \"react\";\r\nimport { verifyAccessToken } from \"./jwks\";\r\nimport { JWTPayload } from \"jose\";\r\nimport { UniDirConfig } from \"./server\";\r\n\r\nconst UserContext = createContext<{\r\n user: any;\r\n isLoading: boolean;\r\n config: UniDirConfig | null;\r\n}>({ user: null, isLoading: true, config: null });\r\n\r\nexport function UserProvider({\r\n children,\r\n config,\r\n}: {\r\n children: React.ReactNode;\r\n config: UniDirConfig;\r\n}) {\r\n const [user, setUser] = useState<JWTPayload | null>(null);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [token, setToken] = useState(null);\r\n const [accessToken, setAccessToken] = useState(null);\r\n const [refreshToken, setRefreshToken] = useState(null);\r\n const [idToken, setIdToken] = useState(null);\r\n const [client, setClient] = useState(null);\r\n const [expiresIn, setExpiresIn] = useState(null);\r\n\r\n // useEffect(() => {\r\n // fetch(\"/api/auth/me\")\r\n // .then((res) => res.json())\r\n // .then((data) => {\r\n // if (data) {\r\n // setUser(data.client);\r\n // setToken(data);\r\n // setAccessToken(data.access_token);\r\n // setRefreshToken(data.refresh_token);\r\n // const idTokenAll = await jwtVerify(\r\n // data.id_token,\r\n // config.jwks || \"https://oauth.biocloud.pro/jwks.json\"\r\n // );\r\n // setIdToken(data.id_token);\r\n // setClient(data.client);\r\n // setExpiresIn(data.expres_in);\r\n // }\r\n // })\r\n // .catch(() => setUser(null));\r\n // }, []);\r\n useEffect(() => {\r\n async function loadUser() {\r\n try {\r\n const res = await fetch(\"/api/auth/me\");\r\n const data = await res.json();\r\n //setUser(data.user);\r\n const { companyId, domainId, email, email_verified, name } =\r\n await verifyAccessToken(\r\n data.id_token,\r\n config.jwks || \"https://oauth.igoodworks.com/jwks.json\",\r\n {\r\n issuer: config.issuer || \"http://oauth.unidir.igoodworks.com/\",\r\n audience: config.clientId,\r\n }\r\n );\r\n setUser({ companyId, domainId, email, email_verified, name });\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }\r\n loadUser();\r\n }, []);\r\n return (\r\n <UserContext.Provider\r\n value={{\r\n user,\r\n isLoading,\r\n config,\r\n // token,\r\n // expiresIn,\r\n // accessToken,\r\n // refreshToken,\r\n // client,\r\n // idToken,\r\n }}\r\n >\r\n {children}\r\n </UserContext.Provider>\r\n );\r\n}\r\n\r\nexport function getDeviceId(): string {\r\n if (typeof window === \"undefined\") return \"server-default\";\r\n\r\n let id = localStorage.getItem(\"unidir_device_id\");\r\n if (!id) {\r\n id = crypto.randomUUID();\r\n localStorage.setItem(\"unidir_device_id\", id);\r\n }\r\n return id;\r\n}\r\n\r\nexport const useUser = () => useContext(UserContext);\r\n","import { jwtVerify, createRemoteJWKSet } from \"jose\";\r\n\r\n// Replace with your IdP issuer and audience\r\nconst ISSUER = \"https://YOUR_ISSUER/\";\r\nconst AUDIENCE = \"YOUR_CLIENT_ID\";\r\n\r\nexport async function verifyAccessToken(\r\n token: string,\r\n jwksUrl: string,\r\n options: Record<string, any> = {}\r\n) {\r\n const JWKS = createRemoteJWKSet(new URL(jwksUrl));\r\n const { payload } = await jwtVerify(token, JWKS, {\r\n issuer: options.issuer,\r\n audience: options.audience,\r\n });\r\n // Optionally apply custom claims checks here (e.g., roles, scopes)\r\n return payload;\r\n}\r\n"],"mappings":"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","names":["parse","EncryptJWT","jwtDecrypt","getSecretKey","secret","encrypt","payload","decrypt","token","NextResponse","redirect","generateCodeVerifier","array","generateCodeChallenge","verifier","data","digest","jsx","defaultActions","initUniDir","config","actions","uniDirActions","getSession","req","cookieHeader","sessionToken","parse","decrypt","action","effectiveDeviceId","returnTo","verifier","generateCodeVerifier","challenge","generateCodeChallenge","url","response","NextResponse","session","code","deviceIdToUse","tokens","encryptedSession","encrypt","Component","props","headers","redirect","pathname","search","createContext","useContext","useState","useEffect","jwtVerify","createRemoteJWKSet","verifyAccessToken","token","jwksUrl","options","JWKS","createRemoteJWKSet","payload","jwtVerify","jsx","UserContext","createContext","UserProvider","children","config","user","setUser","useState","isLoading","setIsLoading","token","setToken","accessToken","setAccessToken","refreshToken","setRefreshToken","idToken","setIdToken","client","setClient","expiresIn","setExpiresIn","useEffect","loadUser","data","companyId","domainId","email","email_verified","name","verifyAccessToken","getDeviceId","id","useUser","useContext"]}
|