From e7cff8384128076ea4fc9cd93500a14bb61cc37d Mon Sep 17 00:00:00 2001 From: Nik Graf Date: Tue, 5 Sep 2017 16:18:25 +0200 Subject: [PATCH] new login wip --- lib/plugins/login/login.js | 187 +++++++++++++------------------------ 1 file changed, 66 insertions(+), 121 deletions(-) diff --git a/lib/plugins/login/login.js b/lib/plugins/login/login.js index 300327a37..cffe69840 100644 --- a/lib/plugins/login/login.js +++ b/lib/plugins/login/login.js @@ -16,10 +16,8 @@ const setConfig = require('../../utils/config').set; const createApolloClient = require('../../utils/createApolloClient'); const config = { - AUTH0_CLIENT_ID: 'iiEYK0KB30gj94mjB8HP9lhhTgae0Rg3', - AUTH0_URL: 'https://serverlessinc.auth0.com', - AUTH0_CALLBACK_URL: 'https://serverless.com/auth', // TODO use a global config that is shared between platform and login + PLATFORM_FRONTEND_BASE_URL: 'https://platform.serverless.com/', GRAPHQL_ENDPOINT_URL: 'https://graphql.serverless.com/graphql', }; @@ -31,7 +29,6 @@ const getCliLoginById = id => query: gql` query getCliLoginById($id: String!) { getCliLoginById(id: $id) { - id token } } @@ -40,10 +37,6 @@ const getCliLoginById = id => }) .then(response => response.data); -function base64url(url) { - return url.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); -} - class Login { constructor(serverless, options) { this.serverless = serverless; @@ -64,127 +57,79 @@ class Login { login() { clearConsole(); this.serverless.cli.log('The Serverless login will open in your default browser...'); - // Generate the verifier, and the corresponding challenge - const verifier = base64url(crypto.randomBytes(32)); - const verifierChallenge = base64url(crypto.createHash('sha256').update(verifier).digest()); const configuration = configUtils.getConfig(); const frameworkId = configuration.frameworkId; - // eslint-disable-next-line prefer-template - const version = this.serverless.version; - const state = `id%3D${frameworkId}%26version%3D${version}%26platform%3D${process.platform}`; - // refresh token docs https://auth0.com/docs/tokens/preview/refresh-token#get-a-refresh-token - const scope = - 'openid%20nickname%20email%20name%20login_count%20created_at%20tracking_id%20offline_access'; // eslint-disable-line - const authorizeUrl = - `${config.AUTH0_URL}/authorize?response_type=code&scope=${scope}` + - `&client_id=${config.AUTH0_CLIENT_ID}&redirect_uri=${config.AUTH0_CALLBACK_URL}` + - `&code_challenge=${verifierChallenge}&code_challenge_method=S256&state=${state}`; - const cliLoginId = uuid.v4(); + + let secondsPassed = 0; // TODO cleanup interval setInterval(() => { - getCliLoginById(cliLoginId); + getCliLoginById(cliLoginId) + .then(({ token }) => { + const decoded = jwtDecode(token); + this.serverless.cli.log('You are now logged in'); + // because platform only support github + const id = decoded.tracking_id || decoded.sub; + const userConfig = { + userId: id, + frameworkId, + users: {}, + }; + // set user auth in global .serverlessrc file + userConfig.users[id] = { + userId: id, + name: decoded.name, + email: decoded.email, + // TODO identify if we need access_token and refresh_token as in the old sign in flow + auth: { + id_token: token, + }, + }; + + // update .serverlessrc + setConfig(userConfig); + + // identify user for better onboarding + userStats + .identify({ + id, + frameworkId, + email: decoded.email, + // unix timestamp + created_at: Math.round(+new Date(decoded.createdAt) / 1000), + trackingDisabled: configuration.trackingDisabled, + force: true, + }) + .then(() => { + userStats + .track('user_loggedIn', { + id, + email: decoded.email, + force: true, + }) + .then(() => { + // then exit process + process.exit(0); + }); + }); + }) + .catch(() => { + this.serverless.cli.consoleLog( + chalk.red('Incorrect token value supplied. Please run "serverless login" again') + ); + process.exit(0); + }); + secondsPassed += 1; + if (secondsPassed >= 20000) { + this.serverless.cli.log('Waiting for your authentication in the browser.'); + secondsPassed = 0; + } }, 1000); - setTimeout(() => { - this.serverless.cli.log('Opening browser...'); - }, 300); + this.serverless.cli.log('Opening browser...'); - setTimeout(() => { - // pop open default browser - openBrowser(authorizeUrl); - - // wait for token - const readlineInterface = readline.createInterface({ - input: process.stdin, - output: process.stdout, - }); - // o get an access token and a refresh token from that code you need to call the oauth/token endpoint. Here's more info - https://auth0.com/docs/protocols#3-getting-the-access-token - readlineInterface.question('Please enter the verification code here: ', code => { - const authorizationData = { - code, - code_verifier: verifier, - client_id: config.AUTH0_CLIENT_ID, - grant_type: 'authorization_code', - redirect_uri: config.AUTH0_CALLBACK_URL, - }; - // verify login - fetch(`${config.AUTH0_URL}/oauth/token`, { - method: 'POST', - body: JSON.stringify(authorizationData), - headers: { 'content-type': 'application/json' }, - }) - .then(response => response.json()) - .then(platformResponse => { - const decoded = jwtDecode(platformResponse.id_token); - this.serverless.cli.log('You are now logged in'); - // because platform only support github - const id = decoded.tracking_id || decoded.sub; - - /* For future use - segment.identify({ - userId: id, - traits: { - email: profile.email, - }, - }) */ - - const userConfig = { - userId: id, - frameworkId, - users: {}, - }; - // set user auth in global .serverlessrc file - userConfig.users[id] = { - userId: id, - name: decoded.name, - email: decoded.email, - auth: platformResponse, - }; - - // update .serverlessrc - setConfig(userConfig); - - const userID = new Buffer(id).toString('base64'); - const email = new Buffer(decoded.email).toString('base64'); - const name = new Buffer(decoded.name).toString('base64'); - const loginCount = decoded.login_count; - const createdAt = decoded.created_at; - const successUrl = `https://serverless.com/success?u=${userID}&e=${email}&n=${name}&c=${loginCount}&v=${version}&d=${createdAt}&id=${frameworkId}`; // eslint-disable-line - - openBrowser(successUrl); - // identify user for better onboarding - userStats - .identify({ - id, - frameworkId, - email: decoded.email, - // unix timestamp - created_at: Math.round(+new Date(createdAt) / 1000), - trackingDisabled: configuration.trackingDisabled, - force: true, - }) - .then(() => { - userStats - .track('user_loggedIn', { - id, - email: decoded.email, - force: true, - }) - .then(() => { - // then exit process - process.exit(0); - }); - }); - }) - .catch(() => { - this.serverless.cli.consoleLog( - chalk.red('Incorrect token value supplied. Please run "serverless login" again') - ); - process.exit(0); - }); - }); - }, 2000); + // pop open default browser + openBrowser('$PLATFORM_FRONTEND_BASE_URL/login?cli=true'); } }