nocal-auth-sdk 0.1.8 → 0.2.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/NocalAuth.d.ts +22 -2
- package/dist/NocalAuth.js +61 -13
- package/dist/index.d.mts +46 -0
- package/dist/index.d.ts +22 -2
- package/dist/index.js +171 -1
- package/dist/index.mjs +110 -0
- package/dist/types.d.ts +23 -0
- package/dist/types.js +1 -0
- package/package.json +1 -1
package/dist/NocalAuth.d.ts
CHANGED
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
export interface NocalAuthOptions {
|
|
2
2
|
authorizeUrl?: string;
|
|
3
|
+
clientId?: string;
|
|
4
|
+
redirectUri?: string;
|
|
5
|
+
scope?: string;
|
|
6
|
+
state?: string;
|
|
3
7
|
[key: string]: any;
|
|
4
8
|
}
|
|
9
|
+
export interface NocalPopupResult {
|
|
10
|
+
success: boolean;
|
|
11
|
+
data?: Record<string, any>;
|
|
12
|
+
error?: string;
|
|
13
|
+
message?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface LoginWithPopupOptions {
|
|
16
|
+
url?: string;
|
|
17
|
+
popupName?: string;
|
|
18
|
+
width?: number;
|
|
19
|
+
height?: number;
|
|
20
|
+
features?: string;
|
|
21
|
+
}
|
|
5
22
|
export declare class NocalAuth {
|
|
6
23
|
private authorizeUrl;
|
|
7
|
-
|
|
24
|
+
private options;
|
|
8
25
|
constructor(options?: NocalAuthOptions);
|
|
9
|
-
|
|
26
|
+
static notifyPopupResult(result: NocalPopupResult, targetWindow?: Window | null): boolean;
|
|
27
|
+
getAuthorizeUrl(): string;
|
|
28
|
+
static loginWithPopup(options?: LoginWithPopupOptions): Promise<unknown>;
|
|
29
|
+
loginWithPopup(options?: LoginWithPopupOptions): Promise<unknown>;
|
|
10
30
|
}
|
package/dist/NocalAuth.js
CHANGED
|
@@ -1,19 +1,61 @@
|
|
|
1
1
|
export class NocalAuth {
|
|
2
2
|
constructor(options = {}) {
|
|
3
|
-
this.
|
|
3
|
+
this.options = options;
|
|
4
|
+
this.authorizeUrl =
|
|
5
|
+
options.authorizeUrl || "https://auth.nocal.vn/oauth/authorize";
|
|
4
6
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
static notifyPopupResult(result, targetWindow = typeof window !== "undefined"
|
|
8
|
+
? window.opener
|
|
9
|
+
: null) {
|
|
10
|
+
if (typeof window === "undefined")
|
|
11
|
+
return false;
|
|
12
|
+
const opener = targetWindow ?? window.opener;
|
|
13
|
+
if (!opener)
|
|
14
|
+
return false;
|
|
15
|
+
const payload = {
|
|
16
|
+
type: "nocal_auth_result",
|
|
17
|
+
success: result.success,
|
|
18
|
+
...(result.success
|
|
19
|
+
? { data: result.data ?? {} }
|
|
20
|
+
: {
|
|
21
|
+
error: result.error || "AUTH_FAILED",
|
|
22
|
+
message: result.message || result.error || "AUTH_FAILED",
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
opener.postMessage(payload, "*");
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
getAuthorizeUrl() {
|
|
29
|
+
const url = new URL(this.authorizeUrl || "https://auth.nocal.vn/oauth/authorize");
|
|
30
|
+
const params = {
|
|
31
|
+
client_id: this.options.clientId,
|
|
32
|
+
redirect_uri: this.options.redirectUri,
|
|
33
|
+
scope: this.options.scope,
|
|
34
|
+
state: this.options.state,
|
|
35
|
+
...this.options,
|
|
36
|
+
};
|
|
37
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
38
|
+
if (value === undefined || value === null || value === "")
|
|
39
|
+
return;
|
|
40
|
+
if (key === "authorizeUrl")
|
|
41
|
+
return;
|
|
42
|
+
url.searchParams.set(key, String(value));
|
|
43
|
+
});
|
|
44
|
+
return url.toString();
|
|
45
|
+
}
|
|
46
|
+
static loginWithPopup(options = {}) {
|
|
7
47
|
if (typeof window === "undefined") {
|
|
8
48
|
return Promise.reject(new Error("loginWithPopup() can only be used in a browser environment"));
|
|
9
49
|
}
|
|
50
|
+
const url = options.url || "https://auth.nocal.vn/oauth/authorize";
|
|
51
|
+
const width = options.width ?? 500;
|
|
52
|
+
const height = options.height ?? 700;
|
|
53
|
+
const left = window.screenX + (window.innerWidth - width) / 2;
|
|
54
|
+
const top = window.screenY + (window.innerHeight - height) / 2;
|
|
55
|
+
const features = options.features ??
|
|
56
|
+
`width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;
|
|
10
57
|
return new Promise((resolve, reject) => {
|
|
11
|
-
const
|
|
12
|
-
const height = 700;
|
|
13
|
-
const left = window.screenX + (window.innerWidth - width) / 2;
|
|
14
|
-
const top = window.screenY + (window.innerHeight - height) / 2;
|
|
15
|
-
const features = `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;
|
|
16
|
-
const popup = window.open(this.authorizeUrl, "nocal_auth_popup", features);
|
|
58
|
+
const popup = window.open(url, options.popupName ?? "nocal_auth_popup", features);
|
|
17
59
|
if (!popup)
|
|
18
60
|
return reject(new Error("POPUP_BLOCKED"));
|
|
19
61
|
popup.focus();
|
|
@@ -33,10 +75,10 @@ export class NocalAuth {
|
|
|
33
75
|
return;
|
|
34
76
|
cleanup();
|
|
35
77
|
if (payload.success) {
|
|
36
|
-
resolve(payload.data);
|
|
78
|
+
resolve(payload.data ?? {});
|
|
37
79
|
}
|
|
38
80
|
else {
|
|
39
|
-
reject(new Error(payload.error || "AUTH_FAILED"));
|
|
81
|
+
reject(new Error(payload.error || payload.message || "AUTH_FAILED"));
|
|
40
82
|
}
|
|
41
83
|
};
|
|
42
84
|
window.addEventListener("message", handleMessage);
|
|
@@ -47,10 +89,16 @@ export class NocalAuth {
|
|
|
47
89
|
reject(new Error("POPUP_CLOSED"));
|
|
48
90
|
}
|
|
49
91
|
}
|
|
50
|
-
catch
|
|
51
|
-
//
|
|
92
|
+
catch {
|
|
93
|
+
// Ignore cross-origin checks while popup is redirecting.
|
|
52
94
|
}
|
|
53
95
|
}, 500);
|
|
54
96
|
});
|
|
55
97
|
}
|
|
98
|
+
loginWithPopup(options = {}) {
|
|
99
|
+
return NocalAuth.loginWithPopup({
|
|
100
|
+
...options,
|
|
101
|
+
url: options.url || this.getAuthorizeUrl(),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
56
104
|
}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as _supabase_auth_js from '@supabase/auth-js';
|
|
2
|
+
import { User, Session } from '@supabase/supabase-js';
|
|
3
|
+
export { Session, User } from '@supabase/supabase-js';
|
|
4
|
+
|
|
5
|
+
interface NocalClientConfig {
|
|
6
|
+
clientId: string;
|
|
7
|
+
redirectUri: string;
|
|
8
|
+
}
|
|
9
|
+
type NocalOAuthProvider = "google" | "facebook" | "github" | "apple";
|
|
10
|
+
interface OAuthLoginReq {
|
|
11
|
+
provider?: NocalOAuthProvider;
|
|
12
|
+
redirectTo?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
declare class NocalAuthSDK {
|
|
16
|
+
private supabase;
|
|
17
|
+
private clientId;
|
|
18
|
+
private redirectUri;
|
|
19
|
+
constructor(config: NocalClientConfig);
|
|
20
|
+
/**
|
|
21
|
+
* Mở Popup UI Đăng nhập/Đăng ký tập trung của Nocal
|
|
22
|
+
*/
|
|
23
|
+
signInWithNocal(req?: OAuthLoginReq): Promise<User>;
|
|
24
|
+
/**
|
|
25
|
+
* Lấy thông tin User hiện tại
|
|
26
|
+
*/
|
|
27
|
+
getUser(): Promise<User | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Lấy Session / Access Token hiện tại
|
|
30
|
+
*/
|
|
31
|
+
getSession(): Promise<Session | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Đăng xuất khỏi hệ thống
|
|
34
|
+
*/
|
|
35
|
+
signOut(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Lắng nghe sự kiện đăng nhập / đăng xuất
|
|
38
|
+
*/
|
|
39
|
+
onAuthStateChange(callback: (event: string, session: Session | null) => void): {
|
|
40
|
+
data: {
|
|
41
|
+
subscription: _supabase_auth_js.Subscription;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { NocalAuthSDK, type NocalClientConfig, type NocalOAuthProvider, type OAuthLoginReq };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { NocalClientConfig, OAuthLoginReq, NocalUser, NocalSession } from "./types";
|
|
2
|
+
export declare class NocalAuthSDK {
|
|
3
|
+
private clientId;
|
|
4
|
+
private redirectUri;
|
|
5
|
+
private authServerUrl;
|
|
6
|
+
private currentSession;
|
|
7
|
+
private currentUser;
|
|
8
|
+
constructor(config: NocalClientConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Mở Popup UI Đăng nhập & Ủy quyền OAuth 2.0 với PKCE
|
|
11
|
+
*/
|
|
12
|
+
signInWithNocal(req?: OAuthLoginReq): Promise<{
|
|
13
|
+
user: NocalUser;
|
|
14
|
+
session: NocalSession;
|
|
15
|
+
}>;
|
|
16
|
+
private exchangeCodeForToken;
|
|
17
|
+
private fetchUserInfo;
|
|
18
|
+
getUser(): Promise<NocalUser | null>;
|
|
19
|
+
getSession(): Promise<NocalSession | null>;
|
|
20
|
+
signOut(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export * from "./types";
|
package/dist/index.js
CHANGED
|
@@ -1 +1,171 @@
|
|
|
1
|
-
|
|
1
|
+
const DEFAULT_AUTH_SERVER_URL = "http://localhost:3001";
|
|
2
|
+
// Helper for PKCE crypto
|
|
3
|
+
function base64URLEncode(buffer) {
|
|
4
|
+
let binary = "";
|
|
5
|
+
const bytes = new Uint8Array(buffer);
|
|
6
|
+
for (let i = 0; i < bytes.byteLength; i++) {
|
|
7
|
+
binary += String.fromCharCode(bytes[i]);
|
|
8
|
+
}
|
|
9
|
+
return btoa(binary)
|
|
10
|
+
.replace(/\+/g, "-")
|
|
11
|
+
.replace(/\//g, "_")
|
|
12
|
+
.replace(/=+$/, "");
|
|
13
|
+
}
|
|
14
|
+
async function generateCodeChallenge(verifier) {
|
|
15
|
+
const encoder = new TextEncoder();
|
|
16
|
+
const data = encoder.encode(verifier);
|
|
17
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
18
|
+
return base64URLEncode(new Uint8Array(digest));
|
|
19
|
+
}
|
|
20
|
+
function generateRandomString(length = 32) {
|
|
21
|
+
const array = new Uint8Array(length);
|
|
22
|
+
crypto.getRandomValues(array);
|
|
23
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
24
|
+
}
|
|
25
|
+
export class NocalAuthSDK {
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.currentSession = null;
|
|
28
|
+
this.currentUser = null;
|
|
29
|
+
this.clientId = config.clientId;
|
|
30
|
+
this.redirectUri = config.redirectUri;
|
|
31
|
+
this.authServerUrl = config.authServerUrl || DEFAULT_AUTH_SERVER_URL;
|
|
32
|
+
// Load session from localStorage if available
|
|
33
|
+
if (typeof window !== "undefined") {
|
|
34
|
+
try {
|
|
35
|
+
const stored = localStorage.getItem("nocal_auth_session");
|
|
36
|
+
if (stored) {
|
|
37
|
+
const parsed = JSON.parse(stored);
|
|
38
|
+
this.currentSession = parsed.session;
|
|
39
|
+
this.currentUser = parsed.user;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
// ignore
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Mở Popup UI Đăng nhập & Ủy quyền OAuth 2.0 với PKCE
|
|
49
|
+
*/
|
|
50
|
+
async signInWithNocal(req) {
|
|
51
|
+
const state = req?.state || generateRandomString(16);
|
|
52
|
+
const codeVerifier = generateRandomString(32);
|
|
53
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
54
|
+
const authUrl = new URL(`${this.authServerUrl}/oauth/authorize`);
|
|
55
|
+
authUrl.searchParams.set("client_id", this.clientId);
|
|
56
|
+
authUrl.searchParams.set("redirect_uri", this.redirectUri);
|
|
57
|
+
authUrl.searchParams.set("response_type", "code");
|
|
58
|
+
authUrl.searchParams.set("state", state);
|
|
59
|
+
authUrl.searchParams.set("code_challenge", codeChallenge);
|
|
60
|
+
authUrl.searchParams.set("code_challenge_method", "S256");
|
|
61
|
+
const width = 480;
|
|
62
|
+
const height = 680;
|
|
63
|
+
const left = typeof window !== "undefined" ? window.screenX + (window.outerWidth - width) / 2 : 0;
|
|
64
|
+
const top = typeof window !== "undefined" ? window.screenY + (window.outerHeight - height) / 2 : 0;
|
|
65
|
+
const popup = window.open(authUrl.toString(), "NocalAuthPopup", `width=${width},height=${height},left=${left},top=${top},status=yes,scrollbars=yes`);
|
|
66
|
+
if (!popup) {
|
|
67
|
+
throw new Error("POPUP_BLOCKED");
|
|
68
|
+
}
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
const allowedOrigin = new URL(this.authServerUrl).origin;
|
|
71
|
+
const messageListener = async (event) => {
|
|
72
|
+
if (event.origin !== allowedOrigin)
|
|
73
|
+
return;
|
|
74
|
+
const data = event.data;
|
|
75
|
+
if (!data || (data.type !== "NOCAL_OAUTH_CODE" && data.type !== "NOCAL_OAUTH_ERROR")) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
window.removeEventListener("message", messageListener);
|
|
79
|
+
clearInterval(checkClosedTimer);
|
|
80
|
+
if (data.type === "NOCAL_OAUTH_ERROR" || data.error) {
|
|
81
|
+
popup.close();
|
|
82
|
+
reject(new Error(data.error || "OAUTH_ERROR"));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (data.state && data.state !== state) {
|
|
86
|
+
popup.close();
|
|
87
|
+
reject(new Error("OAUTH_STATE_MISMATCH"));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const code = data.code;
|
|
91
|
+
if (!code) {
|
|
92
|
+
popup.close();
|
|
93
|
+
reject(new Error("MISSING_AUTHORIZATION_CODE"));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
popup.close();
|
|
98
|
+
// Đổi code lấy token
|
|
99
|
+
const session = await this.exchangeCodeForToken(code, codeVerifier);
|
|
100
|
+
const user = await this.fetchUserInfo(session.access_token);
|
|
101
|
+
this.currentSession = session;
|
|
102
|
+
this.currentUser = user;
|
|
103
|
+
if (typeof window !== "undefined") {
|
|
104
|
+
localStorage.setItem("nocal_auth_session", JSON.stringify({ session, user }));
|
|
105
|
+
}
|
|
106
|
+
resolve({ user, session });
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
reject(err);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
window.addEventListener("message", messageListener);
|
|
113
|
+
const checkClosedTimer = setInterval(() => {
|
|
114
|
+
try {
|
|
115
|
+
if (popup.closed) {
|
|
116
|
+
clearInterval(checkClosedTimer);
|
|
117
|
+
window.removeEventListener("message", messageListener);
|
|
118
|
+
reject(new Error("POPUP_CLOSED_BY_USER"));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
// ignore
|
|
123
|
+
}
|
|
124
|
+
}, 500);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async exchangeCodeForToken(code, codeVerifier) {
|
|
128
|
+
const res = await fetch(`${this.authServerUrl}/api/oauth/token`, {
|
|
129
|
+
method: "POST",
|
|
130
|
+
headers: { "Content-Type": "application/json" },
|
|
131
|
+
body: JSON.stringify({
|
|
132
|
+
grant_type: "authorization_code",
|
|
133
|
+
code,
|
|
134
|
+
client_id: this.clientId,
|
|
135
|
+
redirect_uri: this.redirectUri,
|
|
136
|
+
code_verifier: codeVerifier,
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
const data = await res.json();
|
|
140
|
+
if (!res.ok) {
|
|
141
|
+
throw new Error(data.error_description || data.error || "FAILED_TO_EXCHANGE_TOKEN");
|
|
142
|
+
}
|
|
143
|
+
return data;
|
|
144
|
+
}
|
|
145
|
+
async fetchUserInfo(accessToken) {
|
|
146
|
+
const res = await fetch(`${this.authServerUrl}/api/oauth/userinfo`, {
|
|
147
|
+
headers: {
|
|
148
|
+
Authorization: `Bearer ${accessToken}`,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
const data = await res.json();
|
|
152
|
+
if (!res.ok) {
|
|
153
|
+
throw new Error(data.error_description || data.error || "FAILED_TO_FETCH_USERINFO");
|
|
154
|
+
}
|
|
155
|
+
return data;
|
|
156
|
+
}
|
|
157
|
+
async getUser() {
|
|
158
|
+
return this.currentUser;
|
|
159
|
+
}
|
|
160
|
+
async getSession() {
|
|
161
|
+
return this.currentSession;
|
|
162
|
+
}
|
|
163
|
+
async signOut() {
|
|
164
|
+
this.currentSession = null;
|
|
165
|
+
this.currentUser = null;
|
|
166
|
+
if (typeof window !== "undefined") {
|
|
167
|
+
localStorage.removeItem("nocal_auth_session");
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export * from "./types";
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
createClient
|
|
4
|
+
} from "@supabase/supabase-js";
|
|
5
|
+
var NOCAL_AUTH_SERVER_URL = "https://hldymiruucsqqzicnwdv.supabase.co";
|
|
6
|
+
var NOCAL_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhsZHltaXJ1dWNzcXF6aWNud2R2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODk2MTQ2NzAsImV4cCI6MjEwNTE5MDY3MH0.dLaPWdgTV8mRVToNT1XLg1EUjHvyvRRK2qc0DQAu8YI";
|
|
7
|
+
var NocalAuthSDK = class {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.clientId = config.clientId;
|
|
10
|
+
this.redirectUri = config.redirectUri;
|
|
11
|
+
this.supabase = createClient(NOCAL_AUTH_SERVER_URL, NOCAL_ANON_KEY, {
|
|
12
|
+
auth: {
|
|
13
|
+
autoRefreshToken: true,
|
|
14
|
+
persistSession: true,
|
|
15
|
+
detectSessionInUrl: true
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Mở Popup UI Đăng nhập/Đăng ký tập trung của Nocal
|
|
21
|
+
*/
|
|
22
|
+
async signInWithNocal(req) {
|
|
23
|
+
const targetRedirect = req?.redirectTo || this.redirectUri;
|
|
24
|
+
const provider = req?.provider || "google";
|
|
25
|
+
const { data, error } = await this.supabase.auth.signInWithOAuth({
|
|
26
|
+
provider,
|
|
27
|
+
options: {
|
|
28
|
+
redirectTo: targetRedirect,
|
|
29
|
+
skipBrowserRedirect: true,
|
|
30
|
+
// Lấy URL trả về, không nhảy trang tab chính
|
|
31
|
+
queryParams: {
|
|
32
|
+
client_id: this.clientId
|
|
33
|
+
// Gắn Client ID để Auth Server nhận diện App
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
if (error) throw error;
|
|
38
|
+
if (!data?.url) throw new Error("CANNOT_GENERATE_AUTH_URL");
|
|
39
|
+
const width = 480;
|
|
40
|
+
const height = 680;
|
|
41
|
+
const left = typeof window !== "undefined" ? window.screenX + (window.outerWidth - width) / 2 : 0;
|
|
42
|
+
const top = typeof window !== "undefined" ? window.screenY + (window.outerHeight - height) / 2 : 0;
|
|
43
|
+
const popup = window.open(
|
|
44
|
+
data.url,
|
|
45
|
+
"NocalAuthPopup",
|
|
46
|
+
`width=${width},height=${height},left=${left},top=${top},status=yes,scrollbars=yes`
|
|
47
|
+
);
|
|
48
|
+
if (!popup) {
|
|
49
|
+
throw new Error("POPUP_BLOCKED");
|
|
50
|
+
}
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const isPopupClosed = () => {
|
|
53
|
+
try {
|
|
54
|
+
return popup.closed;
|
|
55
|
+
} catch (e) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const timer = setInterval(async () => {
|
|
60
|
+
if (isPopupClosed()) {
|
|
61
|
+
clearInterval(timer);
|
|
62
|
+
const { data: sessionData } = await this.supabase.auth.getSession();
|
|
63
|
+
if (sessionData?.session?.user) {
|
|
64
|
+
resolve(sessionData.session.user);
|
|
65
|
+
} else {
|
|
66
|
+
reject(new Error("LOGIN_CANCELLED_OR_FAILED"));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}, 500);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Lấy thông tin User hiện tại
|
|
74
|
+
*/
|
|
75
|
+
async getUser() {
|
|
76
|
+
const {
|
|
77
|
+
data: { user },
|
|
78
|
+
error
|
|
79
|
+
} = await this.supabase.auth.getUser();
|
|
80
|
+
if (error) throw error;
|
|
81
|
+
return user;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Lấy Session / Access Token hiện tại
|
|
85
|
+
*/
|
|
86
|
+
async getSession() {
|
|
87
|
+
const {
|
|
88
|
+
data: { session },
|
|
89
|
+
error
|
|
90
|
+
} = await this.supabase.auth.getSession();
|
|
91
|
+
if (error) throw error;
|
|
92
|
+
return session;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Đăng xuất khỏi hệ thống
|
|
96
|
+
*/
|
|
97
|
+
async signOut() {
|
|
98
|
+
const { error } = await this.supabase.auth.signOut();
|
|
99
|
+
if (error) throw error;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Lắng nghe sự kiện đăng nhập / đăng xuất
|
|
103
|
+
*/
|
|
104
|
+
onAuthStateChange(callback) {
|
|
105
|
+
return this.supabase.auth.onAuthStateChange(callback);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
export {
|
|
109
|
+
NocalAuthSDK
|
|
110
|
+
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface NocalClientConfig {
|
|
2
|
+
clientId: string;
|
|
3
|
+
redirectUri: string;
|
|
4
|
+
authServerUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface OAuthLoginReq {
|
|
7
|
+
state?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface NocalUser {
|
|
10
|
+
sub: string;
|
|
11
|
+
email?: string;
|
|
12
|
+
phone?: string;
|
|
13
|
+
email_confirmed?: boolean;
|
|
14
|
+
phone_confirmed?: boolean;
|
|
15
|
+
user_metadata?: Record<string, any>;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
export interface NocalSession {
|
|
19
|
+
access_token: string;
|
|
20
|
+
refresh_token: string;
|
|
21
|
+
token_type: string;
|
|
22
|
+
expires_in: number;
|
|
23
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|