uibee 1.5.0 → 1.6.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/dist/src/utils/auth/callback.d.ts +2 -0
- package/dist/src/utils/auth/callback.js +60 -0
- package/dist/src/utils/auth/login.d.ts +3 -0
- package/dist/src/utils/auth/login.js +12 -0
- package/dist/src/utils/auth/logout.d.ts +3 -0
- package/dist/src/utils/auth/logout.js +19 -0
- package/dist/src/utils/auth/token.d.ts +3 -0
- package/dist/src/utils/auth/token.js +28 -0
- package/dist/src/utils/index.d.ts +4 -0
- package/dist/src/utils/index.js +5 -0
- package/package.json +1 -1
- package/src/types/utils.d.ts +31 -0
- package/src/utils/auth/callback.ts +87 -0
- package/src/utils/auth/login.ts +17 -0
- package/src/utils/auth/logout.tsx +24 -0
- package/src/utils/auth/token.ts +34 -0
- package/src/utils/index.ts +7 -1
- package/tsconfig.json +1 -2
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
export default async function authCallback({ req, tokenURL, clientID, clientSecret, redirectURI, userInfoURL, tokenRedirectURL }) {
|
|
3
|
+
const searchParams = new URL(req.url).searchParams;
|
|
4
|
+
if (!searchParams) {
|
|
5
|
+
return NextResponse.json({ error: 'No search parameters found.' }, { status: 400 });
|
|
6
|
+
}
|
|
7
|
+
const code = searchParams.get('code');
|
|
8
|
+
if (!code) {
|
|
9
|
+
return NextResponse.json({ error: 'No authorization code found.' }, { status: 400 });
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
// Exchanges callback code for access token
|
|
13
|
+
const tokenResponse = await fetch(tokenURL, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
16
|
+
body: new URLSearchParams({
|
|
17
|
+
client_id: clientID,
|
|
18
|
+
client_secret: clientSecret,
|
|
19
|
+
code: code,
|
|
20
|
+
redirect_uri: redirectURI,
|
|
21
|
+
grant_type: 'authorization_code',
|
|
22
|
+
}).toString()
|
|
23
|
+
});
|
|
24
|
+
const tokenResponseBody = await tokenResponse.text();
|
|
25
|
+
if (!tokenResponse.ok) {
|
|
26
|
+
return new Response(JSON.stringify(`Failed to obtain token: ${tokenResponseBody}`), {
|
|
27
|
+
status: 500,
|
|
28
|
+
headers: { 'Content-Type': 'application/json' }
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const token = JSON.parse(tokenResponseBody);
|
|
32
|
+
// Fetches user info using access token
|
|
33
|
+
const userInfoResponse = await fetch(userInfoURL, {
|
|
34
|
+
headers: { Authorization: `Bearer ${token.access_token}` }
|
|
35
|
+
});
|
|
36
|
+
if (!userInfoResponse.ok) {
|
|
37
|
+
const userInfoError = await userInfoResponse.text();
|
|
38
|
+
return new Response(`No user info found: ${userInfoError}`, {
|
|
39
|
+
status: 500,
|
|
40
|
+
headers: { 'Content-Type': 'application/json' }
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const userInfo = await userInfoResponse.json();
|
|
44
|
+
const redirectUrl = new URL(tokenRedirectURL);
|
|
45
|
+
const params = new URLSearchParams({
|
|
46
|
+
id: userInfo.sub,
|
|
47
|
+
name: userInfo.name,
|
|
48
|
+
email: userInfo.email,
|
|
49
|
+
groups: userInfo.groups.join(','),
|
|
50
|
+
access_token: token.access_token,
|
|
51
|
+
});
|
|
52
|
+
redirectUrl.search = params.toString();
|
|
53
|
+
return NextResponse.redirect(redirectUrl.toString());
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
const error = err;
|
|
57
|
+
console.error('Error during OAuth flow:', error.message);
|
|
58
|
+
return NextResponse.json({ error: 'Authentication failed' }, { status: 500 });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
export default async function AuthLogin({ clientID, redirectURI, authURL }) {
|
|
3
|
+
const state = Math.random().toString(36).substring(5);
|
|
4
|
+
const authQueryParams = new URLSearchParams({
|
|
5
|
+
client_id: clientID,
|
|
6
|
+
redirect_uri: redirectURI,
|
|
7
|
+
response_type: 'code',
|
|
8
|
+
scope: 'openid profile email',
|
|
9
|
+
state: state,
|
|
10
|
+
}).toString();
|
|
11
|
+
return NextResponse.redirect(`${authURL}?${authQueryParams}`);
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
export default async function AuthLogout({ request, frontendURL }) {
|
|
3
|
+
console.log(request.url);
|
|
4
|
+
const response = NextResponse.redirect(new URL('/', frontendURL));
|
|
5
|
+
// Remove all authentication cookies
|
|
6
|
+
const cookiesToRemove = [
|
|
7
|
+
'access_token',
|
|
8
|
+
'access_token_expires',
|
|
9
|
+
'refresh_token',
|
|
10
|
+
'refresh_token_expires',
|
|
11
|
+
'user_id',
|
|
12
|
+
'user_name',
|
|
13
|
+
'user_roles'
|
|
14
|
+
];
|
|
15
|
+
cookiesToRemove.forEach(cookieName => {
|
|
16
|
+
response.cookies.delete(cookieName);
|
|
17
|
+
});
|
|
18
|
+
return response;
|
|
19
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
export default async function AuthToken({ request, frontendURL }) {
|
|
3
|
+
const url = new URL(request.url);
|
|
4
|
+
const token = url.searchParams.get('access_token');
|
|
5
|
+
const btg = url.searchParams.get('btg');
|
|
6
|
+
if (!token) {
|
|
7
|
+
return NextResponse.json({ error: 'No access token provided' }, { status: 400 });
|
|
8
|
+
}
|
|
9
|
+
if (btg) {
|
|
10
|
+
return NextResponse.redirect(new URL('/dashboard', frontendURL));
|
|
11
|
+
}
|
|
12
|
+
const accessToken = url.searchParams.get('access_token');
|
|
13
|
+
const accessTokenExpires = url.searchParams.get('access_token_expires');
|
|
14
|
+
const refreshToken = url.searchParams.get('refresh_token');
|
|
15
|
+
const refreshTokenExpires = url.searchParams.get('refresh_token_expires');
|
|
16
|
+
const userId = url.searchParams.get('user_id');
|
|
17
|
+
const userName = url.searchParams.get('user_name');
|
|
18
|
+
const userRoles = url.searchParams.get('user_roles');
|
|
19
|
+
const response = NextResponse.redirect(new URL('/dashboard', frontendURL));
|
|
20
|
+
response.cookies.set('access_token', accessToken);
|
|
21
|
+
response.cookies.set('access_token_expires', accessTokenExpires);
|
|
22
|
+
response.cookies.set('refresh_token', refreshToken);
|
|
23
|
+
response.cookies.set('refresh_token_expires', refreshTokenExpires);
|
|
24
|
+
response.cookies.set('user_id', userId);
|
|
25
|
+
response.cookies.set('user_name', userName);
|
|
26
|
+
response.cookies.set('user_roles', userRoles);
|
|
27
|
+
return response;
|
|
28
|
+
}
|
|
@@ -2,3 +2,7 @@ export { default as alertSlowQuery } from './sql/alertSlowQuery';
|
|
|
2
2
|
export { default as discordAlert } from './discord/discordAlert';
|
|
3
3
|
export { getCookie, setCookie, removeCookie } from './cookies/cookies';
|
|
4
4
|
export { LogoConsoleOutput } from './LogoConsoleOutput/LogoConsoleOutput';
|
|
5
|
+
export { default as authLogin } from './auth/login';
|
|
6
|
+
export { default as authCallback } from './auth/callback';
|
|
7
|
+
export { default as authToken } from './auth/token';
|
|
8
|
+
export { default as authLogout } from './auth/logout';
|
package/dist/src/utils/index.js
CHANGED
|
@@ -2,3 +2,8 @@ export { default as alertSlowQuery } from './sql/alertSlowQuery';
|
|
|
2
2
|
export { default as discordAlert } from './discord/discordAlert';
|
|
3
3
|
export { getCookie, setCookie, removeCookie } from './cookies/cookies';
|
|
4
4
|
export { LogoConsoleOutput } from './LogoConsoleOutput/LogoConsoleOutput';
|
|
5
|
+
// Auth
|
|
6
|
+
export { default as authLogin } from './auth/login';
|
|
7
|
+
export { default as authCallback } from './auth/callback';
|
|
8
|
+
export { default as authToken } from './auth/token';
|
|
9
|
+
export { default as authLogout } from './auth/logout';
|
package/package.json
CHANGED
package/src/types/utils.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @stylistic/semi */
|
|
2
|
+
import { NextRequest } from 'next/server'
|
|
3
|
+
|
|
2
4
|
declare module 'uibee/utils' {
|
|
3
5
|
export interface SlowQueryProps {
|
|
4
6
|
application: string
|
|
@@ -29,6 +31,35 @@ declare module 'uibee/utils' {
|
|
|
29
31
|
webhookURL: string
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
export interface AuthLoginProps {
|
|
35
|
+
clientID: string
|
|
36
|
+
redirectURI: string
|
|
37
|
+
authURL: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface AuthCallbackProps {
|
|
41
|
+
req: Request
|
|
42
|
+
tokenURL: string
|
|
43
|
+
clientID: string
|
|
44
|
+
clientSecret: string
|
|
45
|
+
redirectURI: string
|
|
46
|
+
userInfoURL: string
|
|
47
|
+
tokenRedirectURL: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface AuthTokenProps {
|
|
51
|
+
request: NextRequest
|
|
52
|
+
frontendURL: string
|
|
53
|
+
}
|
|
54
|
+
export interface AuthLogoutProps {
|
|
55
|
+
request: NextRequest
|
|
56
|
+
frontendURL: string
|
|
57
|
+
}
|
|
58
|
+
|
|
32
59
|
export default async function alertSlowQuery(props: SlowQueryProps): Promise<void>;
|
|
33
60
|
export default async function discordAlert(props: DiscordAlertProps): Promise<number>;
|
|
61
|
+
export default async function authLogin(props: AuthLoginProps): Promise<Response>;
|
|
62
|
+
export default async function authCallback(props: AuthCallbackProps): Promise<Response>;
|
|
63
|
+
export default async function authToken(props: AuthTokenProps): Promise<Response>;
|
|
64
|
+
export default async function authLogout(props: AuthLogoutProps): Promise<Response>;
|
|
34
65
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import type { AuthCallbackProps } from 'uibee/utils'
|
|
3
|
+
|
|
4
|
+
type UserInfo = {
|
|
5
|
+
sub: string
|
|
6
|
+
name: string
|
|
7
|
+
email: string
|
|
8
|
+
groups: string[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default async function authCallback({
|
|
12
|
+
req,
|
|
13
|
+
tokenURL,
|
|
14
|
+
clientID,
|
|
15
|
+
clientSecret,
|
|
16
|
+
redirectURI,
|
|
17
|
+
userInfoURL,
|
|
18
|
+
tokenRedirectURL
|
|
19
|
+
}: AuthCallbackProps) {
|
|
20
|
+
const searchParams = new URL(req.url).searchParams
|
|
21
|
+
|
|
22
|
+
if (!searchParams) {
|
|
23
|
+
return NextResponse.json({ error: 'No search parameters found.' }, { status: 400 })
|
|
24
|
+
}
|
|
25
|
+
const code = searchParams.get('code')
|
|
26
|
+
|
|
27
|
+
if (!code) {
|
|
28
|
+
return NextResponse.json({ error: 'No authorization code found.' }, { status: 400 })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
// Exchanges callback code for access token
|
|
33
|
+
const tokenResponse = await fetch(tokenURL, {
|
|
34
|
+
method: 'POST',
|
|
35
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
36
|
+
body: new URLSearchParams({
|
|
37
|
+
client_id: clientID,
|
|
38
|
+
client_secret: clientSecret,
|
|
39
|
+
code: code as string,
|
|
40
|
+
redirect_uri: redirectURI,
|
|
41
|
+
grant_type: 'authorization_code',
|
|
42
|
+
}).toString()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const tokenResponseBody = await tokenResponse.text()
|
|
46
|
+
|
|
47
|
+
if (!tokenResponse.ok) {
|
|
48
|
+
return new Response(JSON.stringify(`Failed to obtain token: ${tokenResponseBody}`), {
|
|
49
|
+
status: 500,
|
|
50
|
+
headers: { 'Content-Type': 'application/json' }
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const token = JSON.parse(tokenResponseBody)
|
|
55
|
+
|
|
56
|
+
// Fetches user info using access token
|
|
57
|
+
const userInfoResponse = await fetch(userInfoURL, {
|
|
58
|
+
headers: { Authorization: `Bearer ${token.access_token}` }
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
if (!userInfoResponse.ok) {
|
|
62
|
+
const userInfoError = await userInfoResponse.text()
|
|
63
|
+
return new Response(`No user info found: ${userInfoError}`, {
|
|
64
|
+
status: 500,
|
|
65
|
+
headers: { 'Content-Type': 'application/json' }
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const userInfo = await userInfoResponse.json() as UserInfo
|
|
70
|
+
|
|
71
|
+
const redirectUrl = new URL(tokenRedirectURL)
|
|
72
|
+
const params = new URLSearchParams({
|
|
73
|
+
id: userInfo.sub,
|
|
74
|
+
name: userInfo.name,
|
|
75
|
+
email: userInfo.email,
|
|
76
|
+
groups: userInfo.groups.join(','),
|
|
77
|
+
access_token: token.access_token,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
redirectUrl.search = params.toString()
|
|
81
|
+
return NextResponse.redirect(redirectUrl.toString())
|
|
82
|
+
} catch (err: unknown) {
|
|
83
|
+
const error = err as Error
|
|
84
|
+
console.error('Error during OAuth flow:', error.message)
|
|
85
|
+
return NextResponse.json({ error: 'Authentication failed' }, { status: 500 })
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import type { AuthLoginProps } from 'uibee/utils'
|
|
3
|
+
|
|
4
|
+
export default async function AuthLogin({ clientID, redirectURI, authURL }: AuthLoginProps) {
|
|
5
|
+
const state = Math.random().toString(36).substring(5)
|
|
6
|
+
const authQueryParams = new URLSearchParams({
|
|
7
|
+
client_id: clientID,
|
|
8
|
+
redirect_uri: redirectURI,
|
|
9
|
+
response_type: 'code',
|
|
10
|
+
scope: 'openid profile email',
|
|
11
|
+
state: state,
|
|
12
|
+
}).toString()
|
|
13
|
+
|
|
14
|
+
return NextResponse.redirect(
|
|
15
|
+
`${authURL}?${authQueryParams}`
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import type { AuthLogoutProps } from 'uibee/utils'
|
|
3
|
+
|
|
4
|
+
export default async function AuthLogout({ request, frontendURL }: AuthLogoutProps) {
|
|
5
|
+
console.log(request.url)
|
|
6
|
+
const response = NextResponse.redirect(new URL('/', frontendURL))
|
|
7
|
+
|
|
8
|
+
// Remove all authentication cookies
|
|
9
|
+
const cookiesToRemove = [
|
|
10
|
+
'access_token',
|
|
11
|
+
'access_token_expires',
|
|
12
|
+
'refresh_token',
|
|
13
|
+
'refresh_token_expires',
|
|
14
|
+
'user_id',
|
|
15
|
+
'user_name',
|
|
16
|
+
'user_roles'
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
cookiesToRemove.forEach(cookieName => {
|
|
20
|
+
response.cookies.delete(cookieName)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
return response
|
|
24
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import type { AuthTokenProps } from 'uibee/utils'
|
|
3
|
+
|
|
4
|
+
export default async function AuthToken({ request, frontendURL }: AuthTokenProps) {
|
|
5
|
+
const url = new URL(request.url)
|
|
6
|
+
const token = url.searchParams.get('access_token')
|
|
7
|
+
const btg = url.searchParams.get('btg')
|
|
8
|
+
if (!token) {
|
|
9
|
+
return NextResponse.json({ error: 'No access token provided' }, { status: 400 })
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (btg) {
|
|
13
|
+
return NextResponse.redirect(new URL('/dashboard', frontendURL))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const accessToken = url.searchParams.get('access_token')!
|
|
17
|
+
const accessTokenExpires = url.searchParams.get('access_token_expires')!
|
|
18
|
+
const refreshToken = url.searchParams.get('refresh_token')!
|
|
19
|
+
const refreshTokenExpires = url.searchParams.get('refresh_token_expires')!
|
|
20
|
+
const userId = url.searchParams.get('user_id')!
|
|
21
|
+
const userName = url.searchParams.get('user_name')!
|
|
22
|
+
const userRoles = url.searchParams.get('user_roles')!
|
|
23
|
+
|
|
24
|
+
const response = NextResponse.redirect(new URL('/dashboard', frontendURL))
|
|
25
|
+
response.cookies.set('access_token', accessToken)
|
|
26
|
+
response.cookies.set('access_token_expires', accessTokenExpires)
|
|
27
|
+
response.cookies.set('refresh_token', refreshToken)
|
|
28
|
+
response.cookies.set('refresh_token_expires', refreshTokenExpires)
|
|
29
|
+
response.cookies.set('user_id', userId)
|
|
30
|
+
response.cookies.set('user_name', userName)
|
|
31
|
+
response.cookies.set('user_roles', userRoles)
|
|
32
|
+
|
|
33
|
+
return response
|
|
34
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export { default as alertSlowQuery } from './sql/alertSlowQuery'
|
|
2
2
|
export { default as discordAlert } from './discord/discordAlert'
|
|
3
3
|
export { getCookie, setCookie, removeCookie } from './cookies/cookies'
|
|
4
|
-
export { LogoConsoleOutput } from './LogoConsoleOutput/LogoConsoleOutput'
|
|
4
|
+
export { LogoConsoleOutput } from './LogoConsoleOutput/LogoConsoleOutput'
|
|
5
|
+
|
|
6
|
+
// Auth
|
|
7
|
+
export { default as authLogin } from './auth/login'
|
|
8
|
+
export { default as authCallback } from './auth/callback'
|
|
9
|
+
export { default as authToken } from './auth/token'
|
|
10
|
+
export { default as authLogout } from './auth/logout'
|
package/tsconfig.json
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
"declaration": true,
|
|
7
7
|
"outDir": "dist",
|
|
8
8
|
"rootDir": ".",
|
|
9
|
-
"baseUrl": ".",
|
|
10
9
|
"esModuleInterop": true,
|
|
11
10
|
"forceConsistentCasingInFileNames": true,
|
|
12
11
|
"strict": true,
|
|
@@ -15,7 +14,7 @@
|
|
|
15
14
|
"resolveJsonModule": true,
|
|
16
15
|
"paths": {
|
|
17
16
|
"@images/*": [
|
|
18
|
-
"images/*"
|
|
17
|
+
"./images/*"
|
|
19
18
|
]
|
|
20
19
|
}
|
|
21
20
|
},
|