Improve: Marketplace auth inside Rocket.Chat instead of inside the iframe. (#14258)
* Oauth inside Rocket.Chat instead of inside the iframe. This is more secure. Refactored the cloud page. Changed menu to cloud connect, add button for cloud console and many others * change cloud sync endpoint * add resend button * add i18n. If disconnected and click register again do sync * more error handling and fall back verbose for now. Handle disconnect / reconnect case better.pull/14229/head^2
parent
ae92a17aeb
commit
67d07a2783
@ -0,0 +1,22 @@ |
||||
import { Users } from '../../../models'; |
||||
import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; |
||||
|
||||
export function checkUserHasCloudLogin(userId) { |
||||
const { connectToCloud, workspaceRegistered } = retrieveRegistrationStatus(); |
||||
|
||||
if (!connectToCloud || !workspaceRegistered) { |
||||
return false; |
||||
} |
||||
|
||||
if (!userId) { |
||||
return false; |
||||
} |
||||
|
||||
const user = Users.findOneById(userId); |
||||
|
||||
if (user && user.services && user.services.cloud && user.services.cloud.accessToken) { |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
@ -0,0 +1,99 @@ |
||||
import { HTTP } from 'meteor/http'; |
||||
import { settings } from '../../../settings'; |
||||
import { Users } from '../../../models'; |
||||
|
||||
import { getRedirectUri } from './getRedirectUri'; |
||||
import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; |
||||
import { unregisterWorkspace } from './unregisterWorkspace'; |
||||
import { userLoggedOut } from './userLoggedOut'; |
||||
import { userScopes } from '../oauthScopes'; |
||||
|
||||
export function getUserCloudAccessToken(userId, forceNew = false, scope = '', save = true) { |
||||
const { connectToCloud, workspaceRegistered } = retrieveRegistrationStatus(); |
||||
|
||||
if (!connectToCloud || !workspaceRegistered) { |
||||
return ''; |
||||
} |
||||
|
||||
if (!userId) { |
||||
return ''; |
||||
} |
||||
|
||||
const user = Users.findOneById(userId); |
||||
|
||||
if (!user || !user.services || !user.services.cloud || !user.services.cloud.accessToken || !user.services.cloud.refreshToken) { |
||||
return ''; |
||||
} |
||||
|
||||
const { accessToken, refreshToken } = user.services.cloud; |
||||
|
||||
const client_id = settings.get('Cloud_Workspace_Client_Id'); |
||||
if (!client_id) { |
||||
return ''; |
||||
} |
||||
|
||||
const expires = user.services.cloud.expiresAt; |
||||
const now = new Date(); |
||||
|
||||
if (now < expires.value && !forceNew) { |
||||
return accessToken; |
||||
} |
||||
|
||||
const cloudUrl = settings.get('Cloud_Url'); |
||||
const client_secret = settings.get('Cloud_Workspace_Client_Secret'); |
||||
const redirectUri = getRedirectUri(); |
||||
|
||||
if (scope === '') { |
||||
scope = userScopes.join(' '); |
||||
} |
||||
|
||||
let authTokenResult; |
||||
try { |
||||
authTokenResult = HTTP.post(`${ cloudUrl }/api/oauth/token`, { |
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, |
||||
params: { |
||||
client_id, |
||||
client_secret, |
||||
refresh_token: refreshToken, |
||||
scope, |
||||
grant_type: 'refresh_token', |
||||
redirect_uri: redirectUri, |
||||
}, |
||||
}); |
||||
} catch (e) { |
||||
if (e.response && e.response.data && e.response.data.error) { |
||||
console.error(`Failed to get User AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`); |
||||
|
||||
if (e.response.data.error === 'oauth_invalid_client_credentials') { |
||||
console.error('Server has been unregistered from cloud'); |
||||
unregisterWorkspace(); |
||||
} |
||||
|
||||
if (e.response.data.error === 'unauthorized') { |
||||
userLoggedOut(userId); |
||||
} |
||||
} else { |
||||
console.error(e); |
||||
} |
||||
|
||||
return ''; |
||||
} |
||||
|
||||
if (save) { |
||||
const expiresAt = new Date(); |
||||
expiresAt.setSeconds(expiresAt.getSeconds() + authTokenResult.data.expires_in); |
||||
|
||||
Users.update(user._id, { |
||||
$set: { |
||||
services: { |
||||
cloud: { |
||||
accessToken: authTokenResult.data.access_token, |
||||
expiresAt, |
||||
}, |
||||
}, |
||||
}, |
||||
}); |
||||
} |
||||
|
||||
return authTokenResult.data.access_token; |
||||
} |
@ -0,0 +1,20 @@ |
||||
import { Users } from '../../../models'; |
||||
|
||||
export function userLoggedOut(userId) { |
||||
|
||||
if (!userId) { |
||||
return false; |
||||
} |
||||
|
||||
const user = Users.findOneById(userId); |
||||
|
||||
if (user && user.services && user.services.cloud) { |
||||
Users.update(user._id, { |
||||
$unset: { |
||||
'services.cloud': 1, |
||||
}, |
||||
}); |
||||
} |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,51 @@ |
||||
import { HTTP } from 'meteor/http'; |
||||
import { Users } from '../../../models'; |
||||
import { userLoggedOut } from './userLoggedOut'; |
||||
import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; |
||||
import { settings } from '../../../settings'; |
||||
|
||||
export function userLogout(userId) { |
||||
const { connectToCloud, workspaceRegistered } = retrieveRegistrationStatus(); |
||||
|
||||
if (!connectToCloud || !workspaceRegistered) { |
||||
return ''; |
||||
} |
||||
|
||||
if (!userId) { |
||||
return ''; |
||||
} |
||||
|
||||
const user = Users.findOneById(userId); |
||||
|
||||
if (user && user.services && user.services.cloud && user.services.cloud.refreshToken) { |
||||
try { |
||||
const client_id = settings.get('Cloud_Workspace_Client_Id'); |
||||
if (!client_id) { |
||||
return ''; |
||||
} |
||||
|
||||
const cloudUrl = settings.get('Cloud_Url'); |
||||
const client_secret = settings.get('Cloud_Workspace_Client_Secret'); |
||||
|
||||
const { refreshToken } = user.services.cloud; |
||||
|
||||
HTTP.post(`${ cloudUrl }/api/oauth/revoke`, { |
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, |
||||
params: { |
||||
client_id, |
||||
client_secret, |
||||
token: refreshToken, |
||||
token_type_hint: 'refresh_token', |
||||
}, |
||||
}); |
||||
} catch (e) { |
||||
if (e.response && e.response.data && e.response.data.error) { |
||||
console.error(`Failed to get Revoke refresh token to logout of Rocket.Chat Cloud. Error: ${ e.response.data.error }`); |
||||
} else { |
||||
console.error(e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return userLoggedOut(userId); |
||||
} |
Loading…
Reference in new issue