@roudanio/awesome-auth 0.1.3 → 0.1.4
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/auth.d.ts +15 -1
- package/dist/awesome-auth.iife.js +1 -1
- package/dist/awesome-auth.js +214 -168
- package/dist/awesome-auth.umd.js +1 -1
- package/package.json +1 -1
- package/tests/unit/auth.test.ts +44 -2
- package/tsconfig.app.tsbuildinfo +1 -1
package/dist/auth.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { default as EventEmitter3 } from 'eventemitter3';
|
|
2
2
|
import { JwtPayload } from 'jwt-decode';
|
|
3
|
+
export type GoogleButtonOptions = {
|
|
4
|
+
type?: 'standard' | 'icon';
|
|
5
|
+
theme?: 'outline' | 'filled_blue' | 'filled_black';
|
|
6
|
+
size?: 'small' | 'medium' | 'large';
|
|
7
|
+
text?: 'signin_with' | 'signup_with' | 'continue_with' | 'signin';
|
|
8
|
+
shape?: 'rectangular' | 'pill' | 'circle' | 'square';
|
|
9
|
+
logo_alignment?: 'left' | 'center';
|
|
10
|
+
width?: number;
|
|
11
|
+
locale?: string;
|
|
12
|
+
};
|
|
3
13
|
export interface AwesomeAuthProps {
|
|
4
14
|
googleId: string;
|
|
5
15
|
prefix?: string;
|
|
@@ -17,7 +27,7 @@ export declare enum AwesomeAuthEvent {
|
|
|
17
27
|
}
|
|
18
28
|
export declare class AwesomeAuth extends EventEmitter3 {
|
|
19
29
|
#private;
|
|
20
|
-
constructor({ googleId, prefix, root
|
|
30
|
+
constructor({ googleId, prefix, root }: AwesomeAuthProps);
|
|
21
31
|
get accessToken(): string;
|
|
22
32
|
get expiredIn(): number;
|
|
23
33
|
get isVerifying(): boolean;
|
|
@@ -30,10 +40,14 @@ export declare class AwesomeAuth extends EventEmitter3 {
|
|
|
30
40
|
store(key: string, value: unknown): Promise<void>;
|
|
31
41
|
retrieve(key: string): Promise<unknown>;
|
|
32
42
|
private initGoogleIdentity;
|
|
43
|
+
renderButton(target: HTMLElement, options?: GoogleButtonOptions): Promise<void>;
|
|
44
|
+
private ensureGoogleIdentityInitialized;
|
|
45
|
+
private handlePromptMoment;
|
|
33
46
|
private refreshCountDown;
|
|
34
47
|
private refreshToken;
|
|
35
48
|
private setAccessToken;
|
|
36
49
|
private verifyToken;
|
|
37
50
|
private onGoogleIdentityCallback;
|
|
51
|
+
private getRevokeHint;
|
|
38
52
|
}
|
|
39
53
|
export declare function getInstance(params: AwesomeAuthProps): AwesomeAuth;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var AwesomeAuth=(function(
|
|
1
|
+
var AwesomeAuth=(function(I){"use strict";function L(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var k={exports:{}},C;function R(){return C||(C=1,(function(r){var e=Object.prototype.hasOwnProperty,t="~";function a(){}Object.create&&(a.prototype=Object.create(null),new a().__proto__||(t=!1));function f(c,i,s){this.fn=c,this.context=i,this.once=s||!1}function p(c,i,s,o,g){if(typeof s!="function")throw new TypeError("The listener must be a function");var d=new f(s,o||c,g),l=t?t+i:i;return c._events[l]?c._events[l].fn?c._events[l]=[c._events[l],d]:c._events[l].push(d):(c._events[l]=d,c._eventsCount++),c}function w(c,i){--c._eventsCount===0?c._events=new a:delete c._events[i]}function u(){this._events=new a,this._eventsCount=0}u.prototype.eventNames=function(){var i=[],s,o;if(this._eventsCount===0)return i;for(o in s=this._events)e.call(s,o)&&i.push(t?o.slice(1):o);return Object.getOwnPropertySymbols?i.concat(Object.getOwnPropertySymbols(s)):i},u.prototype.listeners=function(i){var s=t?t+i:i,o=this._events[s];if(!o)return[];if(o.fn)return[o.fn];for(var g=0,d=o.length,l=new Array(d);g<d;g++)l[g]=o[g].fn;return l},u.prototype.listenerCount=function(i){var s=t?t+i:i,o=this._events[s];return o?o.fn?1:o.length:0},u.prototype.emit=function(i,s,o,g,d,l){var y=t?t+i:i;if(!this._events[y])return!1;var n=this._events[y],v=arguments.length,m,h;if(n.fn){switch(n.once&&this.removeListener(i,n.fn,void 0,!0),v){case 1:return n.fn.call(n.context),!0;case 2:return n.fn.call(n.context,s),!0;case 3:return n.fn.call(n.context,s,o),!0;case 4:return n.fn.call(n.context,s,o,g),!0;case 5:return n.fn.call(n.context,s,o,g,d),!0;case 6:return n.fn.call(n.context,s,o,g,d,l),!0}for(h=1,m=new Array(v-1);h<v;h++)m[h-1]=arguments[h];n.fn.apply(n.context,m)}else{var oe=n.length,O;for(h=0;h<oe;h++)switch(n[h].once&&this.removeListener(i,n[h].fn,void 0,!0),v){case 1:n[h].fn.call(n[h].context);break;case 2:n[h].fn.call(n[h].context,s);break;case 3:n[h].fn.call(n[h].context,s,o);break;case 4:n[h].fn.call(n[h].context,s,o,g);break;default:if(!m)for(O=1,m=new Array(v-1);O<v;O++)m[O-1]=arguments[O];n[h].fn.apply(n[h].context,m)}}return!0},u.prototype.on=function(i,s,o){return p(this,i,s,o,!1)},u.prototype.once=function(i,s,o){return p(this,i,s,o,!0)},u.prototype.removeListener=function(i,s,o,g){var d=t?t+i:i;if(!this._events[d])return this;if(!s)return w(this,d),this;var l=this._events[d];if(l.fn)l.fn===s&&(!g||l.once)&&(!o||l.context===o)&&w(this,d);else{for(var y=0,n=[],v=l.length;y<v;y++)(l[y].fn!==s||g&&!l[y].once||o&&l[y].context!==o)&&n.push(l[y]);n.length?this._events[d]=n.length===1?n[0]:n:w(this,d)}return this},u.prototype.removeAllListeners=function(i){var s;return i?(s=t?t+i:i,this._events[s]&&w(this,s)):(this._events=new a,this._eventsCount=0),this},u.prototype.off=u.prototype.removeListener,u.prototype.addListener=u.prototype.on,u.prefixed=t,u.EventEmitter=u,r.exports=u})(k)),k.exports}var D=R();const N=L(D);class S extends Error{}S.prototype.name="InvalidTokenError";function z(r){return decodeURIComponent(atob(r).replace(/(.)/g,(e,t)=>{let a=t.charCodeAt(0).toString(16).toUpperCase();return a.length<2&&(a="0"+a),"%"+a}))}function B(r){let e=r.replace(/-/g,"+").replace(/_/g,"/");switch(e.length%4){case 0:break;case 2:e+="==";break;case 3:e+="=";break;default:throw new Error("base64 string is not of the correct length")}try{return z(e)}catch{return atob(e)}}function F(r,e){if(typeof r!="string")throw new S("Invalid token specified: must be a string");e||(e={});const t=e.header===!0?0:1,a=r.split(".")[t];if(typeof a!="string")throw new S(`Invalid token specified: missing part #${t+1}`);let f;try{f=B(a)}catch(p){throw new S(`Invalid token specified: invalid base64 for part #${t+1} (${p.message})`)}try{return JSON.parse(f)}catch(p){throw new S(`Invalid token specified: invalid json for part #${t+1} (${p.message})`)}}var M=typeof global=="object"&&global&&global.Object===Object&&global,V=typeof self=="object"&&self&&self.Object===Object&&self,J=M||V||Function("return this")(),_=J.Symbol,$=Object.prototype,U=$.hasOwnProperty,q=$.toString,T=_?_.toStringTag:void 0;function H(r){var e=U.call(r,T),t=r[T];try{r[T]=void 0;var a=!0}catch{}var f=q.call(r);return a&&(e?r[T]=t:delete r[T]),f}var K=Object.prototype,Y=K.toString;function Q(r){return Y.call(r)}var W="[object Null]",X="[object Undefined]",A=_?_.toStringTag:void 0;function Z(r){return r==null?r===void 0?X:W:A&&A in Object(r)?H(r):Q(r)}var ee=Array.isArray;function te(r){return r!=null&&typeof r=="object"}var re="[object String]";function ne(r){return typeof r=="string"||!ee(r)&&te(r)&&Z(r)==re}var P=(r=>(r.INIT="init",r.VERIFYING="verifying",r.VERIFIED="verified",r.REFRESH="refresh",r.ERROR="error",r))(P||{});let j;class G extends N{#t="";#e={};#o=0;#c;#i=!1;#s=!1;#n=!1;#l=!1;#a;#h;#r;constructor({googleId:e,prefix:t="aAuth",root:a="/api"}){if(super(),this.#c=e,this.#h=t,this.#r=a,this.#a=Date.now()/1e3>>0,this.setAccessToken(localStorage.getItem(this.localKey)||"",!1),this.#t){this.verifyToken().then(f=>{f||this.initGoogleIdentity()});return}this.initGoogleIdentity()}get accessToken(){return this.#t}get expiredIn(){return this.#o?0:this.#o-this.#a}get isVerifying(){return this.#s}get isVerified(){return this.#n}get localKey(){return`${this.#h}-token`}get root(){return this.#r}get user(){return this.#e}doSignIn(){this.initGoogleIdentity()}doSignOut(){const e=this.getRevokeHint();this.setAccessToken(""),this.#e={},this.#n=!1,clearInterval(j),this.emit("verified",!1),e&&"google"in globalThis&&"accounts"in globalThis.google&&google.accounts.id.revoke(e)}async store(e,t){t=ne(t)?t:JSON.stringify(t),await fetch(`${this.#r}/store`,{method:"POST",headers:{"Content-type":"application/json",Authorization:`Bearer ${this.#t}`},body:JSON.stringify({key:e,value:t})})}async retrieve(e){const t=await fetch(`${this.#r}/retrieve`,{method:"POST",headers:{"Content-type":"application/json",Authorization:`Bearer ${this.#t}`},body:JSON.stringify({key:e})}),{data:a}=await t.json();return a?.value}initGoogleIdentity(){this.#i||(this.emit("init",!0),this.#i=!0,this.ensureGoogleIdentityInitialized().then(()=>{google.accounts.id.prompt(e=>{this.handlePromptMoment(e)})}).catch(e=>{this.#i=!1,this.emit("init",!1),this.emit("error",e.message||String(e))}))}async renderButton(e,t){if(e){try{await this.ensureGoogleIdentityInitialized()}catch(a){this.emit("error",a.message||String(a));return}if(!E()){this.emit("error","Google Identity Services 未加载完成");return}google.accounts.id.renderButton(e,{type:"standard",theme:"outline",size:"large",text:"signin_with",...t})}}async ensureGoogleIdentityInitialized(){if(await ie(),!E())throw new Error("Google Identity Services 未加载完成");this.#l||(google.accounts.id.initialize({client_id:this.#c,callback:e=>this.onGoogleIdentityCallback(e),auto_select:!0,ux_mode:"popup"}),this.#l=!0)}handlePromptMoment(e){(e.isNotDisplayed()||e.isSkippedMoment()||e.isDismissedMoment())&&(this.#i=!1,this.emit("init",!1))}refreshCountDown(){this.#a=Date.now()/1e3>>0,this.expiredIn<=60&&(clearInterval(j),this.refreshToken())}async refreshToken(){this.emit("refresh",!0);const e=await fetch(`${this.#r}/refresh-token`,{method:"POST",headers:{"Content-type":"application/json",Authorization:`Bearer ${this.#t}`}}),{data:t}=await e.json(),{token:a}=t;this.setAccessToken(a),this.emit("refresh",!1)}setAccessToken(e,t=!0){if(this.#t=e,t&&localStorage.setItem(this.localKey,e),!e){this.#e={},this.#o=0;return}try{this.#e=F(e)}catch{this.#e={}}this.#o=this.#e.exp||0,this.expiredIn>0&&(clearInterval(j),j=setInterval(()=>this.refreshCountDown(),1e3))}async verifyToken(){this.emit("verifying",!0),this.#s=!0;try{const e=await fetch(`${this.#r}/verify-auth`,{method:"POST",headers:{"Content-type":"application/json",Authorization:`Bearer ${this.#t}`}}),{data:t}=await e.json();t&&(this.#e=t,this.#n=!0,this.emit("verified",!0))}catch(e){this.#n=!1,this.emit("error",e.message||String(e))}return this.emit("verifying",!1),this.#s=!1,this.#n}async onGoogleIdentityCallback(e){this.emit("init",!1),this.#i=!1,this.emit("verifying",!0),this.#s=!0;const t=await fetch(`${this.#r}/google-auth`,{method:"POST",headers:{"Content-type":"application/json"},body:JSON.stringify({credential:e.credential})}),{data:a}=await t.json();a||this.emit("error","Failed to validate user.");const{token:f}=a;this.setAccessToken(f),this.emit("verifying",!1),this.#s=!1,this.emit("verified",!0),this.#n=!0}getRevokeHint(){const e=this.#e.email;if(typeof e=="string"&&e.trim())return e;const t=this.#e.sub;return typeof t=="string"&&t.trim()?t:""}}let b=null;function E(){return"google"in globalThis&&"accounts"in globalThis.google}function ie(){return E()?Promise.resolve():b||(b=new Promise((r,e)=>{const t="https://accounts.google.com/gsi/client",a=document.querySelector(`script[src="${t}"]`),f=a||document.createElement("script");function p(){r()}function w(){e(new Error("Google Identity Services 加载失败"))}f.addEventListener("load",p,{once:!0}),f.addEventListener("error",w,{once:!0}),a||(f.src=t,f.async=!0,document.head.appendChild(f))}),b.catch(()=>{b=null}),b)}let x;function se(r){return x=x||new G(r),x}return I.AwesomeAuth=G,I.AwesomeAuthEvent=P,I.getInstance=se,Object.defineProperty(I,Symbol.toStringTag,{value:"Module"}),I})({});
|
package/dist/awesome-auth.js
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
function
|
|
2
|
-
return
|
|
1
|
+
function G(r) {
|
|
2
|
+
return r && r.__esModule && Object.prototype.hasOwnProperty.call(r, "default") ? r.default : r;
|
|
3
3
|
}
|
|
4
|
-
var
|
|
5
|
-
function
|
|
6
|
-
return
|
|
7
|
-
var
|
|
4
|
+
var j = { exports: {} }, E;
|
|
5
|
+
function A() {
|
|
6
|
+
return E || (E = 1, (function(r) {
|
|
7
|
+
var e = Object.prototype.hasOwnProperty, t = "~";
|
|
8
8
|
function a() {
|
|
9
9
|
}
|
|
10
10
|
Object.create && (a.prototype = /* @__PURE__ */ Object.create(null), new a().__proto__ || (t = !1));
|
|
11
|
-
function
|
|
11
|
+
function f(c, i, s) {
|
|
12
12
|
this.fn = c, this.context = i, this.once = s || !1;
|
|
13
13
|
}
|
|
14
|
-
function
|
|
14
|
+
function p(c, i, s, o, g) {
|
|
15
15
|
if (typeof s != "function")
|
|
16
16
|
throw new TypeError("The listener must be a function");
|
|
17
|
-
var
|
|
18
|
-
return c._events[l] ? c._events[l].fn ? c._events[l] = [c._events[l],
|
|
17
|
+
var d = new f(s, o || c, g), l = t ? t + i : i;
|
|
18
|
+
return c._events[l] ? c._events[l].fn ? c._events[l] = [c._events[l], d] : c._events[l].push(d) : (c._events[l] = d, c._eventsCount++), c;
|
|
19
19
|
}
|
|
20
|
-
function
|
|
20
|
+
function b(c, i) {
|
|
21
21
|
--c._eventsCount === 0 ? c._events = new a() : delete c._events[i];
|
|
22
22
|
}
|
|
23
|
-
function
|
|
23
|
+
function u() {
|
|
24
24
|
this._events = new a(), this._eventsCount = 0;
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
u.prototype.eventNames = function() {
|
|
27
27
|
var i = [], s, o;
|
|
28
28
|
if (this._eventsCount === 0) return i;
|
|
29
29
|
for (o in s = this._events)
|
|
30
|
-
|
|
30
|
+
e.call(s, o) && i.push(t ? o.slice(1) : o);
|
|
31
31
|
return Object.getOwnPropertySymbols ? i.concat(Object.getOwnPropertySymbols(s)) : i;
|
|
32
|
-
},
|
|
32
|
+
}, u.prototype.listeners = function(i) {
|
|
33
33
|
var s = t ? t + i : i, o = this._events[s];
|
|
34
34
|
if (!o) return [];
|
|
35
35
|
if (o.fn) return [o.fn];
|
|
36
|
-
for (var
|
|
37
|
-
l[
|
|
36
|
+
for (var g = 0, d = o.length, l = new Array(d); g < d; g++)
|
|
37
|
+
l[g] = o[g].fn;
|
|
38
38
|
return l;
|
|
39
|
-
},
|
|
39
|
+
}, u.prototype.listenerCount = function(i) {
|
|
40
40
|
var s = t ? t + i : i, o = this._events[s];
|
|
41
41
|
return o ? o.fn ? 1 : o.length : 0;
|
|
42
|
-
},
|
|
43
|
-
var
|
|
44
|
-
if (!this._events[
|
|
45
|
-
var n = this._events[
|
|
42
|
+
}, u.prototype.emit = function(i, s, o, g, d, l) {
|
|
43
|
+
var y = t ? t + i : i;
|
|
44
|
+
if (!this._events[y]) return !1;
|
|
45
|
+
var n = this._events[y], v = arguments.length, m, h;
|
|
46
46
|
if (n.fn) {
|
|
47
|
-
switch (n.once && this.removeListener(i, n.fn, void 0, !0),
|
|
47
|
+
switch (n.once && this.removeListener(i, n.fn, void 0, !0), v) {
|
|
48
48
|
case 1:
|
|
49
49
|
return n.fn.call(n.context), !0;
|
|
50
50
|
case 2:
|
|
@@ -52,301 +52,347 @@ function P() {
|
|
|
52
52
|
case 3:
|
|
53
53
|
return n.fn.call(n.context, s, o), !0;
|
|
54
54
|
case 4:
|
|
55
|
-
return n.fn.call(n.context, s, o,
|
|
55
|
+
return n.fn.call(n.context, s, o, g), !0;
|
|
56
56
|
case 5:
|
|
57
|
-
return n.fn.call(n.context, s, o,
|
|
57
|
+
return n.fn.call(n.context, s, o, g, d), !0;
|
|
58
58
|
case 6:
|
|
59
|
-
return n.fn.call(n.context, s, o,
|
|
59
|
+
return n.fn.call(n.context, s, o, g, d, l), !0;
|
|
60
60
|
}
|
|
61
|
-
for (
|
|
62
|
-
|
|
63
|
-
n.fn.apply(n.context,
|
|
61
|
+
for (h = 1, m = new Array(v - 1); h < v; h++)
|
|
62
|
+
m[h - 1] = arguments[h];
|
|
63
|
+
n.fn.apply(n.context, m);
|
|
64
64
|
} else {
|
|
65
|
-
var
|
|
66
|
-
for (
|
|
67
|
-
switch (n[
|
|
65
|
+
var P = n.length, I;
|
|
66
|
+
for (h = 0; h < P; h++)
|
|
67
|
+
switch (n[h].once && this.removeListener(i, n[h].fn, void 0, !0), v) {
|
|
68
68
|
case 1:
|
|
69
|
-
n[
|
|
69
|
+
n[h].fn.call(n[h].context);
|
|
70
70
|
break;
|
|
71
71
|
case 2:
|
|
72
|
-
n[
|
|
72
|
+
n[h].fn.call(n[h].context, s);
|
|
73
73
|
break;
|
|
74
74
|
case 3:
|
|
75
|
-
n[
|
|
75
|
+
n[h].fn.call(n[h].context, s, o);
|
|
76
76
|
break;
|
|
77
77
|
case 4:
|
|
78
|
-
n[
|
|
78
|
+
n[h].fn.call(n[h].context, s, o, g);
|
|
79
79
|
break;
|
|
80
80
|
default:
|
|
81
|
-
if (!
|
|
82
|
-
|
|
83
|
-
n[
|
|
81
|
+
if (!m) for (I = 1, m = new Array(v - 1); I < v; I++)
|
|
82
|
+
m[I - 1] = arguments[I];
|
|
83
|
+
n[h].fn.apply(n[h].context, m);
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
return !0;
|
|
87
|
-
},
|
|
88
|
-
return
|
|
89
|
-
},
|
|
90
|
-
return
|
|
91
|
-
},
|
|
92
|
-
var
|
|
93
|
-
if (!this._events[
|
|
87
|
+
}, u.prototype.on = function(i, s, o) {
|
|
88
|
+
return p(this, i, s, o, !1);
|
|
89
|
+
}, u.prototype.once = function(i, s, o) {
|
|
90
|
+
return p(this, i, s, o, !0);
|
|
91
|
+
}, u.prototype.removeListener = function(i, s, o, g) {
|
|
92
|
+
var d = t ? t + i : i;
|
|
93
|
+
if (!this._events[d]) return this;
|
|
94
94
|
if (!s)
|
|
95
|
-
return
|
|
96
|
-
var l = this._events[
|
|
95
|
+
return b(this, d), this;
|
|
96
|
+
var l = this._events[d];
|
|
97
97
|
if (l.fn)
|
|
98
|
-
l.fn === s && (!
|
|
98
|
+
l.fn === s && (!g || l.once) && (!o || l.context === o) && b(this, d);
|
|
99
99
|
else {
|
|
100
|
-
for (var
|
|
101
|
-
(l[
|
|
102
|
-
n.length ? this._events[
|
|
100
|
+
for (var y = 0, n = [], v = l.length; y < v; y++)
|
|
101
|
+
(l[y].fn !== s || g && !l[y].once || o && l[y].context !== o) && n.push(l[y]);
|
|
102
|
+
n.length ? this._events[d] = n.length === 1 ? n[0] : n : b(this, d);
|
|
103
103
|
}
|
|
104
104
|
return this;
|
|
105
|
-
},
|
|
105
|
+
}, u.prototype.removeAllListeners = function(i) {
|
|
106
106
|
var s;
|
|
107
|
-
return i ? (s = t ? t + i : i, this._events[s] &&
|
|
108
|
-
},
|
|
109
|
-
})(
|
|
107
|
+
return i ? (s = t ? t + i : i, this._events[s] && b(this, s)) : (this._events = new a(), this._eventsCount = 0), this;
|
|
108
|
+
}, u.prototype.off = u.prototype.removeListener, u.prototype.addListener = u.prototype.on, u.prefixed = t, u.EventEmitter = u, r.exports = u;
|
|
109
|
+
})(j)), j.exports;
|
|
110
110
|
}
|
|
111
|
-
var
|
|
112
|
-
const
|
|
111
|
+
var L = A();
|
|
112
|
+
const R = /* @__PURE__ */ G(L);
|
|
113
113
|
class T extends Error {
|
|
114
114
|
}
|
|
115
115
|
T.prototype.name = "InvalidTokenError";
|
|
116
|
-
function
|
|
117
|
-
return decodeURIComponent(atob(
|
|
116
|
+
function D(r) {
|
|
117
|
+
return decodeURIComponent(atob(r).replace(/(.)/g, (e, t) => {
|
|
118
118
|
let a = t.charCodeAt(0).toString(16).toUpperCase();
|
|
119
119
|
return a.length < 2 && (a = "0" + a), "%" + a;
|
|
120
120
|
}));
|
|
121
121
|
}
|
|
122
|
-
function N(
|
|
123
|
-
let
|
|
124
|
-
switch (
|
|
122
|
+
function N(r) {
|
|
123
|
+
let e = r.replace(/-/g, "+").replace(/_/g, "/");
|
|
124
|
+
switch (e.length % 4) {
|
|
125
125
|
case 0:
|
|
126
126
|
break;
|
|
127
127
|
case 2:
|
|
128
|
-
|
|
128
|
+
e += "==";
|
|
129
129
|
break;
|
|
130
130
|
case 3:
|
|
131
|
-
|
|
131
|
+
e += "=";
|
|
132
132
|
break;
|
|
133
133
|
default:
|
|
134
134
|
throw new Error("base64 string is not of the correct length");
|
|
135
135
|
}
|
|
136
136
|
try {
|
|
137
|
-
return
|
|
137
|
+
return D(e);
|
|
138
138
|
} catch {
|
|
139
|
-
return atob(
|
|
139
|
+
return atob(e);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
-
function
|
|
143
|
-
if (typeof
|
|
142
|
+
function z(r, e) {
|
|
143
|
+
if (typeof r != "string")
|
|
144
144
|
throw new T("Invalid token specified: must be a string");
|
|
145
|
-
|
|
146
|
-
const t =
|
|
145
|
+
e || (e = {});
|
|
146
|
+
const t = e.header === !0 ? 0 : 1, a = r.split(".")[t];
|
|
147
147
|
if (typeof a != "string")
|
|
148
148
|
throw new T(`Invalid token specified: missing part #${t + 1}`);
|
|
149
|
-
let
|
|
149
|
+
let f;
|
|
150
150
|
try {
|
|
151
|
-
|
|
152
|
-
} catch (
|
|
153
|
-
throw new T(`Invalid token specified: invalid base64 for part #${t + 1} (${
|
|
151
|
+
f = N(a);
|
|
152
|
+
} catch (p) {
|
|
153
|
+
throw new T(`Invalid token specified: invalid base64 for part #${t + 1} (${p.message})`);
|
|
154
154
|
}
|
|
155
155
|
try {
|
|
156
|
-
return JSON.parse(
|
|
157
|
-
} catch (
|
|
158
|
-
throw new T(`Invalid token specified: invalid json for part #${t + 1} (${
|
|
156
|
+
return JSON.parse(f);
|
|
157
|
+
} catch (p) {
|
|
158
|
+
throw new T(`Invalid token specified: invalid json for part #${t + 1} (${p.message})`);
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
var
|
|
162
|
-
function U(
|
|
163
|
-
var
|
|
161
|
+
var B = typeof global == "object" && global && global.Object === Object && global, F = typeof self == "object" && self && self.Object === Object && self, V = B || F || Function("return this")(), O = V.Symbol, $ = Object.prototype, J = $.hasOwnProperty, M = $.toString, S = O ? O.toStringTag : void 0;
|
|
162
|
+
function U(r) {
|
|
163
|
+
var e = J.call(r, S), t = r[S];
|
|
164
164
|
try {
|
|
165
|
-
|
|
165
|
+
r[S] = void 0;
|
|
166
166
|
var a = !0;
|
|
167
167
|
} catch {
|
|
168
168
|
}
|
|
169
|
-
var
|
|
170
|
-
return a && (
|
|
169
|
+
var f = M.call(r);
|
|
170
|
+
return a && (e ? r[S] = t : delete r[S]), f;
|
|
171
171
|
}
|
|
172
|
-
var
|
|
173
|
-
function K(
|
|
174
|
-
return
|
|
172
|
+
var q = Object.prototype, H = q.toString;
|
|
173
|
+
function K(r) {
|
|
174
|
+
return H.call(r);
|
|
175
175
|
}
|
|
176
|
-
var
|
|
177
|
-
function
|
|
178
|
-
return
|
|
176
|
+
var Y = "[object Null]", Q = "[object Undefined]", C = O ? O.toStringTag : void 0;
|
|
177
|
+
function W(r) {
|
|
178
|
+
return r == null ? r === void 0 ? Q : Y : C && C in Object(r) ? U(r) : K(r);
|
|
179
179
|
}
|
|
180
|
-
var
|
|
181
|
-
function
|
|
182
|
-
return
|
|
180
|
+
var X = Array.isArray;
|
|
181
|
+
function Z(r) {
|
|
182
|
+
return r != null && typeof r == "object";
|
|
183
183
|
}
|
|
184
|
-
var
|
|
185
|
-
function
|
|
186
|
-
return typeof
|
|
184
|
+
var ee = "[object String]";
|
|
185
|
+
function te(r) {
|
|
186
|
+
return typeof r == "string" || !X(r) && Z(r) && W(r) == ee;
|
|
187
187
|
}
|
|
188
|
-
var
|
|
189
|
-
let
|
|
190
|
-
class
|
|
191
|
-
#
|
|
192
|
-
#
|
|
193
|
-
#
|
|
188
|
+
var re = /* @__PURE__ */ ((r) => (r.INIT = "init", r.VERIFYING = "verifying", r.VERIFIED = "verified", r.REFRESH = "refresh", r.ERROR = "error", r))(re || {});
|
|
189
|
+
let _;
|
|
190
|
+
class ne extends R {
|
|
191
|
+
#t = "";
|
|
192
|
+
#e = {};
|
|
193
|
+
#o = 0;
|
|
194
194
|
#c;
|
|
195
|
-
#o = !1;
|
|
196
|
-
#n = !1;
|
|
197
195
|
#i = !1;
|
|
196
|
+
#s = !1;
|
|
197
|
+
#n = !1;
|
|
198
|
+
#l = !1;
|
|
198
199
|
#a;
|
|
199
|
-
#
|
|
200
|
+
#h;
|
|
200
201
|
#r;
|
|
201
|
-
constructor({
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}) {
|
|
206
|
-
if (super(), this.#c = r, this.#l = t, this.#r = a, this.#a = Date.now() / 1e3 >> 0, this.setAccessToken(localStorage.getItem(this.localKey) || "", !1), this.#e) {
|
|
207
|
-
this.verifyToken().then((d) => {
|
|
208
|
-
d || this.initGoogleIdentity();
|
|
202
|
+
constructor({ googleId: e, prefix: t = "aAuth", root: a = "/api" }) {
|
|
203
|
+
if (super(), this.#c = e, this.#h = t, this.#r = a, this.#a = Date.now() / 1e3 >> 0, this.setAccessToken(localStorage.getItem(this.localKey) || "", !1), this.#t) {
|
|
204
|
+
this.verifyToken().then((f) => {
|
|
205
|
+
f || this.initGoogleIdentity();
|
|
209
206
|
});
|
|
210
207
|
return;
|
|
211
208
|
}
|
|
212
209
|
this.initGoogleIdentity();
|
|
213
210
|
}
|
|
214
211
|
get accessToken() {
|
|
215
|
-
return this.#
|
|
212
|
+
return this.#t;
|
|
216
213
|
}
|
|
217
214
|
get expiredIn() {
|
|
218
|
-
return this.#
|
|
215
|
+
return this.#o ? 0 : this.#o - this.#a;
|
|
219
216
|
}
|
|
220
217
|
get isVerifying() {
|
|
221
|
-
return this.#
|
|
218
|
+
return this.#s;
|
|
222
219
|
}
|
|
223
220
|
get isVerified() {
|
|
224
|
-
return this.#
|
|
221
|
+
return this.#n;
|
|
225
222
|
}
|
|
226
223
|
get localKey() {
|
|
227
|
-
return `${this.#
|
|
224
|
+
return `${this.#h}-token`;
|
|
228
225
|
}
|
|
229
226
|
get root() {
|
|
230
227
|
return this.#r;
|
|
231
228
|
}
|
|
232
229
|
get user() {
|
|
233
|
-
return this.#
|
|
230
|
+
return this.#e;
|
|
234
231
|
}
|
|
235
232
|
doSignIn() {
|
|
236
233
|
this.initGoogleIdentity();
|
|
237
234
|
}
|
|
238
235
|
doSignOut() {
|
|
239
|
-
|
|
236
|
+
const e = this.getRevokeHint();
|
|
237
|
+
this.setAccessToken(""), this.#e = {}, this.#n = !1, clearInterval(_), this.emit("verified", !1), e && "google" in globalThis && "accounts" in globalThis.google && google.accounts.id.revoke(e);
|
|
240
238
|
}
|
|
241
|
-
async store(
|
|
242
|
-
t =
|
|
239
|
+
async store(e, t) {
|
|
240
|
+
t = te(t) ? t : JSON.stringify(t), await fetch(`${this.#r}/store`, {
|
|
243
241
|
method: "POST",
|
|
244
242
|
headers: {
|
|
245
243
|
"Content-type": "application/json",
|
|
246
|
-
Authorization: `Bearer ${this.#
|
|
244
|
+
Authorization: `Bearer ${this.#t}`
|
|
247
245
|
},
|
|
248
246
|
body: JSON.stringify({
|
|
249
|
-
key:
|
|
247
|
+
key: e,
|
|
250
248
|
value: t
|
|
251
249
|
})
|
|
252
250
|
});
|
|
253
251
|
}
|
|
254
|
-
async retrieve(
|
|
252
|
+
async retrieve(e) {
|
|
255
253
|
const t = await fetch(`${this.#r}/retrieve`, {
|
|
256
254
|
method: "POST",
|
|
257
255
|
headers: {
|
|
258
256
|
"Content-type": "application/json",
|
|
259
|
-
Authorization: `Bearer ${this.#
|
|
257
|
+
Authorization: `Bearer ${this.#t}`
|
|
260
258
|
},
|
|
261
259
|
body: JSON.stringify({
|
|
262
|
-
key:
|
|
260
|
+
key: e
|
|
263
261
|
})
|
|
264
262
|
}), { data: a } = await t.json();
|
|
265
263
|
return a?.value;
|
|
266
264
|
}
|
|
267
265
|
initGoogleIdentity() {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
266
|
+
this.#i || (this.emit("init", !0), this.#i = !0, this.ensureGoogleIdentityInitialized().then(() => {
|
|
267
|
+
google.accounts.id.prompt((e) => {
|
|
268
|
+
this.handlePromptMoment(e);
|
|
269
|
+
});
|
|
270
|
+
}).catch((e) => {
|
|
271
|
+
this.#i = !1, this.emit("init", !1), this.emit("error", e.message || String(e));
|
|
272
|
+
}));
|
|
273
|
+
}
|
|
274
|
+
async renderButton(e, t) {
|
|
275
|
+
if (e) {
|
|
276
|
+
try {
|
|
277
|
+
await this.ensureGoogleIdentityInitialized();
|
|
278
|
+
} catch (a) {
|
|
279
|
+
this.emit("error", a.message || String(a));
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if (!x()) {
|
|
283
|
+
this.emit("error", "Google Identity Services 未加载完成");
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
google.accounts.id.renderButton(e, {
|
|
287
|
+
type: "standard",
|
|
288
|
+
theme: "outline",
|
|
289
|
+
size: "large",
|
|
290
|
+
text: "signin_with",
|
|
291
|
+
...t
|
|
292
|
+
});
|
|
271
293
|
}
|
|
272
|
-
|
|
294
|
+
}
|
|
295
|
+
async ensureGoogleIdentityInitialized() {
|
|
296
|
+
if (await ie(), !x())
|
|
297
|
+
throw new Error("Google Identity Services 未加载完成");
|
|
298
|
+
this.#l || (google.accounts.id.initialize({
|
|
273
299
|
client_id: this.#c,
|
|
274
|
-
callback: (
|
|
300
|
+
callback: (e) => this.onGoogleIdentityCallback(e),
|
|
275
301
|
auto_select: !0,
|
|
276
302
|
ux_mode: "popup"
|
|
277
|
-
}),
|
|
303
|
+
}), this.#l = !0);
|
|
304
|
+
}
|
|
305
|
+
handlePromptMoment(e) {
|
|
306
|
+
(e.isNotDisplayed() || e.isSkippedMoment() || e.isDismissedMoment()) && (this.#i = !1, this.emit("init", !1));
|
|
278
307
|
}
|
|
279
308
|
refreshCountDown() {
|
|
280
|
-
this.#a = Date.now() / 1e3 >> 0, this.expiredIn <= 60 && (clearInterval(
|
|
309
|
+
this.#a = Date.now() / 1e3 >> 0, this.expiredIn <= 60 && (clearInterval(_), this.refreshToken());
|
|
281
310
|
}
|
|
282
311
|
async refreshToken() {
|
|
283
312
|
this.emit("refresh", !0);
|
|
284
|
-
const
|
|
313
|
+
const e = await fetch(`${this.#r}/refresh-token`, {
|
|
285
314
|
method: "POST",
|
|
286
315
|
headers: {
|
|
287
316
|
"Content-type": "application/json",
|
|
288
|
-
Authorization: `Bearer ${this.#
|
|
317
|
+
Authorization: `Bearer ${this.#t}`
|
|
289
318
|
}
|
|
290
|
-
}), { data: t } = await
|
|
319
|
+
}), { data: t } = await e.json(), { token: a } = t;
|
|
291
320
|
this.setAccessToken(a), this.emit("refresh", !1);
|
|
292
321
|
}
|
|
293
|
-
setAccessToken(
|
|
294
|
-
if (this.#
|
|
295
|
-
this.#
|
|
322
|
+
setAccessToken(e, t = !0) {
|
|
323
|
+
if (this.#t = e, t && localStorage.setItem(this.localKey, e), !e) {
|
|
324
|
+
this.#e = {}, this.#o = 0;
|
|
296
325
|
return;
|
|
297
326
|
}
|
|
298
327
|
try {
|
|
299
|
-
this.#
|
|
328
|
+
this.#e = z(e);
|
|
300
329
|
} catch {
|
|
301
|
-
this.#
|
|
330
|
+
this.#e = {};
|
|
302
331
|
}
|
|
303
|
-
this.#
|
|
332
|
+
this.#o = this.#e.exp || 0, this.expiredIn > 0 && (clearInterval(_), _ = setInterval(() => this.refreshCountDown(), 1e3));
|
|
304
333
|
}
|
|
305
334
|
async verifyToken() {
|
|
306
|
-
this.emit("verifying", !0), this.#
|
|
335
|
+
this.emit("verifying", !0), this.#s = !0;
|
|
307
336
|
try {
|
|
308
|
-
const
|
|
337
|
+
const e = await fetch(`${this.#r}/verify-auth`, {
|
|
309
338
|
method: "POST",
|
|
310
339
|
headers: {
|
|
311
340
|
"Content-type": "application/json",
|
|
312
|
-
Authorization: `Bearer ${this.#
|
|
341
|
+
Authorization: `Bearer ${this.#t}`
|
|
313
342
|
}
|
|
314
|
-
}), { data: t } = await
|
|
315
|
-
t && (this.#
|
|
316
|
-
} catch (
|
|
317
|
-
this.#
|
|
343
|
+
}), { data: t } = await e.json();
|
|
344
|
+
t && (this.#e = t, this.#n = !0, this.emit("verified", !0));
|
|
345
|
+
} catch (e) {
|
|
346
|
+
this.#n = !1, this.emit("error", e.message || String(e));
|
|
318
347
|
}
|
|
319
|
-
return this.emit("verifying", !1), this.#
|
|
348
|
+
return this.emit("verifying", !1), this.#s = !1, this.#n;
|
|
320
349
|
}
|
|
321
|
-
async onGoogleIdentityCallback(
|
|
322
|
-
this.emit("init", !1), this.#
|
|
350
|
+
async onGoogleIdentityCallback(e) {
|
|
351
|
+
this.emit("init", !1), this.#i = !1, this.emit("verifying", !0), this.#s = !0;
|
|
323
352
|
const t = await fetch(`${this.#r}/google-auth`, {
|
|
324
353
|
method: "POST",
|
|
325
354
|
headers: {
|
|
326
355
|
"Content-type": "application/json"
|
|
327
356
|
},
|
|
328
357
|
body: JSON.stringify({
|
|
329
|
-
credential:
|
|
358
|
+
credential: e.credential
|
|
330
359
|
})
|
|
331
360
|
}), { data: a } = await t.json();
|
|
332
361
|
a || this.emit("error", "Failed to validate user.");
|
|
333
|
-
const { token:
|
|
334
|
-
this.setAccessToken(
|
|
362
|
+
const { token: f } = a;
|
|
363
|
+
this.setAccessToken(f), this.emit("verifying", !1), this.#s = !1, this.emit("verified", !0), this.#n = !0;
|
|
364
|
+
}
|
|
365
|
+
getRevokeHint() {
|
|
366
|
+
const e = this.#e.email;
|
|
367
|
+
if (typeof e == "string" && e.trim()) return e;
|
|
368
|
+
const t = this.#e.sub;
|
|
369
|
+
return typeof t == "string" && t.trim() ? t : "";
|
|
335
370
|
}
|
|
336
371
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
372
|
+
let w = null;
|
|
373
|
+
function x() {
|
|
374
|
+
return "google" in globalThis && "accounts" in globalThis.google;
|
|
375
|
+
}
|
|
376
|
+
function ie() {
|
|
377
|
+
return x() ? Promise.resolve() : w || (w = new Promise((r, e) => {
|
|
378
|
+
const t = "https://accounts.google.com/gsi/client", a = document.querySelector(`script[src="${t}"]`), f = a || document.createElement("script");
|
|
379
|
+
function p() {
|
|
380
|
+
r();
|
|
381
|
+
}
|
|
382
|
+
function b() {
|
|
383
|
+
e(new Error("Google Identity Services 加载失败"));
|
|
384
|
+
}
|
|
385
|
+
f.addEventListener("load", p, { once: !0 }), f.addEventListener("error", b, { once: !0 }), a || (f.src = t, f.async = !0, document.head.appendChild(f));
|
|
386
|
+
}), w.catch(() => {
|
|
387
|
+
w = null;
|
|
388
|
+
}), w);
|
|
343
389
|
}
|
|
344
|
-
let
|
|
345
|
-
function
|
|
346
|
-
return
|
|
390
|
+
let k;
|
|
391
|
+
function se(r) {
|
|
392
|
+
return k = k || new ne(r), k;
|
|
347
393
|
}
|
|
348
394
|
export {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
395
|
+
ne as AwesomeAuth,
|
|
396
|
+
re as AwesomeAuthEvent,
|
|
397
|
+
se as getInstance
|
|
352
398
|
};
|
package/dist/awesome-auth.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(v,S){typeof exports=="object"&&typeof module<"u"?S(exports):typeof define=="function"&&define.amd?define(["exports"],S):(v=typeof globalThis<"u"?globalThis:v||self,S(v.AwesomeAuth={}))})(this,(function(v){"use strict";function S(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var E={exports:{}},$;function R(){return $||($=1,(function(n){var e=Object.prototype.hasOwnProperty,t="~";function a(){}Object.create&&(a.prototype=Object.create(null),new a().__proto__||(t=!1));function h(c,i,s){this.fn=c,this.context=i,this.once=s||!1}function p(c,i,s,o,g){if(typeof s!="function")throw new TypeError("The listener must be a function");var d=new h(s,o||c,g),l=t?t+i:i;return c._events[l]?c._events[l].fn?c._events[l]=[c._events[l],d]:c._events[l].push(d):(c._events[l]=d,c._eventsCount++),c}function I(c,i){--c._eventsCount===0?c._events=new a:delete c._events[i]}function u(){this._events=new a,this._eventsCount=0}u.prototype.eventNames=function(){var i=[],s,o;if(this._eventsCount===0)return i;for(o in s=this._events)e.call(s,o)&&i.push(t?o.slice(1):o);return Object.getOwnPropertySymbols?i.concat(Object.getOwnPropertySymbols(s)):i},u.prototype.listeners=function(i){var s=t?t+i:i,o=this._events[s];if(!o)return[];if(o.fn)return[o.fn];for(var g=0,d=o.length,l=new Array(d);g<d;g++)l[g]=o[g].fn;return l},u.prototype.listenerCount=function(i){var s=t?t+i:i,o=this._events[s];return o?o.fn?1:o.length:0},u.prototype.emit=function(i,s,o,g,d,l){var y=t?t+i:i;if(!this._events[y])return!1;var r=this._events[y],m=arguments.length,b,f;if(r.fn){switch(r.once&&this.removeListener(i,r.fn,void 0,!0),m){case 1:return r.fn.call(r.context),!0;case 2:return r.fn.call(r.context,s),!0;case 3:return r.fn.call(r.context,s,o),!0;case 4:return r.fn.call(r.context,s,o,g),!0;case 5:return r.fn.call(r.context,s,o,g,d),!0;case 6:return r.fn.call(r.context,s,o,g,d,l),!0}for(f=1,b=new Array(m-1);f<m;f++)b[f-1]=arguments[f];r.fn.apply(r.context,b)}else{var oe=r.length,_;for(f=0;f<oe;f++)switch(r[f].once&&this.removeListener(i,r[f].fn,void 0,!0),m){case 1:r[f].fn.call(r[f].context);break;case 2:r[f].fn.call(r[f].context,s);break;case 3:r[f].fn.call(r[f].context,s,o);break;case 4:r[f].fn.call(r[f].context,s,o,g);break;default:if(!b)for(_=1,b=new Array(m-1);_<m;_++)b[_-1]=arguments[_];r[f].fn.apply(r[f].context,b)}}return!0},u.prototype.on=function(i,s,o){return p(this,i,s,o,!1)},u.prototype.once=function(i,s,o){return p(this,i,s,o,!0)},u.prototype.removeListener=function(i,s,o,g){var d=t?t+i:i;if(!this._events[d])return this;if(!s)return I(this,d),this;var l=this._events[d];if(l.fn)l.fn===s&&(!g||l.once)&&(!o||l.context===o)&&I(this,d);else{for(var y=0,r=[],m=l.length;y<m;y++)(l[y].fn!==s||g&&!l[y].once||o&&l[y].context!==o)&&r.push(l[y]);r.length?this._events[d]=r.length===1?r[0]:r:I(this,d)}return this},u.prototype.removeAllListeners=function(i){var s;return i?(s=t?t+i:i,this._events[s]&&I(this,s)):(this._events=new a,this._eventsCount=0),this},u.prototype.off=u.prototype.removeListener,u.prototype.addListener=u.prototype.on,u.prefixed=t,u.EventEmitter=u,n.exports=u})(E)),E.exports}var D=R();const N=S(D);class T extends Error{}T.prototype.name="InvalidTokenError";function z(n){return decodeURIComponent(atob(n).replace(/(.)/g,(e,t)=>{let a=t.charCodeAt(0).toString(16).toUpperCase();return a.length<2&&(a="0"+a),"%"+a}))}function B(n){let e=n.replace(/-/g,"+").replace(/_/g,"/");switch(e.length%4){case 0:break;case 2:e+="==";break;case 3:e+="=";break;default:throw new Error("base64 string is not of the correct length")}try{return z(e)}catch{return atob(e)}}function F(n,e){if(typeof n!="string")throw new T("Invalid token specified: must be a string");e||(e={});const t=e.header===!0?0:1,a=n.split(".")[t];if(typeof a!="string")throw new T(`Invalid token specified: missing part #${t+1}`);let h;try{h=B(a)}catch(p){throw new T(`Invalid token specified: invalid base64 for part #${t+1} (${p.message})`)}try{return JSON.parse(h)}catch(p){throw new T(`Invalid token specified: invalid json for part #${t+1} (${p.message})`)}}var M=typeof global=="object"&&global&&global.Object===Object&&global,V=typeof self=="object"&&self&&self.Object===Object&&self,J=M||V||Function("return this")(),j=J.Symbol,A=Object.prototype,U=A.hasOwnProperty,q=A.toString,O=j?j.toStringTag:void 0;function H(n){var e=U.call(n,O),t=n[O];try{n[O]=void 0;var a=!0}catch{}var h=q.call(n);return a&&(e?n[O]=t:delete n[O]),h}var K=Object.prototype,Y=K.toString;function Q(n){return Y.call(n)}var W="[object Null]",X="[object Undefined]",P=j?j.toStringTag:void 0;function Z(n){return n==null?n===void 0?X:W:P&&P in Object(n)?H(n):Q(n)}var ee=Array.isArray;function te(n){return n!=null&&typeof n=="object"}var ne="[object String]";function re(n){return typeof n=="string"||!ee(n)&&te(n)&&Z(n)==ne}var G=(n=>(n.INIT="init",n.VERIFYING="verifying",n.VERIFIED="verified",n.REFRESH="refresh",n.ERROR="error",n))(G||{});let k;class L extends N{#t="";#e={};#o=0;#c;#i=!1;#s=!1;#r=!1;#l=!1;#a;#f;#n;constructor({googleId:e,prefix:t="aAuth",root:a="/api"}){if(super(),this.#c=e,this.#f=t,this.#n=a,this.#a=Date.now()/1e3>>0,this.setAccessToken(localStorage.getItem(this.localKey)||"",!1),this.#t){this.verifyToken().then(h=>{h||this.initGoogleIdentity()});return}this.initGoogleIdentity()}get accessToken(){return this.#t}get expiredIn(){return this.#o?0:this.#o-this.#a}get isVerifying(){return this.#s}get isVerified(){return this.#r}get localKey(){return`${this.#f}-token`}get root(){return this.#n}get user(){return this.#e}doSignIn(){this.initGoogleIdentity()}doSignOut(){const e=this.getRevokeHint();this.setAccessToken(""),this.#e={},this.#r=!1,clearInterval(k),this.emit("verified",!1),e&&"google"in globalThis&&"accounts"in globalThis.google&&google.accounts.id.revoke(e)}async store(e,t){t=re(t)?t:JSON.stringify(t),await fetch(`${this.#n}/store`,{method:"POST",headers:{"Content-type":"application/json",Authorization:`Bearer ${this.#t}`},body:JSON.stringify({key:e,value:t})})}async retrieve(e){const t=await fetch(`${this.#n}/retrieve`,{method:"POST",headers:{"Content-type":"application/json",Authorization:`Bearer ${this.#t}`},body:JSON.stringify({key:e})}),{data:a}=await t.json();return a?.value}initGoogleIdentity(){this.#i||(this.emit("init",!0),this.#i=!0,this.ensureGoogleIdentityInitialized().then(()=>{google.accounts.id.prompt(e=>{this.handlePromptMoment(e)})}).catch(e=>{this.#i=!1,this.emit("init",!1),this.emit("error",e.message||String(e))}))}async renderButton(e,t){if(e){try{await this.ensureGoogleIdentityInitialized()}catch(a){this.emit("error",a.message||String(a));return}if(!x()){this.emit("error","Google Identity Services 未加载完成");return}google.accounts.id.renderButton(e,{type:"standard",theme:"outline",size:"large",text:"signin_with",...t})}}async ensureGoogleIdentityInitialized(){if(await ie(),!x())throw new Error("Google Identity Services 未加载完成");this.#l||(google.accounts.id.initialize({client_id:this.#c,callback:e=>this.onGoogleIdentityCallback(e),auto_select:!0,ux_mode:"popup"}),this.#l=!0)}handlePromptMoment(e){(e.isNotDisplayed()||e.isSkippedMoment()||e.isDismissedMoment())&&(this.#i=!1,this.emit("init",!1))}refreshCountDown(){this.#a=Date.now()/1e3>>0,this.expiredIn<=60&&(clearInterval(k),this.refreshToken())}async refreshToken(){this.emit("refresh",!0);const e=await fetch(`${this.#n}/refresh-token`,{method:"POST",headers:{"Content-type":"application/json",Authorization:`Bearer ${this.#t}`}}),{data:t}=await e.json(),{token:a}=t;this.setAccessToken(a),this.emit("refresh",!1)}setAccessToken(e,t=!0){if(this.#t=e,t&&localStorage.setItem(this.localKey,e),!e){this.#e={},this.#o=0;return}try{this.#e=F(e)}catch{this.#e={}}this.#o=this.#e.exp||0,this.expiredIn>0&&(clearInterval(k),k=setInterval(()=>this.refreshCountDown(),1e3))}async verifyToken(){this.emit("verifying",!0),this.#s=!0;try{const e=await fetch(`${this.#n}/verify-auth`,{method:"POST",headers:{"Content-type":"application/json",Authorization:`Bearer ${this.#t}`}}),{data:t}=await e.json();t&&(this.#e=t,this.#r=!0,this.emit("verified",!0))}catch(e){this.#r=!1,this.emit("error",e.message||String(e))}return this.emit("verifying",!1),this.#s=!1,this.#r}async onGoogleIdentityCallback(e){this.emit("init",!1),this.#i=!1,this.emit("verifying",!0),this.#s=!0;const t=await fetch(`${this.#n}/google-auth`,{method:"POST",headers:{"Content-type":"application/json"},body:JSON.stringify({credential:e.credential})}),{data:a}=await t.json();a||this.emit("error","Failed to validate user.");const{token:h}=a;this.setAccessToken(h),this.emit("verifying",!1),this.#s=!1,this.emit("verified",!0),this.#r=!0}getRevokeHint(){const e=this.#e.email;if(typeof e=="string"&&e.trim())return e;const t=this.#e.sub;return typeof t=="string"&&t.trim()?t:""}}let w=null;function x(){return"google"in globalThis&&"accounts"in globalThis.google}function ie(){return x()?Promise.resolve():w||(w=new Promise((n,e)=>{const t="https://accounts.google.com/gsi/client",a=document.querySelector(`script[src="${t}"]`),h=a||document.createElement("script");function p(){n()}function I(){e(new Error("Google Identity Services 加载失败"))}h.addEventListener("load",p,{once:!0}),h.addEventListener("error",I,{once:!0}),a||(h.src=t,h.async=!0,document.head.appendChild(h))}),w.catch(()=>{w=null}),w)}let C;function se(n){return C=C||new L(n),C}v.AwesomeAuth=L,v.AwesomeAuthEvent=G,v.getInstance=se,Object.defineProperty(v,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
CHANGED
package/tests/unit/auth.test.ts
CHANGED
|
@@ -27,6 +27,7 @@ describe('AwesomeAuth One Tap', () => {
|
|
|
27
27
|
let promptCallbacks: PromptCallback[];
|
|
28
28
|
let initialize: ReturnType<typeof vi.fn>;
|
|
29
29
|
let prompt: ReturnType<typeof vi.fn>;
|
|
30
|
+
let revoke: ReturnType<typeof vi.fn>;
|
|
30
31
|
|
|
31
32
|
beforeEach(() => {
|
|
32
33
|
promptCallbacks = [];
|
|
@@ -36,12 +37,14 @@ describe('AwesomeAuth One Tap', () => {
|
|
|
36
37
|
promptCallbacks.push(callback);
|
|
37
38
|
}
|
|
38
39
|
});
|
|
40
|
+
revoke = vi.fn();
|
|
39
41
|
|
|
40
42
|
const googleMock = {
|
|
41
43
|
accounts: {
|
|
42
44
|
id: {
|
|
43
45
|
initialize,
|
|
44
46
|
prompt,
|
|
47
|
+
revoke,
|
|
45
48
|
},
|
|
46
49
|
},
|
|
47
50
|
};
|
|
@@ -79,34 +82,73 @@ describe('AwesomeAuth One Tap', () => {
|
|
|
79
82
|
vi.clearAllMocks();
|
|
80
83
|
});
|
|
81
84
|
|
|
82
|
-
it('在提示被关闭后重置初始化状态,并允许再次唤起', () => {
|
|
85
|
+
it('在提示被关闭后重置初始化状态,并允许再次唤起', async () => {
|
|
83
86
|
const events: boolean[] = [];
|
|
84
87
|
const auth = new AwesomeAuth({ googleId: 'test-client' });
|
|
85
88
|
auth.on(AwesomeAuthEvent.INIT, (value: boolean) => {
|
|
86
89
|
events.push(value);
|
|
87
90
|
});
|
|
88
91
|
|
|
92
|
+
await flushPromises();
|
|
89
93
|
expect(promptCallbacks).toHaveLength(1);
|
|
90
94
|
promptCallbacks[0](createPromptNotification('dismissed'));
|
|
91
95
|
|
|
92
96
|
expect(events).toEqual([false]);
|
|
93
97
|
|
|
94
98
|
auth.doSignIn();
|
|
99
|
+
await flushPromises();
|
|
95
100
|
expect(promptCallbacks).toHaveLength(2);
|
|
96
101
|
expect(events[1]).toBe(true);
|
|
97
102
|
expect(initialize).toHaveBeenCalledTimes(1);
|
|
98
103
|
});
|
|
99
104
|
|
|
100
|
-
it('在提示未显示时结束初始化状态', () => {
|
|
105
|
+
it('在提示未显示时结束初始化状态', async () => {
|
|
101
106
|
const events: boolean[] = [];
|
|
102
107
|
const auth = new AwesomeAuth({ googleId: 'test-client' });
|
|
103
108
|
auth.on(AwesomeAuthEvent.INIT, (value: boolean) => {
|
|
104
109
|
events.push(value);
|
|
105
110
|
});
|
|
106
111
|
|
|
112
|
+
await flushPromises();
|
|
107
113
|
expect(promptCallbacks).toHaveLength(1);
|
|
108
114
|
promptCallbacks[0](createPromptNotification('not-displayed'));
|
|
109
115
|
|
|
110
116
|
expect(events).toEqual([false]);
|
|
111
117
|
});
|
|
118
|
+
|
|
119
|
+
it('未提供 hint 时不调用 revoke', () => {
|
|
120
|
+
const auth = new AwesomeAuth({ googleId: 'test-client' });
|
|
121
|
+
|
|
122
|
+
auth.doSignOut();
|
|
123
|
+
|
|
124
|
+
expect(revoke).not.toHaveBeenCalled();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('使用 email 作为 hint 调用 revoke', () => {
|
|
128
|
+
const token = createJwt({
|
|
129
|
+
email: 'test@example.com',
|
|
130
|
+
sub: 'sub-123',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const auth = new AwesomeAuth({ googleId: 'test-client' });
|
|
134
|
+
(auth as unknown as { setAccessToken: (value: string, local?: boolean) => void }).setAccessToken(token, false);
|
|
135
|
+
|
|
136
|
+
auth.doSignOut();
|
|
137
|
+
|
|
138
|
+
expect(revoke).toHaveBeenCalledWith('test@example.com');
|
|
139
|
+
});
|
|
112
140
|
});
|
|
141
|
+
|
|
142
|
+
function createJwt(payload: Record<string, unknown>): string {
|
|
143
|
+
const header = encodeBase64Url(JSON.stringify({ alg: 'none', typ: 'JWT' }));
|
|
144
|
+
const body = encodeBase64Url(JSON.stringify(payload));
|
|
145
|
+
return `${header}.${body}.`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function encodeBase64Url(value: string): string {
|
|
149
|
+
return Buffer.from(value, 'utf-8').toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function flushPromises(): Promise<void> {
|
|
153
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
154
|
+
}
|
package/tsconfig.app.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/auth.ts","./src/main.ts","./src/vite-env.d.ts","./src/app.vue"],"
|
|
1
|
+
{"root":["./src/auth.ts","./src/main.ts","./src/vite-env.d.ts","./src/app.vue"],"version":"5.9.3"}
|