nocal-auth-sdk 0.2.0 → 0.2.2

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/index.d.ts CHANGED
@@ -7,16 +7,17 @@ export declare class NocalAuthSDK {
7
7
  private currentUser;
8
8
  constructor(config: NocalClientConfig);
9
9
  /**
10
- * Mở Popup UI Đăng nhập & Ủy quyền OAuth 2.0 với PKCE
10
+ * Mở Popup UI Đăng nhập & Ủy quyền chuẩn Supabase Native OAuth 2.0 với PKCE
11
11
  */
12
12
  signInWithNocal(req?: OAuthLoginReq): Promise<{
13
13
  user: NocalUser;
14
14
  session: NocalSession;
15
15
  }>;
16
- private exchangeCodeForToken;
16
+ exchangeCodeForToken(code: string, codeVerifier: string): Promise<NocalSession>;
17
17
  private fetchUserInfo;
18
18
  getUser(): Promise<NocalUser | null>;
19
19
  getSession(): Promise<NocalSession | null>;
20
20
  signOut(): Promise<void>;
21
21
  }
22
+ export { NocalAuthSDK as NocalAuth };
22
23
  export * from "./types";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const DEFAULT_AUTH_SERVER_URL = "http://localhost:3001";
1
+ const DEFAULT_AUTH_SERVER_URL = "https://hldymiruucsqqzicnwdv.supabase.co";
2
2
  // Helper for PKCE crypto
3
3
  function base64URLEncode(buffer) {
4
4
  let binary = "";
@@ -45,13 +45,13 @@ export class NocalAuthSDK {
45
45
  }
46
46
  }
47
47
  /**
48
- * Mở Popup UI Đăng nhập & Ủy quyền OAuth 2.0 với PKCE
48
+ * Mở Popup UI Đăng nhập & Ủy quyền chuẩn Supabase Native OAuth 2.0 với PKCE
49
49
  */
50
50
  async signInWithNocal(req) {
51
51
  const state = req?.state || generateRandomString(16);
52
52
  const codeVerifier = generateRandomString(32);
53
53
  const codeChallenge = await generateCodeChallenge(codeVerifier);
54
- const authUrl = new URL(`${this.authServerUrl}/oauth/authorize`);
54
+ const authUrl = new URL(`${this.authServerUrl}/auth/v1/oauth/authorize`);
55
55
  authUrl.searchParams.set("client_id", this.clientId);
56
56
  authUrl.searchParams.set("redirect_uri", this.redirectUri);
57
57
  authUrl.searchParams.set("response_type", "code");
@@ -60,8 +60,12 @@ export class NocalAuthSDK {
60
60
  authUrl.searchParams.set("code_challenge_method", "S256");
61
61
  const width = 480;
62
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;
63
+ const left = typeof window !== "undefined"
64
+ ? window.screenX + (window.outerWidth - width) / 2
65
+ : 0;
66
+ const top = typeof window !== "undefined"
67
+ ? window.screenY + (window.outerHeight - height) / 2
68
+ : 0;
65
69
  const popup = window.open(authUrl.toString(), "NocalAuthPopup", `width=${width},height=${height},left=${left},top=${top},status=yes,scrollbars=yes`);
66
70
  if (!popup) {
67
71
  throw new Error("POPUP_BLOCKED");
@@ -72,7 +76,9 @@ export class NocalAuthSDK {
72
76
  if (event.origin !== allowedOrigin)
73
77
  return;
74
78
  const data = event.data;
75
- if (!data || (data.type !== "NOCAL_OAUTH_CODE" && data.type !== "NOCAL_OAUTH_ERROR")) {
79
+ if (!data ||
80
+ (data.type !== "NOCAL_OAUTH_CODE" &&
81
+ data.type !== "NOCAL_OAUTH_ERROR")) {
76
82
  return;
77
83
  }
78
84
  window.removeEventListener("message", messageListener);
@@ -95,7 +101,6 @@ export class NocalAuthSDK {
95
101
  }
96
102
  try {
97
103
  popup.close();
98
- // Đổi code lấy token
99
104
  const session = await this.exchangeCodeForToken(code, codeVerifier);
100
105
  const user = await this.fetchUserInfo(session.access_token);
101
106
  this.currentSession = session;
@@ -117,6 +122,40 @@ export class NocalAuthSDK {
117
122
  window.removeEventListener("message", messageListener);
118
123
  reject(new Error("POPUP_CLOSED_BY_USER"));
119
124
  }
125
+ else {
126
+ try {
127
+ const popupUrl = new URL(popup.location.href);
128
+ if (popupUrl.origin === new URL(this.redirectUri).origin) {
129
+ const code = popupUrl.searchParams.get("code");
130
+ const error = popupUrl.searchParams.get("error");
131
+ if (code || error) {
132
+ clearInterval(checkClosedTimer);
133
+ window.removeEventListener("message", messageListener);
134
+ popup.close();
135
+ if (error) {
136
+ reject(new Error(error));
137
+ return;
138
+ }
139
+ if (code) {
140
+ this.exchangeCodeForToken(code, codeVerifier)
141
+ .then(async (session) => {
142
+ const user = await this.fetchUserInfo(session.access_token);
143
+ this.currentSession = session;
144
+ this.currentUser = user;
145
+ if (typeof window !== "undefined") {
146
+ localStorage.setItem("nocal_auth_session", JSON.stringify({ session, user }));
147
+ }
148
+ resolve({ user, session });
149
+ })
150
+ .catch(reject);
151
+ }
152
+ }
153
+ }
154
+ }
155
+ catch (e) {
156
+ // Cross-origin check
157
+ }
158
+ }
120
159
  }
121
160
  catch (e) {
122
161
  // ignore
@@ -125,25 +164,27 @@ export class NocalAuthSDK {
125
164
  });
126
165
  }
127
166
  async exchangeCodeForToken(code, codeVerifier) {
128
- const res = await fetch(`${this.authServerUrl}/api/oauth/token`, {
167
+ const params = new URLSearchParams();
168
+ params.set("grant_type", "authorization_code");
169
+ params.set("client_id", this.clientId);
170
+ params.set("redirect_uri", this.redirectUri);
171
+ params.set("code", code);
172
+ params.set("code_verifier", codeVerifier); // PKCE xác thực thay cho secret
173
+ const response = await fetch(`${this.authServerUrl}/auth/v1/oauth/token`, {
129
174
  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
- }),
175
+ headers: {
176
+ "Content-Type": "application/x-www-form-urlencoded",
177
+ },
178
+ body: params.toString(),
138
179
  });
139
- const data = await res.json();
140
- if (!res.ok) {
141
- throw new Error(data.error_description || data.error || "FAILED_TO_EXCHANGE_TOKEN");
180
+ if (!response.ok) {
181
+ const errorData = await response.json();
182
+ throw new Error(`Supabase Auth Error: ${errorData.error_description || errorData.error}`);
142
183
  }
143
- return data;
184
+ return (await response.json());
144
185
  }
145
186
  async fetchUserInfo(accessToken) {
146
- const res = await fetch(`${this.authServerUrl}/api/oauth/userinfo`, {
187
+ const res = await fetch(`${this.authServerUrl}/auth/v1/oauth/userinfo`, {
147
188
  headers: {
148
189
  Authorization: `Bearer ${accessToken}`,
149
190
  },
@@ -168,4 +209,5 @@ export class NocalAuthSDK {
168
209
  }
169
210
  }
170
211
  }
212
+ export { NocalAuthSDK as NocalAuth };
171
213
  export * from "./types";
package/dist/types.d.ts CHANGED
@@ -2,9 +2,12 @@ export interface NocalClientConfig {
2
2
  clientId: string;
3
3
  redirectUri: string;
4
4
  authServerUrl?: string;
5
+ storageKey?: string;
5
6
  }
6
7
  export interface OAuthLoginReq {
7
8
  state?: string;
9
+ provider?: string;
10
+ redirectTo?: string;
8
11
  }
9
12
  export interface NocalUser {
10
13
  sub: string;
@@ -12,12 +15,13 @@ export interface NocalUser {
12
15
  phone?: string;
13
16
  email_confirmed?: boolean;
14
17
  phone_confirmed?: boolean;
15
- user_metadata?: Record<string, any>;
16
- [key: string]: any;
18
+ user_metadata?: Record<string, unknown>;
19
+ [key: string]: unknown;
17
20
  }
18
21
  export interface NocalSession {
19
22
  access_token: string;
20
23
  refresh_token: string;
21
24
  token_type: string;
22
25
  expires_in: number;
26
+ expires_at?: number;
23
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nocal-auth-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Nocal Auth - client-side SDK for Login with Nocal (popup flow)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",