[IMPROVE] Support for Google OAuth for mobile app (#22014)
parent
99e7da6601
commit
3db591804c
@ -0,0 +1,92 @@ |
|||||||
|
import { Meteor } from 'meteor/meteor'; |
||||||
|
import { OAuth } from 'meteor/oauth'; |
||||||
|
|
||||||
|
// The code on this file was copied directly from Meteor and modified to support mobile google oauth
|
||||||
|
// https://github.com/meteor/meteor/blob/ffcfa5062cf1bf8a64ea64fef681ffcd99fe7939/packages/oauth/oauth_server.js
|
||||||
|
|
||||||
|
Meteor.startup(() => { |
||||||
|
const appRedirectUrl = 'rocketchat://auth'; |
||||||
|
|
||||||
|
const renderEndOfLoginResponse = (options) => { |
||||||
|
const escape = (s) => { |
||||||
|
if (!s) { |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\'/g, '"').replace(/\'/g, ''').replace(/\//g, '/'); |
||||||
|
}; |
||||||
|
|
||||||
|
const config = { |
||||||
|
setCredentialToken: !! options.setCredentialToken, |
||||||
|
credentialToken: escape(options.credentialToken), |
||||||
|
credentialSecret: escape(options.credentialSecret), |
||||||
|
storagePrefix: escape(OAuth._storageTokenPrefix), |
||||||
|
redirectUrl: escape(options.redirectUrl), |
||||||
|
isCordova: !! options.isCordova, |
||||||
|
}; |
||||||
|
|
||||||
|
let template; |
||||||
|
if (options.loginStyle === 'popup') { |
||||||
|
template = OAuth._endOfPopupResponseTemplate; |
||||||
|
} else if (options.loginStyle === 'redirect') { |
||||||
|
template = OAuth._endOfRedirectResponseTemplate; |
||||||
|
} else { |
||||||
|
throw new Error(`invalid loginStyle: ${ options.loginStyle }`); |
||||||
|
} |
||||||
|
|
||||||
|
const result = template.replace(/##CONFIG##/, JSON.stringify(config)).replace(/##ROOT_URL_PATH_PREFIX##/, __meteor_runtime_config__.ROOT_URL_PATH_PREFIX); |
||||||
|
|
||||||
|
return `<!DOCTYPE html>\n${ result }`; |
||||||
|
}; |
||||||
|
|
||||||
|
OAuth._endOfLoginResponse = (res, details) => { |
||||||
|
res.writeHead(200, { 'Content-Type': 'text/html' }); |
||||||
|
let redirectUrl; |
||||||
|
|
||||||
|
if (details.loginStyle === 'redirect') { |
||||||
|
redirectUrl = OAuth._stateFromQuery(details.query).redirectUrl; |
||||||
|
const appHost = Meteor.absoluteUrl(); |
||||||
|
|
||||||
|
if (redirectUrl.startsWith(appRedirectUrl)) { |
||||||
|
redirectUrl = `${ appRedirectUrl }?host=${ appHost }&type=oauth`; |
||||||
|
|
||||||
|
if (details.error) { |
||||||
|
const error = encodeURIComponent(details.error.toString()); |
||||||
|
redirectUrl = `${ redirectUrl }&error=${ error }`; |
||||||
|
} |
||||||
|
|
||||||
|
if (details.credentials) { |
||||||
|
const { token, secret } = details.credentials; |
||||||
|
redirectUrl = `${ redirectUrl }&credentialToken=${ token }&credentialSecret=${ secret }`; |
||||||
|
} |
||||||
|
} else if (!Meteor.settings?.packages?.oauth?.disableCheckRedirectUrlOrigin && OAuth._checkRedirectUrlOrigin(redirectUrl)) { |
||||||
|
details.error = `redirectUrl (${ redirectUrl }) is not on the same host as the app (${ appHost })`; |
||||||
|
redirectUrl = appHost; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const isCordova = OAuth._isCordovaFromQuery(details.query); |
||||||
|
|
||||||
|
if (details.error) { |
||||||
|
res.end(renderEndOfLoginResponse({ |
||||||
|
loginStyle: details.loginStyle, |
||||||
|
setCredentialToken: false, |
||||||
|
redirectUrl, |
||||||
|
isCordova, |
||||||
|
}), 'utf-8'); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// If we have a credentialSecret, report it back to the parent
|
||||||
|
// window, with the corresponding credentialToken. The parent window
|
||||||
|
// uses the credentialToken and credentialSecret to log in over DDP.
|
||||||
|
res.end(renderEndOfLoginResponse({ |
||||||
|
loginStyle: details.loginStyle, |
||||||
|
setCredentialToken: true, |
||||||
|
credentialToken: details.credentials.token, |
||||||
|
credentialSecret: details.credentials.secret, |
||||||
|
redirectUrl, |
||||||
|
isCordova, |
||||||
|
}), 'utf-8'); |
||||||
|
}; |
||||||
|
}); |
Loading…
Reference in new issue