From 8a6d0e92973efe5a080f2fdc21adb2d2d7668aeb Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Tue, 21 Jun 2022 19:41:45 -0600 Subject: [PATCH 1/9] feat[2-google-auth]: Add signInWithGoogle --- src/index.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/index.ts b/src/index.ts index 8d54b78..dc60eac 100644 --- a/src/index.ts +++ b/src/index.ts @@ -190,6 +190,17 @@ class Auth extends EventEmitter { throw new Error(`Error logging in, verify email and password`); } } + + signInWithGoogle = async () => { + try { + const url = `${jsdbAxios.defaults.baseURL}/auth/oauth2/signin-with-google?url=${encodeURIComponent(window.location.href)}` + console.log('url: ', url) + window.location.assign(url) + } catch (e) { + throw new Error(`Error logging in, verify email and password`); + } + } + } export const auth = new Auth(); From 987581ac7d9300b93d5c18c1544083d879d82d15 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Tue, 21 Jun 2022 19:46:52 -0600 Subject: [PATCH 2/9] feat[2-google-auth]: Remove console.log --- src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index dc60eac..2d610ed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -194,7 +194,6 @@ class Auth extends EventEmitter { signInWithGoogle = async () => { try { const url = `${jsdbAxios.defaults.baseURL}/auth/oauth2/signin-with-google?url=${encodeURIComponent(window.location.href)}` - console.log('url: ', url) window.location.assign(url) } catch (e) { throw new Error(`Error logging in, verify email and password`); From a9eef487153617c4ece9c36cab9298ebdacf2745 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 25 Jun 2022 08:44:31 -0600 Subject: [PATCH 3/9] feat[2-google-auth]: Make signinWithGoogle awaitable promise with the token as resolved value, and close the window used to auth --- src/index.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2d610ed..7b60dc2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -192,14 +192,22 @@ class Auth extends EventEmitter { } signInWithGoogle = async () => { - try { + return new Promise((resolve, reject) => { + let timeout = setTimeout(() => { + reject({message:'signInWithGoogle timeout exceeded'}) + }, 2*60*1000) + let loginWindow: any; const url = `${jsdbAxios.defaults.baseURL}/auth/oauth2/signin-with-google?url=${encodeURIComponent(window.location.href)}` - window.location.assign(url) - } catch (e) { - throw new Error(`Error logging in, verify email and password`); - } + const uniqueWindowId = "authorizationGoogleJavascriptDatabase"; + window.addEventListener("message", function (e) { + const token = e.data; + clearTimeout(timeout); + loginWindow.close(); + resolve(token) + }, false); + loginWindow = window.open(url, uniqueWindowId) + }) } - } export const auth = new Auth(); From df93fa3d88fcca3dd466fbb24ee8167a8f39e6e9 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 25 Jun 2022 18:21:24 -0600 Subject: [PATCH 4/9] feat[2-google-auth]: Add token to axios header and emit tokenChanged --- src/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 7b60dc2..ae5e3a1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -199,11 +199,13 @@ class Auth extends EventEmitter { let loginWindow: any; const url = `${jsdbAxios.defaults.baseURL}/auth/oauth2/signin-with-google?url=${encodeURIComponent(window.location.href)}` const uniqueWindowId = "authorizationGoogleJavascriptDatabase"; - window.addEventListener("message", function (e) { + window.addEventListener("message", (e)=> { const token = e.data; clearTimeout(timeout); loginWindow.close(); - resolve(token) + jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + this.emit('tokenChanged', this.token); + resolve(); }, false); loginWindow = window.open(url, uniqueWindowId) }) From 870ca3f15b8262c860c504e2d63a2f756a8f0b77 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 25 Jun 2022 19:49:58 -0600 Subject: [PATCH 5/9] feat[2-google-auth]: extract signin with provider --- src/index.ts | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/index.ts b/src/index.ts index ae5e3a1..6734af1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -132,6 +132,24 @@ export function setApiKey(apiKey: string) { jsdbAxios.defaults.headers.common['X-API-Key'] = apiKey; } +async function singInWithProvider(providerName: string, callbackUrl: string): Promise { + return new Promise((resolve, reject) => { + let timeout = setTimeout(() => { + reject({message:`signInWith${providerName} timeout exceeded`}) + }, 2*60*1000) + let loginWindow: any; + const url = new URL(callbackUrl, jsdbAxios.defaults.baseURL); + url.searchParams.set('url', window.location.href) + const uniqueWindowId = `authorization${providerName}JavascriptDatabase`; + window.addEventListener("message", (e)=> { + const token = e.data; + clearTimeout(timeout); + loginWindow.close(); + resolve(token); + }, false); + loginWindow = window.open(url.toString(), uniqueWindowId) + }) +} class Auth extends EventEmitter { token: undefined | string; userId: undefined | string; @@ -192,23 +210,9 @@ class Auth extends EventEmitter { } signInWithGoogle = async () => { - return new Promise((resolve, reject) => { - let timeout = setTimeout(() => { - reject({message:'signInWithGoogle timeout exceeded'}) - }, 2*60*1000) - let loginWindow: any; - const url = `${jsdbAxios.defaults.baseURL}/auth/oauth2/signin-with-google?url=${encodeURIComponent(window.location.href)}` - const uniqueWindowId = "authorizationGoogleJavascriptDatabase"; - window.addEventListener("message", (e)=> { - const token = e.data; - clearTimeout(timeout); - loginWindow.close(); - jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; - this.emit('tokenChanged', this.token); - resolve(); - }, false); - loginWindow = window.open(url, uniqueWindowId) - }) + const token = await singInWithProvider('Google', 'auth/oauth2/signin-with-google') + jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + this.emit('tokenChanged', this.token); } } From 9c8efd26ce7f5aea4fa7dd54fc1afdcb5eace1ef Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 25 Jun 2022 22:13:26 -0600 Subject: [PATCH 6/9] feat[2-google-auth]: Add sign in with github --- src/index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/index.ts b/src/index.ts index 6734af1..b7a1ec1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -214,6 +214,11 @@ class Auth extends EventEmitter { jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; this.emit('tokenChanged', this.token); } + signInWithGithub = async () => { + const token = await singInWithProvider('Github', 'auth/oauth2/signin-with-github') + jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + this.emit('tokenChanged', this.token); + } } export const auth = new Auth(); From ba329c36c0c4950e57a6922a180d95a00c378f96 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 25 Jun 2022 22:42:35 -0600 Subject: [PATCH 7/9] feat[2-google-auth]: Pop un a little window --- src/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index b7a1ec1..78593cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -134,6 +134,8 @@ export function setApiKey(apiKey: string) { async function singInWithProvider(providerName: string, callbackUrl: string): Promise { return new Promise((resolve, reject) => { + const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; + let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` let timeout = setTimeout(() => { reject({message:`signInWith${providerName} timeout exceeded`}) }, 2*60*1000) @@ -147,7 +149,7 @@ async function singInWithProvider(providerName: string, callbackUrl: string): Pr loginWindow.close(); resolve(token); }, false); - loginWindow = window.open(url.toString(), uniqueWindowId) + loginWindow = window.open(url.toString(), uniqueWindowId, params) }) } class Auth extends EventEmitter { From 4f3ac8fb9b8d1970033b67bbdff3039acfde592c Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sun, 3 Jul 2022 11:42:09 -0600 Subject: [PATCH 8/9] feat[2-google-auth]: Add link with google and github --- src/index.ts | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/index.ts b/src/index.ts index 78593cd..add6d6a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -132,26 +132,37 @@ export function setApiKey(apiKey: string) { jsdbAxios.defaults.headers.common['X-API-Key'] = apiKey; } -async function singInWithProvider(providerName: string, callbackUrl: string): Promise { +async function singInWithProvider(providerName: string, callbackUrl: string): Promise<{ token: string, user: any}> { return new Promise((resolve, reject) => { const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` let timeout = setTimeout(() => { reject({message:`signInWith${providerName} timeout exceeded`}) - }, 2*60*1000) + }, 10*60*1000) let loginWindow: any; const url = new URL(callbackUrl, jsdbAxios.defaults.baseURL); url.searchParams.set('url', window.location.href) const uniqueWindowId = `authorization${providerName}JavascriptDatabase`; - window.addEventListener("message", (e)=> { - const token = e.data; + const handleMessage = (e: MessageEvent)=> { + const {token, user} = e.data; clearTimeout(timeout); loginWindow.close(); - resolve(token); - }, false); + window.removeEventListener('message', handleMessage) + resolve({token, user}); + } + window.addEventListener("message", handleMessage , false); loginWindow = window.open(url.toString(), uniqueWindowId, params) }) } +async function linkWithProvider(providerName: string, callbackUrl: string, that: any) { + if(!that.userId) throw 'User must be logged'; + const {token} = await singInWithProvider(providerName, callbackUrl) + const oldToken = that.token; + const newToken = token; + jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`; + that.emit('tokenChanged', that.token); + await jsdbAxios.post('/auth/link-providers', {oldToken, newToken}); +} class Auth extends EventEmitter { token: undefined | string; userId: undefined | string; @@ -212,15 +223,22 @@ class Auth extends EventEmitter { } signInWithGoogle = async () => { - const token = await singInWithProvider('Google', 'auth/oauth2/signin-with-google') + const {token, user} = await singInWithProvider('Google', 'auth/oauth2/signin-with-google') + this.userId = user.id; + this.token = token; jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; this.emit('tokenChanged', this.token); } signInWithGithub = async () => { - const token = await singInWithProvider('Github', 'auth/oauth2/signin-with-github') + const {token, user} = await singInWithProvider('Github', 'auth/oauth2/signin-with-github') + this.userId = user.id; + this.token = token; jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; this.emit('tokenChanged', this.token); } + + linkWithGoogle = async () => linkWithProvider('Google', 'auth/oauth2/signin-with-google', this) + linkWithGithub = async () => linkWithProvider('Github', 'auth/oauth2/signin-with-github', this) } export const auth = new Auth(); From c07fdb24e45cc138cf454b30e56f07aafd5a3195 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 6 Aug 2022 10:31:59 -0600 Subject: [PATCH 9/9] feat[2-google-auth]: Add new structure using custom passport on backend, revokeTokens and verifyEmail --- src/index.ts | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/index.ts b/src/index.ts index add6d6a..5ee8102 100644 --- a/src/index.ts +++ b/src/index.ts @@ -132,7 +132,11 @@ export function setApiKey(apiKey: string) { jsdbAxios.defaults.headers.common['X-API-Key'] = apiKey; } -async function singInWithProvider(providerName: string, callbackUrl: string): Promise<{ token: string, user: any}> { +async function singInWithProvider(providerName: string, callbackUrl: string): Promise<{ token: { + id: string, + userId: string, + createdAt: Date + }, user: any}> { return new Promise((resolve, reject) => { const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` @@ -158,7 +162,7 @@ async function linkWithProvider(providerName: string, callbackUrl: string, that: if(!that.userId) throw 'User must be logged'; const {token} = await singInWithProvider(providerName, callbackUrl) const oldToken = that.token; - const newToken = token; + const newToken = token.id; jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`; that.emit('tokenChanged', that.token); await jsdbAxios.post('/auth/link-providers', {oldToken, newToken}); @@ -191,9 +195,9 @@ class Auth extends EventEmitter { signIn = async (credentials: { email: string, password: string }) => { try { const {data: {token, userId}} = await jsdbAxios.post('/auth/signin', {...credentials}); - this.token = token; + this.token = token.id; this.userId = userId; - jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`; this.emit('tokenChanged', this.token); if (typeof process !== 'object') { localStorage.token = this.token; @@ -207,10 +211,10 @@ class Auth extends EventEmitter { createAccount = async (credentials: { email: string, password: string }) => { try { - const {data: {token, userId}} = await jsdbAxios.post('/auth/signup', {...credentials}); - this.token = token; - this.userId = userId; - jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + const {data: {token}} = await jsdbAxios.post('/auth/signup', {...credentials}); + this.token = token.id; + this.userId = token.userId; + jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`; this.emit('tokenChanged', this.token); if (typeof process !== 'object') { localStorage.token = this.token; @@ -225,20 +229,28 @@ class Auth extends EventEmitter { signInWithGoogle = async () => { const {token, user} = await singInWithProvider('Google', 'auth/oauth2/signin-with-google') this.userId = user.id; - this.token = token; - jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + this.token = token.id; + jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`; this.emit('tokenChanged', this.token); } signInWithGithub = async () => { const {token, user} = await singInWithProvider('Github', 'auth/oauth2/signin-with-github') this.userId = user.id; - this.token = token; - jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + this.token = token.id; + jsdbAxios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`; this.emit('tokenChanged', this.token); } linkWithGoogle = async () => linkWithProvider('Google', 'auth/oauth2/signin-with-google', this) linkWithGithub = async () => linkWithProvider('Github', 'auth/oauth2/signin-with-github', this) + revokeTokens = async(userId: string) => { + const {data: {revoked}} = await jsdbAxios.post('/auth/revoke-tokens', {userId}); + console.log(revoked) + } + verifyEmail = async(userId: string) => { + const resp = await jsdbAxios.post('/auth/verify-email', {userId}); + console.log(resp) + } } export const auth = new Auth();