Skip to content

Commit 3a301ea

Browse files
authored
Merge pull request #318 from topcoder-platform/dice-integration
Dice integration
2 parents b281a90 + dfbe8a8 commit 3a301ea

File tree

6 files changed

+169
-15
lines changed

6 files changed

+169
-15
lines changed

web-assets/auth0/dev-tenant/database/login.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ function login(handleOrEmail, password, callback) {
5454
handle:user.result.content.handle,
5555
roles: user.result.content.roles,
5656
email_verified: user.result.content.emailActive,
57-
created_at: user.result.content.createdAt
57+
created_at: user.result.content.createdAt,
58+
mfa_enabled: user.result.content.mfaEnabled,
59+
mfa_verified: user.result.content.mfaVerified
5860
});
5961
});
6062
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
function (user, context, callback) {
2+
if (context.clientID === configuration.CLIENT_ACCOUNTS_LOGIN) {
3+
console.log("rule:DICE DID:enter");
4+
5+
if (context.redirect) {
6+
console.log("rule:DICE DID:exiting due to context being a redirect");
7+
return callback(null, user, context);
8+
}
9+
const _ = require('lodash');
10+
const isAuth0 = (_.get(user, "identities[0].provider") === 'auth0') ? true : false;
11+
const isSocial = _.get(user, "identities[0].isSocial");
12+
const mfaEnabled = _.get(user, "mfa_enabled", false);
13+
const mfaVerified = _.get(user, "mfa_verified", false);
14+
15+
if (!isAuth0 && !isSocial) {
16+
console.log("rule:DICE DID:exiting due to enterprise user");
17+
return callback(null, user, context);
18+
}
19+
if (mfaEnabled && mfaVerified) {
20+
if (context.protocol === "redirect-callback") {
21+
// User was redirected to the /continue endpoint
22+
console.log("rule:DICE DID:User was redirected to the /continue endpoint");
23+
if (context.request.query.diceVerificationStatus === 'false') {
24+
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);
25+
} else if (context.request.query.otp) {
26+
request.post({
27+
url: 'https://api.' + configuration.DOMAIN + '/v3/users/checkOtp',
28+
json: {
29+
"param": {
30+
"userId": user.userId,
31+
"otp": context.request.query.otp
32+
}
33+
}
34+
}, function (error, response, body) {
35+
if (error) return callback(error, user, context);
36+
if (response.statusCode !== 200) {
37+
return callback('Login Error: Whoops! Something went wrong.', user, context);
38+
}
39+
if (body.result.content.verified === true) {
40+
return callback(null, user, context);
41+
} else {
42+
return callback('Login Error: wrong OTP', user, context);
43+
}
44+
});
45+
} else {
46+
const jwt_decode = require('jwt-decode');
47+
request.post({
48+
url: 'https://tc-vcauth-uat.diceid.com/vc/connect/token',
49+
form: {
50+
code: context.request.query.code,
51+
grant_type: 'authorization_code',
52+
client_id: 'topcoder'
53+
}
54+
}, function (error, response, body) {
55+
if (error) return callback(error, user, context);
56+
if (response.statusCode !== 200) {
57+
return callback('Login Error: Whoops! Something went wrong.', user, context);
58+
}
59+
const result = JSON.parse(body);
60+
const decoded = jwt_decode(result.id_token);
61+
console.log("Decoded: ", decoded);
62+
if (decoded.Email !== user.email) {
63+
return callback('Login Error: Credetials do not match', user, context);
64+
}
65+
console.log("rule:DICE DID:credentials approved");
66+
return callback(null, user, context);
67+
});
68+
}
69+
} else {
70+
const maxRetry = 2;
71+
const useOtp = function () {
72+
request.post({
73+
url: 'https://api.' + configuration.DOMAIN + '/v3/users/sendOtp',
74+
json: {
75+
"param": {
76+
"userId": user.userId
77+
}
78+
}
79+
}, function (error, response, body) {
80+
if (error) return callback(error, user, context);
81+
if (response.statusCode !== 200) {
82+
return callback('Login Error: Whoops! Something went wrong.', user, context);
83+
}
84+
console.log("rule:DICE DID: redirecting to OTP page");
85+
context.redirect = {
86+
url: `https://accounts-auth0.${configuration.DOMAIN}/check_email.html`
87+
};
88+
return callback(null, user, context);
89+
});
90+
};
91+
const checkDiceHealth = function (attempt) {
92+
console.log("rule:DICE DID:checking dice health, attempt:" + attempt);
93+
request.get({
94+
url: 'https://tc-vcauth-uat.diceid.com/.well-known/openid-configuration'
95+
}, function (error, response, body) {
96+
if (error || response.statusCode !== 200) {
97+
if (attempt >= maxRetry) {
98+
console.log("rule:DICE DID:dice services down, using otp flow...");
99+
useOtp();
100+
} else {
101+
checkDiceHealth(attempt + 1);
102+
}
103+
} else {
104+
console.log("rule:DICE DID:exiting with redirecting user to QR code page.");
105+
context.redirect = {
106+
url: `https://tc-vcauth-uat.diceid.com/vc/connect/authorize?pres_req_conf_id=Topcoder_2FA&client_id=topcoder&redirect_uri=https%3A%2F%2Fauth.topcoder-dev.com%2Fcontinue&response_type=code&scope=openid%20profile%20vc_authn`
107+
};
108+
return callback(null, user, context);
109+
}
110+
});
111+
};
112+
if (!global.ENABLE_2FA) {
113+
console.log("rule:DICE DID:dice switch disabled, using otp flow...");
114+
useOtp();
115+
} else {
116+
checkDiceHealth(1);
117+
}
118+
}
119+
} else {
120+
console.log("rule:DICE DID:exiting due to mfa is not enabled");
121+
return callback(null, user, context);
122+
}
123+
} else {
124+
return callback(null, user, context);
125+
}
126+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
function (user, context, callback) {
2+
global.ENABLE_2FA = false;
3+
return callback(null, user, context);
4+
}

web-assets/auth0/dev-tenant/rules/custom.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ function (user, context, callback) {
1919
handle = _.get(user, "nickname", null);
2020
}
2121
console.log("Fetch roles for email/handle: ", user.email, handle, provider);
22+
2223
global.AUTH0_CLAIM_NAMESPACE = "https://" + configuration.DOMAIN + "/";
2324
try {
2425
request.post({
@@ -33,10 +34,12 @@ function (user, context, callback) {
3334
if (response.statusCode !== 200) {
3435
return callback('Login Error: Whoops! Something went wrong. Looks like your registered email has discrepancy with Authentication. Please connect to our support <a href="mailto:support@topcoder.com">support@topcoder.com</a>. Back to application ', user, context);
3536
}
36-
3737
let res = JSON.parse(body);
38+
user.mfa_enabled = res.result.content.mfaEnabled;
39+
user.mfa_verified = res.result.content.mfaVerified;
3840
// TODO need to double sure about multiple result or no result
3941
let userId = res.result.content.id;
42+
user.userId = userId;
4043
let handle = res.result.content.handle;
4144
let roles = res.result.content.roles.map(function (role) {
4245
return role.roleName;
@@ -45,12 +48,12 @@ function (user, context, callback) {
4548

4649
// TEMP
4750
let tcsso = res.result.content.regSource || '';
48-
51+
4952
// block wipro/topgear contractor user
50-
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 ';
51-
if (roles.indexOf(configuration.TOPGEAR_CONTRACTOR_ROLE) > -1) {
52-
return callback(topgearBlockMessage, user, context);
53-
}
53+
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 ';
54+
if (roles.indexOf(configuration.TOPGEAR_CONTRACTOR_ROLE) > -1) {
55+
return callback(topgearBlockMessage, user, context);
56+
}
5457

5558
context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'roles'] = roles;
5659
context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'userId'] = userId;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function (user, context, callback) {
2+
// TODO: implement your rule
3+
//user.sachin.userId = 1234;
4+
if (!global.init) {
5+
global.AUTH0_CLAIM_NAMESPACE = "https://topcoder-dev-test.com/claims/";
6+
//global.AUTH0_CLAIM_NAMESPACE = "identityData";
7+
8+
// Protocols that get custom claims
9+
global.CUSTOM_CLAIMS_PROTOCOLS = ['oauth2-refresh-token', 'oauth2-device-code', 'oidc-basic-profile', 'oauth2'];
10+
11+
// 2FA switch
12+
global.ENABLE_2FA = true;
13+
14+
global.init = true;
15+
}
16+
callback(null, user, context);
17+
}

web-assets/auth0/dev-tenant/rules/user-privacy-policy.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
function (user, context, callback) {
22
if (context.clientID === configuration.CLIENT_ACCOUNTS_LOGIN) { // client/application specific
33
console.log("rule:user-privacy-policy:enter");
4-
4+
// configuration.M2M_CLIENT_I vgXLK3lICyra8wQonokc7NCJr4UrHmk4
55
const _ = require('lodash');
66

77
const loginCount = _.get(context, "stats.loginsCount");
@@ -29,7 +29,7 @@ function (user, context, callback) {
2929
return callback(null, user, context);
3030
}
3131

32-
if (loginCount < 3) {
32+
if (loginCount < 10) {
3333
const getToken = function (tokenCB) {
3434
if (global.M2MToken) {
3535
console.log('rule:user-privacy-policy:a M2M token is present');
@@ -43,7 +43,7 @@ function (user, context, callback) {
4343
tokenCB(null, global.M2MToken);
4444
return;
4545
}
46-
}
46+
}
4747
console.log('rule:user-privacy-policy:fetching fresh m2m token');
4848
request.post({
4949
url: `https://auth0proxy.${configuration.DOMAIN}/token`,
@@ -100,8 +100,10 @@ function (user, context, callback) {
100100
callTermApi(token);
101101
}
102102
});
103-
} // if login count
104-
105-
} // if end
106-
return callback(null, user, context);
107-
}
103+
} else {
104+
return callback(null, user, context);
105+
}
106+
} else {
107+
return callback(null, user, context);
108+
}
109+
}

0 commit comments

Comments
 (0)