@auditauth/next 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/guard.d.ts +10 -0
- package/dist/guard.js +49 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/sdk.d.ts +48 -0
- package/dist/sdk.js +298 -0
- package/dist/settings.d.ts +61 -0
- package/dist/settings.js +61 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.js +1 -0
- package/package.json +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nimibyte
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/guard.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SessionUser } from "./types";
|
|
2
|
+
type AuthContextValue = {
|
|
3
|
+
user: SessionUser | null;
|
|
4
|
+
};
|
|
5
|
+
declare const useAuditAuth: () => AuthContextValue;
|
|
6
|
+
type AuditAuthGuardProps = {
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
};
|
|
9
|
+
declare const AuditAuthGuard: (props: AuditAuthGuardProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
export { AuditAuthGuard, useAuditAuth };
|
package/dist/guard.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { SETTINGS } from "./settings";
|
|
5
|
+
const AuthContext = createContext(null);
|
|
6
|
+
const useAuditAuth = () => {
|
|
7
|
+
const ctx = useContext(AuthContext);
|
|
8
|
+
if (!ctx) {
|
|
9
|
+
throw new Error('useAuditAuth must be used within AuditAuthProvider');
|
|
10
|
+
}
|
|
11
|
+
return ctx;
|
|
12
|
+
};
|
|
13
|
+
const AuditAuthGuard = (props) => {
|
|
14
|
+
const [user, setUser] = useState(null);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
let cancelled = false;
|
|
17
|
+
const checkSession = async () => {
|
|
18
|
+
try {
|
|
19
|
+
const response = await fetch(SETTINGS.bff.paths.session, {
|
|
20
|
+
credentials: 'include',
|
|
21
|
+
cache: 'no-store',
|
|
22
|
+
});
|
|
23
|
+
if (cancelled)
|
|
24
|
+
return;
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
window.location.href = SETTINGS.bff.paths.login;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
setUser(data.user);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
window.location.href = SETTINGS.bff.paths.login;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
checkSession();
|
|
38
|
+
return () => {
|
|
39
|
+
cancelled = true;
|
|
40
|
+
};
|
|
41
|
+
}, []);
|
|
42
|
+
const value = useMemo(() => ({
|
|
43
|
+
user,
|
|
44
|
+
}), [user]);
|
|
45
|
+
if (!user)
|
|
46
|
+
return null;
|
|
47
|
+
return (_jsx(AuthContext.Provider, { value: value, children: props.children }));
|
|
48
|
+
};
|
|
49
|
+
export { AuditAuthGuard, useAuditAuth };
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import { AuditAuthConfig, CookieAdapter, Metric, SessionUser } from "./types";
|
|
3
|
+
declare class AuditAuthNext {
|
|
4
|
+
private config;
|
|
5
|
+
private cookies;
|
|
6
|
+
constructor(config: AuditAuthConfig, cookies: CookieAdapter);
|
|
7
|
+
private verifyAccessToken;
|
|
8
|
+
private getCookieTokens;
|
|
9
|
+
private setCookieTokens;
|
|
10
|
+
getSession(): SessionUser | null;
|
|
11
|
+
hasSession(): boolean;
|
|
12
|
+
private buildAuthUrl;
|
|
13
|
+
callback(request: NextRequest): Promise<{
|
|
14
|
+
ok: boolean;
|
|
15
|
+
url: string;
|
|
16
|
+
}>;
|
|
17
|
+
logout(): Promise<void>;
|
|
18
|
+
getPortalUrl(): Promise<{
|
|
19
|
+
ok: boolean;
|
|
20
|
+
url: null;
|
|
21
|
+
reason: string;
|
|
22
|
+
} | {
|
|
23
|
+
ok: boolean;
|
|
24
|
+
url: string;
|
|
25
|
+
reason: null;
|
|
26
|
+
}>;
|
|
27
|
+
private refresh;
|
|
28
|
+
request(path: string, init?: RequestInit): Promise<Response>;
|
|
29
|
+
private pushMetric;
|
|
30
|
+
middleware(_request: NextRequest): Promise<NextResponse<unknown>>;
|
|
31
|
+
getHandlers(): {
|
|
32
|
+
GET: (req: NextRequest, ctx: {
|
|
33
|
+
params: Promise<{
|
|
34
|
+
auditauth: string[];
|
|
35
|
+
}>;
|
|
36
|
+
}) => Promise<Response>;
|
|
37
|
+
POST: (req: Request, ctx: {
|
|
38
|
+
params: Promise<{
|
|
39
|
+
auditauth: string[];
|
|
40
|
+
}>;
|
|
41
|
+
}) => Promise<Response>;
|
|
42
|
+
};
|
|
43
|
+
metrics(payload: Metric): Promise<Response>;
|
|
44
|
+
}
|
|
45
|
+
declare const login: () => void;
|
|
46
|
+
declare const logout: () => void;
|
|
47
|
+
declare const goToPortal: () => void;
|
|
48
|
+
export { AuditAuthNext, login, logout, goToPortal };
|
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { importSPKI, jwtVerify } from 'jose';
|
|
3
|
+
import { SETTINGS } from "./settings";
|
|
4
|
+
/* -------------------------------------------------------------------------- */
|
|
5
|
+
/* KEYS */
|
|
6
|
+
/* -------------------------------------------------------------------------- */
|
|
7
|
+
let cachedKey = null;
|
|
8
|
+
/* -------------------------------------------------------------------------- */
|
|
9
|
+
/* MAIN CLASS */
|
|
10
|
+
/* -------------------------------------------------------------------------- */
|
|
11
|
+
class AuditAuthNext {
|
|
12
|
+
constructor(config, cookies) {
|
|
13
|
+
if (!cookies.get || !cookies.set) {
|
|
14
|
+
throw new Error('Missing cookie adapter');
|
|
15
|
+
}
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.cookies = cookies;
|
|
18
|
+
}
|
|
19
|
+
/* ------------------------------------------------------------------------ */
|
|
20
|
+
/* AUTH PRIMITIVES */
|
|
21
|
+
/* ------------------------------------------------------------------------ */
|
|
22
|
+
async verifyAccessToken(token) {
|
|
23
|
+
try {
|
|
24
|
+
cachedKey =
|
|
25
|
+
cachedKey ||
|
|
26
|
+
await importSPKI(SETTINGS.jwt_public_key, 'RS256');
|
|
27
|
+
await jwtVerify(token, cachedKey, {
|
|
28
|
+
issuer: SETTINGS.jwt_issuer,
|
|
29
|
+
audience: this.config.appId,
|
|
30
|
+
});
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
getCookieTokens() {
|
|
38
|
+
return {
|
|
39
|
+
access: this.cookies.get(SETTINGS.cookies.access.name),
|
|
40
|
+
refresh: this.cookies.get(SETTINGS.cookies.refresh.name),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
setCookieTokens(tokens) {
|
|
44
|
+
this.cookies.set(SETTINGS.cookies.access.name, tokens.at, SETTINGS.cookies.access.config);
|
|
45
|
+
this.cookies.set(SETTINGS.cookies.refresh.name, tokens.rt, SETTINGS.cookies.refresh.config);
|
|
46
|
+
}
|
|
47
|
+
/* ------------------------------------------------------------------------ */
|
|
48
|
+
/* SESSION HELPERS */
|
|
49
|
+
/* ------------------------------------------------------------------------ */
|
|
50
|
+
getSession() {
|
|
51
|
+
return JSON.parse(this.cookies.get(SETTINGS.cookies.session.name) || '{}')?.user || null;
|
|
52
|
+
}
|
|
53
|
+
hasSession() {
|
|
54
|
+
return !!this.cookies.get(SETTINGS.cookies.session.name);
|
|
55
|
+
}
|
|
56
|
+
/* ------------------------------------------------------------------------ */
|
|
57
|
+
/* AUTH FLOWS */
|
|
58
|
+
/* ------------------------------------------------------------------------ */
|
|
59
|
+
async buildAuthUrl() {
|
|
60
|
+
const response = await fetch(`${SETTINGS.domains.api}/apps/login`, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
headers: { 'x-api-key': this.config.apiKey },
|
|
63
|
+
});
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
throw new Error('invalid_app');
|
|
66
|
+
}
|
|
67
|
+
const { code, redirectUrl } = await response.json();
|
|
68
|
+
const url = new URL(redirectUrl);
|
|
69
|
+
url.searchParams.set('code', code);
|
|
70
|
+
return url;
|
|
71
|
+
}
|
|
72
|
+
async callback(request) {
|
|
73
|
+
const code = new URL(request.url).searchParams.get('code');
|
|
74
|
+
if (!code) {
|
|
75
|
+
return {
|
|
76
|
+
ok: false,
|
|
77
|
+
url: `${SETTINGS.domains.client}/auth/invalid?reason=wrong_config`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const response = await fetch(`${SETTINGS.domains.api}/auth/authorize`, {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
headers: { 'Content-Type': 'application/json' },
|
|
83
|
+
body: JSON.stringify({ code, client_type: 'server' }),
|
|
84
|
+
});
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
return {
|
|
87
|
+
ok: false,
|
|
88
|
+
url: `${SETTINGS.domains.client}/auth/invalid?reason=unauthorized`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const result = await response.json();
|
|
92
|
+
const session = {
|
|
93
|
+
user: {
|
|
94
|
+
_id: result.user._id.toString(),
|
|
95
|
+
email: result.user.email,
|
|
96
|
+
avatar: result.user.avatar,
|
|
97
|
+
name: result.user.name,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
this.cookies.set(SETTINGS.cookies.session.name, JSON.stringify(session), SETTINGS.cookies.session.config);
|
|
101
|
+
this.setCookieTokens({
|
|
102
|
+
at: result.access_token,
|
|
103
|
+
rt: result.refresh_token,
|
|
104
|
+
});
|
|
105
|
+
return { ok: true, url: this.config.redirectUrl };
|
|
106
|
+
}
|
|
107
|
+
async logout() {
|
|
108
|
+
const { access } = this.getCookieTokens();
|
|
109
|
+
if (access) {
|
|
110
|
+
await fetch(`${SETTINGS.domains.api}/auth/revoke`, {
|
|
111
|
+
method: 'GET',
|
|
112
|
+
headers: { Authorization: `Bearer ${access}` },
|
|
113
|
+
}).catch(() => { });
|
|
114
|
+
}
|
|
115
|
+
this.cookies.remove(SETTINGS.cookies.access.name);
|
|
116
|
+
this.cookies.remove(SETTINGS.cookies.refresh.name);
|
|
117
|
+
this.cookies.remove(SETTINGS.cookies.session.name);
|
|
118
|
+
}
|
|
119
|
+
async getPortalUrl() {
|
|
120
|
+
const { access } = this.getCookieTokens();
|
|
121
|
+
const res = await fetch(`${SETTINGS.domains.api}/portal/exchange`, {
|
|
122
|
+
method: 'GET',
|
|
123
|
+
headers: {
|
|
124
|
+
Authorization: `Bearer ${access}`,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
if (!res.ok && res.status === 401) {
|
|
128
|
+
return { ok: false, url: null, reason: 'unathorized' };
|
|
129
|
+
}
|
|
130
|
+
else if (!res.ok) {
|
|
131
|
+
return { ok: false, url: null, reason: 'fail' };
|
|
132
|
+
}
|
|
133
|
+
const body = await res.json();
|
|
134
|
+
return { ok: true, url: `${body.redirectUrl}?code=${body.code}&redirectUrl=${this.config.redirectUrl}`, reason: null };
|
|
135
|
+
}
|
|
136
|
+
/* ------------------------------------------------------------------------ */
|
|
137
|
+
/* REFRESH FLOW */
|
|
138
|
+
/* ------------------------------------------------------------------------ */
|
|
139
|
+
async refresh(refreshToken) {
|
|
140
|
+
try {
|
|
141
|
+
const response = await fetch(`${SETTINGS.domains.api}/auth/refresh`, {
|
|
142
|
+
method: 'POST',
|
|
143
|
+
headers: { 'Content-Type': 'application/json' },
|
|
144
|
+
body: JSON.stringify({
|
|
145
|
+
refresh_token: refreshToken,
|
|
146
|
+
client_type: 'server',
|
|
147
|
+
}),
|
|
148
|
+
});
|
|
149
|
+
if (!response.ok)
|
|
150
|
+
return null;
|
|
151
|
+
return response.json();
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/* ------------------------------------------------------------------------ */
|
|
158
|
+
/* REQUEST WITH AUTO-REFRESH */
|
|
159
|
+
/* ------------------------------------------------------------------------ */
|
|
160
|
+
async request(path, init = {}) {
|
|
161
|
+
const { access, refresh } = this.getCookieTokens();
|
|
162
|
+
const doFetch = (token) => fetch(`${this.config.requestUrl}${path}`, {
|
|
163
|
+
...init,
|
|
164
|
+
headers: {
|
|
165
|
+
...init.headers,
|
|
166
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
const start = performance.now();
|
|
170
|
+
let res = await doFetch(access);
|
|
171
|
+
// Attempt refresh once on 401
|
|
172
|
+
if (res.status === 401 && refresh) {
|
|
173
|
+
const data = await this.refresh(refresh);
|
|
174
|
+
if (data?.access_token && data?.refresh_token) {
|
|
175
|
+
this.setCookieTokens({
|
|
176
|
+
at: data.access_token,
|
|
177
|
+
rt: data.refresh_token,
|
|
178
|
+
});
|
|
179
|
+
res = await doFetch(data.access_token);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
this.pushMetric({
|
|
183
|
+
event_type: 'request',
|
|
184
|
+
runtime: 'server',
|
|
185
|
+
target: {
|
|
186
|
+
type: 'api',
|
|
187
|
+
method: init.method || 'GET',
|
|
188
|
+
path,
|
|
189
|
+
status: res.status,
|
|
190
|
+
duration_ms: Math.round(performance.now() - start),
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
return res;
|
|
194
|
+
}
|
|
195
|
+
/* ------------------------------------------------------------------------ */
|
|
196
|
+
/* METRICS */
|
|
197
|
+
/* ------------------------------------------------------------------------ */
|
|
198
|
+
pushMetric(payload) {
|
|
199
|
+
let sid = this.cookies.get(SETTINGS.cookies.session_id.name);
|
|
200
|
+
if (!sid) {
|
|
201
|
+
sid = 's_' + crypto.randomUUID();
|
|
202
|
+
this.cookies.set(SETTINGS.cookies.session_id.name, sid, SETTINGS.cookies.session_id.config);
|
|
203
|
+
}
|
|
204
|
+
queueMicrotask(() => {
|
|
205
|
+
fetch(`${this.config.baseUrl}${SETTINGS.bff.paths.metrics}`, {
|
|
206
|
+
method: 'POST',
|
|
207
|
+
headers: { 'Content-Type': 'application/json' },
|
|
208
|
+
body: JSON.stringify({ ...payload, session_id: sid }),
|
|
209
|
+
}).catch(() => { });
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
/* ------------------------------------------------------------------------ */
|
|
213
|
+
/* MIDDLEWARE */
|
|
214
|
+
/* ------------------------------------------------------------------------ */
|
|
215
|
+
async middleware(_request) {
|
|
216
|
+
const { access, refresh } = this.getCookieTokens();
|
|
217
|
+
if (access && await this.verifyAccessToken(access)) {
|
|
218
|
+
return NextResponse.next();
|
|
219
|
+
}
|
|
220
|
+
if (refresh) {
|
|
221
|
+
const data = await this.refresh(refresh);
|
|
222
|
+
if (data?.access_token && data?.refresh_token) {
|
|
223
|
+
this.setCookieTokens({
|
|
224
|
+
at: data.access_token,
|
|
225
|
+
rt: data.refresh_token,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return NextResponse.next();
|
|
230
|
+
}
|
|
231
|
+
/* ------------------------------------------------------------------------ */
|
|
232
|
+
/* BFF HANDLERS */
|
|
233
|
+
/* ------------------------------------------------------------------------ */
|
|
234
|
+
getHandlers() {
|
|
235
|
+
return {
|
|
236
|
+
GET: async (req, ctx) => {
|
|
237
|
+
const action = (await ctx.params).auditauth[0];
|
|
238
|
+
switch (action) {
|
|
239
|
+
case 'login':
|
|
240
|
+
return NextResponse.redirect(await this.buildAuthUrl());
|
|
241
|
+
case 'callback': {
|
|
242
|
+
const result = await this.callback(req);
|
|
243
|
+
return NextResponse.redirect(result.url);
|
|
244
|
+
}
|
|
245
|
+
case 'logout':
|
|
246
|
+
await this.logout();
|
|
247
|
+
return NextResponse.redirect(this.config.redirectUrl);
|
|
248
|
+
case 'portal': {
|
|
249
|
+
const result = await this.getPortalUrl();
|
|
250
|
+
return result.ok && result.url
|
|
251
|
+
? NextResponse.redirect(result.url)
|
|
252
|
+
: NextResponse.redirect(`${SETTINGS.domains.client}/auth/invalid`);
|
|
253
|
+
}
|
|
254
|
+
case 'session': {
|
|
255
|
+
const user = this.getSession();
|
|
256
|
+
if (!user)
|
|
257
|
+
return new NextResponse(null, { status: 401 });
|
|
258
|
+
return NextResponse.json({ user });
|
|
259
|
+
}
|
|
260
|
+
default:
|
|
261
|
+
return new Response('not found', { status: 404 });
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
POST: async (req, ctx) => {
|
|
265
|
+
const action = (await ctx.params).auditauth[0];
|
|
266
|
+
if (action === 'metrics') {
|
|
267
|
+
return this.metrics(await req.json());
|
|
268
|
+
}
|
|
269
|
+
return new Response('not found', { status: 404 });
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
async metrics(payload) {
|
|
274
|
+
await fetch(`${SETTINGS.domains.api}/metrics`, {
|
|
275
|
+
method: 'POST',
|
|
276
|
+
headers: {
|
|
277
|
+
'Content-Type': 'application/json',
|
|
278
|
+
'x-auditauth-app': this.config.appId,
|
|
279
|
+
'x-auditauth-key': this.config.apiKey,
|
|
280
|
+
},
|
|
281
|
+
body: JSON.stringify(payload),
|
|
282
|
+
});
|
|
283
|
+
return new Response(null, { status: 204 });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/* -------------------------------------------------------------------------- */
|
|
287
|
+
/* CLIENT SHORTCUTS */
|
|
288
|
+
/* -------------------------------------------------------------------------- */
|
|
289
|
+
const login = () => {
|
|
290
|
+
window.location.href = SETTINGS.bff.paths.login;
|
|
291
|
+
};
|
|
292
|
+
const logout = () => {
|
|
293
|
+
window.location.href = SETTINGS.bff.paths.logout;
|
|
294
|
+
};
|
|
295
|
+
const goToPortal = () => {
|
|
296
|
+
window.location.href = SETTINGS.bff.paths.portal;
|
|
297
|
+
};
|
|
298
|
+
export { AuditAuthNext, login, logout, goToPortal };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
declare const SETTINGS: {
|
|
2
|
+
readonly jwt_public_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs2EYs4Q9OyjNuAEPqb4j\nIzc52JdfVcNvEbG43Xp8B2kI9QxwRyX7rtFSwKowj3W1BlCLaTIMK3TafWOf9QwH\nfemuL9Ni37PFcGptzpyuoCYYA650EuD82PENcO49lsObvty2cuXxQszbPPvAecm4\nJ/XG70td/W1UwbjAJcdmp8ktZGYR0JXM37hYA9Xq/aKwu7d0FTL6WdKTvt3L5VxL\nF6WNyLs65ZSbu+j8UEkwmoJ9h9Y0mLQmFtmkoh/HWOFyFDnBNiJX0vRb++RhJw6w\ncrSbqpbTu7z4vIep5lgSOut39P273SVTQZ3cGQIS+605Ur5wjkkSzzaJV1QLBBR9\nAQIDAQAB\n-----END PUBLIC KEY-----\n";
|
|
3
|
+
readonly jwt_issuer: "https://api.auditauth.com";
|
|
4
|
+
readonly domains: {
|
|
5
|
+
readonly api: "http://localhost:4000/v1";
|
|
6
|
+
readonly client: "http://localhost:3000";
|
|
7
|
+
};
|
|
8
|
+
readonly bff: {
|
|
9
|
+
readonly paths: {
|
|
10
|
+
readonly callback: "/api/auditauth/callback";
|
|
11
|
+
readonly metrics: "/api/auditauth/metrics";
|
|
12
|
+
readonly login: "/api/auditauth/login";
|
|
13
|
+
readonly logout: "/api/auditauth/logout";
|
|
14
|
+
readonly portal: "/api/auditauth/portal";
|
|
15
|
+
readonly session: "/api/auditauth/session";
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
readonly cookies: {
|
|
19
|
+
readonly access: {
|
|
20
|
+
readonly name: "auditauth_access";
|
|
21
|
+
readonly config: {
|
|
22
|
+
readonly httpOnly: true;
|
|
23
|
+
readonly sameSite: "lax";
|
|
24
|
+
readonly secure: false;
|
|
25
|
+
readonly path: "/";
|
|
26
|
+
readonly maxAge: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
readonly session: {
|
|
30
|
+
readonly name: "auditauth_session";
|
|
31
|
+
readonly config: {
|
|
32
|
+
readonly maxAge: number;
|
|
33
|
+
readonly httpOnly: true;
|
|
34
|
+
readonly secure: false;
|
|
35
|
+
readonly path: "/";
|
|
36
|
+
readonly sameSite: "lax";
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
readonly refresh: {
|
|
40
|
+
readonly name: "auditauth_refresh";
|
|
41
|
+
readonly config: {
|
|
42
|
+
readonly httpOnly: true;
|
|
43
|
+
readonly sameSite: "lax";
|
|
44
|
+
readonly secure: false;
|
|
45
|
+
readonly path: "/";
|
|
46
|
+
readonly maxAge: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
readonly session_id: {
|
|
50
|
+
readonly name: "auditauth_sid";
|
|
51
|
+
readonly config: {
|
|
52
|
+
readonly httpOnly: false;
|
|
53
|
+
readonly sameSite: "lax";
|
|
54
|
+
readonly secure: false;
|
|
55
|
+
readonly path: "/";
|
|
56
|
+
readonly maxAge: number;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
export { SETTINGS };
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const SETTINGS = {
|
|
2
|
+
jwt_public_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs2EYs4Q9OyjNuAEPqb4j\nIzc52JdfVcNvEbG43Xp8B2kI9QxwRyX7rtFSwKowj3W1BlCLaTIMK3TafWOf9QwH\nfemuL9Ni37PFcGptzpyuoCYYA650EuD82PENcO49lsObvty2cuXxQszbPPvAecm4\nJ/XG70td/W1UwbjAJcdmp8ktZGYR0JXM37hYA9Xq/aKwu7d0FTL6WdKTvt3L5VxL\nF6WNyLs65ZSbu+j8UEkwmoJ9h9Y0mLQmFtmkoh/HWOFyFDnBNiJX0vRb++RhJw6w\ncrSbqpbTu7z4vIep5lgSOut39P273SVTQZ3cGQIS+605Ur5wjkkSzzaJV1QLBBR9\nAQIDAQAB\n-----END PUBLIC KEY-----\n",
|
|
3
|
+
jwt_issuer: "https://api.auditauth.com",
|
|
4
|
+
domains: {
|
|
5
|
+
api: 'http://localhost:4000/v1',
|
|
6
|
+
client: 'http://localhost:3000',
|
|
7
|
+
},
|
|
8
|
+
bff: {
|
|
9
|
+
paths: {
|
|
10
|
+
callback: '/api/auditauth/callback',
|
|
11
|
+
metrics: '/api/auditauth/metrics',
|
|
12
|
+
login: '/api/auditauth/login',
|
|
13
|
+
logout: '/api/auditauth/logout',
|
|
14
|
+
portal: '/api/auditauth/portal',
|
|
15
|
+
session: '/api/auditauth/session',
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
cookies: {
|
|
19
|
+
access: {
|
|
20
|
+
name: 'auditauth_access',
|
|
21
|
+
config: {
|
|
22
|
+
httpOnly: true,
|
|
23
|
+
sameSite: 'lax',
|
|
24
|
+
secure: false,
|
|
25
|
+
path: '/',
|
|
26
|
+
maxAge: 60 * 15,
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
session: {
|
|
30
|
+
name: 'auditauth_session',
|
|
31
|
+
config: {
|
|
32
|
+
maxAge: 60 * 60 * 24,
|
|
33
|
+
httpOnly: true,
|
|
34
|
+
secure: false,
|
|
35
|
+
path: "/",
|
|
36
|
+
sameSite: "lax",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
refresh: {
|
|
40
|
+
name: 'auditauth_refresh',
|
|
41
|
+
config: {
|
|
42
|
+
httpOnly: true,
|
|
43
|
+
sameSite: 'lax',
|
|
44
|
+
secure: false,
|
|
45
|
+
path: '/',
|
|
46
|
+
maxAge: 60 * 60 * 24,
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
session_id: {
|
|
50
|
+
name: 'auditauth_sid',
|
|
51
|
+
config: {
|
|
52
|
+
httpOnly: false,
|
|
53
|
+
sameSite: 'lax',
|
|
54
|
+
secure: false,
|
|
55
|
+
path: '/',
|
|
56
|
+
maxAge: 60 * 60,
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
export { SETTINGS };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
type AuditAuthConfig = {
|
|
2
|
+
requestUrl: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
redirectUrl: string;
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
appId: string;
|
|
7
|
+
};
|
|
8
|
+
type SessionUser = {
|
|
9
|
+
_id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
email: string;
|
|
12
|
+
avatar: {
|
|
13
|
+
url: string | null;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
type Session = {
|
|
17
|
+
user: SessionUser;
|
|
18
|
+
};
|
|
19
|
+
type CookieOptions = {
|
|
20
|
+
httpOnly?: boolean;
|
|
21
|
+
secure?: boolean;
|
|
22
|
+
sameSite?: 'lax' | 'strict' | 'none';
|
|
23
|
+
path?: string;
|
|
24
|
+
maxAge?: number;
|
|
25
|
+
};
|
|
26
|
+
type RequestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
27
|
+
type Metric = {
|
|
28
|
+
event_type: 'request';
|
|
29
|
+
runtime: 'browser' | 'server';
|
|
30
|
+
target: {
|
|
31
|
+
type: 'api';
|
|
32
|
+
method: RequestMethod;
|
|
33
|
+
path: string;
|
|
34
|
+
status: number;
|
|
35
|
+
duration_ms: number;
|
|
36
|
+
};
|
|
37
|
+
} | {
|
|
38
|
+
event_type: 'navigation';
|
|
39
|
+
runtime: 'browser' | 'server';
|
|
40
|
+
target: {
|
|
41
|
+
type: 'page';
|
|
42
|
+
path: string;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
type CookieAdapter = {
|
|
46
|
+
get: (name: string) => string | undefined;
|
|
47
|
+
set: (name: string, value: string, options?: CookieOptions) => void;
|
|
48
|
+
remove: (name: string) => void;
|
|
49
|
+
};
|
|
50
|
+
export type { AuditAuthConfig, SessionUser, Session, RequestMethod, Metric, CookieOptions, CookieAdapter, };
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@auditauth/next",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official AuditAuth SDK for Next.js",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Nimibyte",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.build.json",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"next": ">=13",
|
|
25
|
+
"react": ">=18",
|
|
26
|
+
"react-dom": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"crypto": "^1.0.1",
|
|
30
|
+
"jose": "^5.2.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^25.0.9",
|
|
34
|
+
"@types/react": "^19.2.8",
|
|
35
|
+
"@types/react-dom": "^19.2.3",
|
|
36
|
+
"typescript": "^5.9.3"
|
|
37
|
+
}
|
|
38
|
+
}
|