Skip to content

Commit

Permalink
Merge branch 'master' into SNOW-728803-request-id-sqlText
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-ext-simba-lf authored Oct 6, 2023
2 parents 4a45148 + d01c4f4 commit 2fbd976
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 242 deletions.
87 changes: 17 additions & 70 deletions lib/authentication/auth_web.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,27 @@
*/

const util = require('../util');
const rest = require('../global_config').rest;

const net = require('net');
const querystring = require('querystring');
const URLUtil = require('./../../lib/url_util');
const Util = require('./../../lib/util');
const SsoUrlProvider = require('../authentication/sso_url_provider');

/**
* Creates an external browser authenticator.
*
* @param {String} host
* @param {Object} connectionConfig
* @param {Object} ssoUrlProvider
* @param {module} webbrowser
* @param {module} httpclient
* @param {module} browserActionTimeout
*
* @returns {Object}
* @constructor
*/
function auth_web(host, browserActionTimeout, webbrowser, httpclient, ) {
function auth_web(connectionConfig, httpClient, webbrowser) {

const host = connectionConfig.host;
const browserActionTimeout = connectionConfig.getBrowserActionTimeout();
const ssoUrlProvider = new SsoUrlProvider(httpClient);

if (!Util.exists(host)) {
throw new Error(`Invalid value for host: ${host}`);
Expand All @@ -31,14 +33,9 @@ function auth_web(host, browserActionTimeout, webbrowser, httpclient, ) {
}

const open = typeof webbrowser !== "undefined" ? webbrowser : require('open');
const axios = typeof httpclient !== "undefined" ? httpclient : require('axios');

const browserTimeout = browserActionTimeout
const port = rest.HTTPS_PORT;
const protocol = rest.HTTPS_PROTOCOL;
let proofKey;
let token;
let data;

const successResponse = 'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nYour identity was confirmed and propagated to Snowflake Node.js driver. You can close this window now and go back where you started from.';

Expand Down Expand Up @@ -79,13 +76,17 @@ function auth_web(host, browserActionTimeout, webbrowser, httpclient, ) {
server.listen(0, 0);

// Step 1: query Snowflake to obtain SSO url
const ssoURL = await getSSOURL(authenticator,
const ssoData = await ssoUrlProvider.getSSOURL(authenticator,
serviceName,
account,
server.address().port,
username);
username,
host);

proofKey = ssoData['proofKey'];

// Step 2: validate URL
let ssoURL = ssoData['ssoUrl'];
if (!URLUtil.isValidURL(ssoURL)) {
throw new Error(util.format("Invalid SSO URL found - %s ", ssoURL));
}
Expand All @@ -94,8 +95,8 @@ function auth_web(host, browserActionTimeout, webbrowser, httpclient, ) {
open(ssoURL);

// Step 4: get SAML token
data = await withBrowserActionTimeout(browserActionTimeout, receiveData)
processGet(data);
const tokenData = await withBrowserActionTimeout(browserActionTimeout, receiveData)
processGet(tokenData);
};

/**
Expand Down Expand Up @@ -139,60 +140,6 @@ function auth_web(host, browserActionTimeout, webbrowser, httpclient, ) {
return server;
};

/**
* Get SSO URL through POST request.
*
* @param {String} authenticator
* @param {String} serviceName
* @param {String} account
* @param {Number} callback_port
* @param {String} user
*
* @returns {String} the SSO URL.
*/
function getSSOURL(authenticator, serviceName, account, callback_port, user)
{
// Create URL to send POST request to
const url = protocol + '://' + host + "/session/authenticator-request";

let header;
if (serviceName)
{
header = {
'HTTP_HEADER_SERVICE_NAME': serviceName
}
}

// JSON body to send with POST request
const body = {
"data": {
"ACCOUNT_NAME": account,
"LOGIN_NAME": user,
"PORT": port,
"PROTOCOL": protocol,
"AUTHENTICATOR": authenticator,
"BROWSER_MODE_REDIRECT_PORT": callback_port.toString()
}
};

// Post request to get the SSO URL
return axios
.post(url, body, {
headers: header
})
.then((response) =>
{
var data = response['data']['data'];
proofKey = data['proofKey'];

return data['ssoUrl'];
})
.catch(requestErr =>
{
throw requestErr;
});
};

/**
* Parse the GET request and get token parameter value.
*
Expand Down Expand Up @@ -228,7 +175,7 @@ function auth_web(host, browserActionTimeout, webbrowser, httpclient, ) {
const withBrowserActionTimeout = (millis, promise) => {
const timeout = new Promise((resolve, reject) =>
setTimeout(
() => reject(`Browser action timed out after ${browserTimeout} ms.`),
() => reject(`Browser action timed out after ${browserActionTimeout} ms.`),
millis));
return Promise.race([
promise,
Expand Down
46 changes: 17 additions & 29 deletions lib/authentication/authentication.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
* Copyright (c) 2015-2021 Snowflake Computing Inc. All rights reserved.
*/

var auth_default = require('./auth_default');
var auth_web = require('./auth_web');
var auth_keypair = require('./auth_keypair');
var auth_oauth = require('./auth_oauth');
var auth_okta = require('./auth_okta');
const auth_default = require('./auth_default');
const auth_web = require('./auth_web');
const auth_keypair = require('./auth_keypair');
const auth_oauth = require('./auth_oauth');
const auth_okta = require('./auth_okta');

var authenticationTypes =
const authenticationTypes =
{
DEFAULT_AUTHENTICATOR: 'SNOWFLAKE', // default authenticator name
EXTERNAL_BROWSER_AUTHENTICATOR: 'EXTERNALBROWSER',
Expand Down Expand Up @@ -37,9 +37,8 @@ exports.formAuthJSON = function formAuthJSON(
clientType,
clientVersion,
clientEnv
)
{
var body =
) {
const body =
{
data:
{
Expand Down Expand Up @@ -67,39 +66,28 @@ exports.formAuthJSON = function formAuthJSON(
*
* @returns {Object} the authenticator.
*/
exports.getAuthenticator = function getAuthenticator(connectionConfig)
{
var auth = connectionConfig.getAuthenticator();
exports.getAuthenticator = function getAuthenticator(connectionConfig, httpClient) {
const auth = connectionConfig.getAuthenticator();

if (auth == authenticationTypes.DEFAULT_AUTHENTICATOR)
{
if (auth === authenticationTypes.DEFAULT_AUTHENTICATOR) {
return new auth_default(connectionConfig.password);
} else if (auth === authenticationTypes.EXTERNAL_BROWSER_AUTHENTICATOR) {
return new auth_web(connectionConfig, httpClient);
}
else if (auth == authenticationTypes.EXTERNAL_BROWSER_AUTHENTICATOR)
{
return new auth_web(connectionConfig.host, connectionConfig.getBrowserActionTimeout());
}
if (auth == authenticationTypes.KEY_PAIR_AUTHENTICATOR)
{
if (auth === authenticationTypes.KEY_PAIR_AUTHENTICATOR) {
return new auth_keypair(connectionConfig.getPrivateKey(),
connectionConfig.getPrivateKeyPath(),
connectionConfig.getPrivateKeyPass());
}
else if (auth == authenticationTypes.OAUTH_AUTHENTICATOR)
{
} else if (auth === authenticationTypes.OAUTH_AUTHENTICATOR) {
return new auth_oauth(connectionConfig.getToken());
}
else if (auth.startsWith('HTTPS://'))
{
} else if (auth.startsWith('HTTPS://')) {
return new auth_okta(connectionConfig.password,
connectionConfig.region,
connectionConfig.account,
connectionConfig.getClientType(),
connectionConfig.getClientVersion()
);
}
else
{
} else {
// Authenticator specified does not exist
return new auth_default(connectionConfig.password);
}
Expand Down
76 changes: 76 additions & 0 deletions lib/authentication/sso_url_provider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (c) 2015-2023 Snowflake Computing Inc. All rights reserved.
*/

const Util = require('../util');
const Errors = require('../errors');
const { rest } = require('../global_config');

/**
* Creates a new instance of an SsoUrlProvider.
*
* @param {Object} httpClient
* @constructor
*/
function SsoUrlProvider(httpClient) {

Errors.assertInternal(Util.isObject(httpClient));

const port = rest.HTTPS_PORT;
const protocol = rest.HTTPS_PROTOCOL;

/**
* Get SSO URL through POST request.
*
* @param {String} authenticator
* @param {String} serviceName
* @param {String} account
* @param {Number} callbackPort
* @param {String} user
* @param {String} host
*
* @returns {String} the SSO URL.
*/
this.getSSOURL = function (authenticator, serviceName, account, callbackPort, user, host) {
// Create URL to send POST request to
const url = protocol + '://' + host + '/session/authenticator-request';

let header;
if (serviceName) {
header = {
'HTTP_HEADER_SERVICE_NAME': serviceName
};
}
const body = {
'data': {
'ACCOUNT_NAME': account,
'LOGIN_NAME': user,
'PORT': port,
'PROTOCOL': protocol,
'AUTHENTICATOR': authenticator,
'BROWSER_MODE_REDIRECT_PORT': callbackPort.toString()
}
};

const requestOptions =
{
method: 'post',
url: url,
headers: header,
data: body,
responseType: 'json'
};

// Post request to get the SSO URL
return httpClient.requestAsync(requestOptions)
.then((response) => {
const data = response['data']['data'];
return data;
})
.catch(requestErr => {
throw requestErr;
});
};
}

module.exports = SsoUrlProvider;
4 changes: 2 additions & 2 deletions lib/connection/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ function Connection(context)
}

// Get authenticator to use
var auth = Authenticator.getAuthenticator(connectionConfig);
const auth = Authenticator.getAuthenticator(connectionConfig, context.getHttpClient());

try
{
Expand Down Expand Up @@ -297,7 +297,7 @@ function Connection(context)
var self = this;

// Get authenticator to use
var auth = Authenticator.getAuthenticator(connectionConfig);
const auth = Authenticator.getAuthenticator(connectionConfig, context.getHttpClient());

try
{
Expand Down
9 changes: 9 additions & 0 deletions lib/connection/connection_context.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ function ConnectionContext(connectionConfig, httpClient, config)
}
};
};
/**
* Returns instance of httpClient
*
* @returns {NodeHttpClient}
*/
this.getHttpClient = function ()
{
return httpClient;
};
}

module.exports = ConnectionContext;
Loading

0 comments on commit 2fbd976

Please sign in to comment.