Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ perl -pi -e "s/\{\{AUTH0DOMAIN\}\}/$AUTH0DOMAIN/g" $SIGNUPFILENAME
CHECKEMAIL="./web-assets/static-pages/check_email.html"
perl -pi -e "s/\{\{DOMAIN\}\}/$DOMAIN/g" $CHECKEMAIL

OTPFILENAME="./web-assets/js/otp.js"
perl -pi -e "s/\{\{DOMAIN\}\}/$DOMAIN/g" $OTPFILENAME
perl -pi -e "s/\{\{AUTH0DOMAIN\}\}/$AUTH0DOMAIN/g" $OTPFILENAME

mkdir dist
cp -rv ./web-assets/css/* ./dist/
cp -rv ./web-assets/js/* ./dist/
Expand Down
10 changes: 8 additions & 2 deletions web-assets/auth0/dev-tenant/rules/DICE DID.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function (user, context, callback) {
// User was redirected to the /continue endpoint
console.log("rule:DICE DID:User was redirected to the /continue endpoint");
if (context.request.query.diceVerificationStatus === 'false') {
return callback('Login Error: Whoops! Something went wrong. Please connect to DICE Platform Admin <a href="mailto:info@diceid.com">dice.wallet@wipro.com</a>.<br> Back to application ', user, context);
return callback('Login Error: Credentials verification is failed.<br>Please contact with support <a href="mailto:support@topcoder.com">support@topcoder.com</a>.<br> Back to application ', user, context);
} else if (context.request.query.otp) {
request.post({
url: 'https://api.' + configuration.DOMAIN + '/v3/users/checkOtp',
Expand Down Expand Up @@ -82,8 +82,14 @@ function (user, context, callback) {
return callback('Login Error: Whoops! Something went wrong.', user, context);
}
console.log("rule:DICE DID: redirecting to OTP page");
const hostName = _.get(context, "request.hostname", null);
const otpCompletetUrl = "https://" + hostName + "/continue";
const retUrl = _.get(context, "request.query.returnUrl", null);
const otpRedirectUrl = configuration.CUSTOM_PAGES_BASE_URL +
"/otp.html?formAction=" + otpCompletetUrl +
"&returnUrl=" + retUrl;
context.redirect = {
url: `https://accounts-auth0.${configuration.DOMAIN}/check_email.html`
url: otpRedirectUrl
};
return callback(null, user, context);
});
Expand Down
13 changes: 8 additions & 5 deletions web-assets/auth0/prod-tenant/database/login.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function login(handleOrEmail, password, callback) {
request.post({
url: "https://api."+configuration.DOMAIN+"/v3/users/login",
request.post({
url: "https://api." + configuration.DOMAIN + "/v3/users/login",
form: {
handleOrEmail: handleOrEmail,
password: password
Expand All @@ -12,16 +12,19 @@ request.post({
if (err) return callback(err);
if (response.statusCode === 401) return callback();
var user = JSON.parse(body);
user.result.content.roles = user.result.content.roles.map(function(role) {
user.result.content.roles = user.result.content.roles.map(function (role) {
return role.roleName;
});

callback(null, {
callback(null, {
user_id: user.result.content.id,
nickname: user.result.content.handle,
email: user.result.content.email,
roles: user.result.content.roles,
email_verified: user.result.content.emailActive,
created_at: user.result.content.createdAt,
mfa_enabled: user.result.content.mfaEnabled,
mfa_verified: user.result.content.mfaVerified
});
});
}
}
130 changes: 130 additions & 0 deletions web-assets/auth0/prod-tenant/rules/DICE DID.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
function (user, context, callback) {
if (context.clientID === configuration.CLIENT_ACCOUNTS_LOGIN) {
console.log("rule:DICE DID:enter");
if (context.redirect) {
console.log("rule:DICE DID:exiting due to context being a redirect");
return callback(null, user, context);
}
const _ = require('lodash');
const isAuth0 = (_.get(user, "identities[0].provider") === 'auth0') ? true : false;
const isSocial = _.get(user, "identities[0].isSocial");
const mfaEnabled = _.get(user, "mfa_enabled", false);
const mfaVerified = _.get(user, "mfa_verified", false);
if (!isAuth0 && !isSocial) {
console.log("rule:DICE DID:exiting due to enterprise user");
return callback(null, user, context);
}
if (mfaEnabled && mfaVerified) {
if (context.protocol === "redirect-callback") {
// User was redirected to the /continue endpoint
console.log("rule:DICE DID:User was redirected to the /continue endpoint");
if (context.request.query.diceVerificationStatus === 'false') {
return callback('Login Error: Credentials verification is failed.<br>Please contact with support <a href="mailto:support@topcoder.com">support@topcoder.com</a>.<br> Back to application ', user, context);
} else if (context.request.query.otp) {
request.post({
url: 'https://api.' + configuration.DOMAIN + '/v3/users/checkOtp',
json: {
"param": {
"userId": user.userId,
"otp": context.request.query.otp
}
}
}, function (error, response, body) {
if (error) return callback(error, user, context);
if (response.statusCode !== 200) {
return callback('Login Error: Whoops! Something went wrong.', user, context);
}
if (body.result.content.verified === true) {
return callback(null, user, context);
} else {
return callback('Login Error: wrong OTP', user, context);
}
});
} else {
const jwt_decode = require('jwt-decode');
request.post({
url: 'https://tc-vcauth.diceid.com/vc/connect/token',
form: {
code: context.request.query.code,
grant_type: 'authorization_code',
client_id: 'topcoder'
}
}, function (error, response, body) {
if (error) return callback(error, user, context);
if (response.statusCode !== 200) {
return callback('Login Error: Whoops! Something went wrong.', user, context);
}
const result = JSON.parse(body);
const decoded = jwt_decode(result.id_token);
console.log("Decoded: ", decoded);
if (decoded.Email !== user.email) {
return callback('Login Error: Credetials do not match', user, context);
}
console.log("rule:DICE DID:credentials approved");
return callback(null, user, context);
});
}
} else {
const maxRetry = 2;
const useOtp = function () {
request.post({
url: 'https://api.' + configuration.DOMAIN + '/v3/users/sendOtp',
json: {
"param": {
"userId": user.userId
}
}
}, function (error, response, body) {
if (error) return callback(error, user, context);
if (response.statusCode !== 200) {
return callback('Login Error: Whoops! Something went wrong.', user, context);
}
console.log("rule:DICE DID: redirecting to OTP page");
const hostName = _.get(context, "request.hostname", null);
const otpCompletetUrl = "https://" + hostName + "/continue";
const retUrl = _.get(context, "request.query.returnUrl", null);
const otpRedirectUrl = configuration.CUSTOM_PAGES_BASE_URL +
"/otp.html?formAction=" + otpCompletetUrl +
"&returnUrl=" + retUrl;
context.redirect = {
url: otpRedirectUrl
};
return callback(null, user, context);
});
};
const checkDiceHealth = function (attempt) {
console.log("rule:DICE DID:checking dice health, attempt:" + attempt);
request.get({
url: 'https://tc-vcauth.diceid.com/.well-known/openid-configuration'
}, function (error, response, body) {
if (error || response.statusCode !== 200) {
if (attempt >= maxRetry) {
console.log("rule:DICE DID:dice services down, using otp flow...");
useOtp();
} else {
checkDiceHealth(attempt + 1);
}
} else {
console.log("rule:DICE DID:exiting with redirecting user to QR code page.");
context.redirect = {
url: `https://tc-vcauth.diceid.com/vc/connect/authorize?pres_req_conf_id=Topcoder_2FA&client_id=topcoder&redirect_uri=https%3A%2F%2Fauth.topcoder.com%2Fcontinue&response_type=code&scope=openid%20profile%20vc_authn`
};
return callback(null, user, context);
}
});
};
if (!global.ENABLE_2FA) {
console.log("rule:DICE DID:dice switch disabled, using otp flow...");
useOtp();
} else {
checkDiceHealth(1);
}
}
} else {
console.log("rule:DICE DID:exiting due to mfa is not enabled");
return callback(null, user, context);
}
} else {
return callback(null, user, context);
}
}
5 changes: 5 additions & 0 deletions web-assets/auth0/prod-tenant/rules/DisableDID.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function (user, context, callback) {
// Set the Enable_2FA to false globally - safety switch to turn off
global.ENABLE_2FA = false;
return callback(null, user, context);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function (user, context, callback) {
if (!global.init) {
global.AUTH0_CLAIM_NAMESPACE = "https://topcoder.com/";
global.CUSTOM_CLAIMS_PROTOCOLS = ['oauth2-refresh-token', 'oauth2-device-code', 'oidc-basic-profile'];
global.ENABLE_2FA = true;
global.init = true;
}
callback(null, user, context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ function (user, context, callback) {
}

let res = JSON.parse(body);
// Assign MFA flags to user objects - PLAT-1420
user.mfa_enabled = res.result.content.mfaEnabled;
user.mfa_verified = res.result.content.mfaVerified;
// TODO need to double sure about multiple result or no result
let userId = res.result.content.id;
user.userId = userId;
let handle = res.result.content.handle;
let roles = res.result.content.roles.map(function (role) {
return role.roleName;
Expand All @@ -42,11 +46,11 @@ function (user, context, callback) {
// TEMP
let tcsso = res.result.content.regSource || '';

// block wipro/topgear contractor user
const topgearBlockMessage = 'Topgear can be accessed only by Wipro Employees. If you are a Wipro employee and not able to access, drop an email to <a href="mailto:ask.topgear@wipro.com"> ask.topgear@wipro.com </a> with the error message.Back to application ';
if (roles.indexOf(configuration.TOPGEAR_CONTRACTOR_ROLE) > -1) {
return callback(topgearBlockMessage, user, context);
}
// block wipro/topgear contractor user
const topgearBlockMessage = 'Topgear can be accessed only by Wipro Employees. If you are a Wipro employee and not able to access, drop an email to <a href="mailto:ask.topgear@wipro.com"> ask.topgear@wipro.com </a> with the error message.Back to application ';
if (roles.indexOf(configuration.TOPGEAR_CONTRACTOR_ROLE) > -1) {
return callback(topgearBlockMessage, user, context);
}

context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'roles'] = roles;
context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'userId'] = userId;
Expand All @@ -55,14 +59,14 @@ function (user, context, callback) {
context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'tcsso'] = tcsso;
context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'active'] = userStatus;
context.idToken.nickname = handle;
if (!userStatus) {
context.redirect = {
url: `https://accounts-auth0.${configuration.DOMAIN}/check_email.html`
};
return callback(null, user, context);

if (!userStatus) {
context.redirect = {
url: `https://accounts-auth0.${configuration.DOMAIN}/check_email.html`
};
return callback(null, user, context);
}

//console.log(user, context);
return callback(null, user, context);
}
Expand Down
92 changes: 92 additions & 0 deletions web-assets/js/otp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
var qs = (function (a) {
if (a == "") return {};
var b = {};
for (var i = 0; i < a.length; ++i) {
var p = a[i].split("=", 2);
if (p.length == 1) b[p[0]] = "";
else b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
}
return b;
})(window.location.search.substr(1).split("&"));
$(document).ready(function () {
window.history.forward();
$("#continueBtn").click(function () {
var otp = $("#otp").val();
if (!otp) {
$("#error").html("Need Password");
$("#error").closest(".message").fadeIn();
return false;
}
$("#error").closest(".message").fadeOut();
$("#error").html("");
let formAction = qs["formAction"];
console.log(formAction)
const opt1 = 'https://auth.{{DOMAIN}}/continue';
const opt2 = 'https://{{AUTH0DOMAIN}}/continue';
if (!formAction.startsWith(opt1) && !formAction.startsWith(opt2)) {
// looks like XSS attack
console.log("err")
formAction = "#";
}
$('#verifyOtp').attr('action', formAction);
$("#state").val(qs["state"]);
$("#returnUrl").val(qs["returnUrl"]);
$("#verifyOtp").submit();
return false;
});

/**
* Script for field placeholder
**/
$(".messages .close-error").on("click", function () {
$(this).closest(".message").fadeOut();
});
var inputObj = $(".input-field .input-text"),
continueBtnDisable = false;
inputObj
.on("focus", function () {
$(this).parent().addClass("active focussed");
})
.on("blur", function () {
var parentObj = $(this).parent();
if ($(this).val() === "") {
parentObj.removeClass("active");
}
parentObj.removeClass("focussed");
})
.on("change keydown paste input", function () {
var disableStatus = false;
inputObj.each(function (index, element) {
if ($(element).val() === "") {
disableStatus = true;
return;
} else {
disableStatus = false;
return;
}
});
setContinueButtonDisabledStatus(disableStatus);
})
.each(function (index, element) {
var parentObj = $(element).parent();
if ($(element).val() !== "") {
parentObj.addClass("active");
} else {
parentObj.removeClass("active");
}

if ($(element).val() === "" && continueBtnDisable === false) {
continueBtnDisable = true;
}

setContinueButtonDisabledStatus(continueBtnDisable);
});
});
function setContinueButtonDisabledStatus(status) {
var continueBtnObj = $("#continueBtn");
if (status) {
continueBtnObj.attr("disabled", true);
} else {
continueBtnObj.removeAttr("disabled");
}
}
Loading