FSN#41669 Basic Auth en FSN#41668 aanzet

svn path=/Website/trunk/; revision=35003
This commit is contained in:
Jos Groot Lipman
2017-08-17 21:03:42 +00:00
parent 774d14879b
commit 5fcdd475e6
8 changed files with 344 additions and 297 deletions

View File

@@ -18,47 +18,22 @@ var DEZE = this;
api2_rest = {
authenticate: function _authenticate()
{
var APIKEY;
if (S("fac_api_key_in_url"))
APIKEY = getQParam("APIKEY", "");
if (!APIKEY && Request.ServerVariables("HTTP_X_FACILITOR_API_KEY").Count)
APIKEY = String(Request.ServerVariables("HTTP_X_FACILITOR_API_KEY")); // Meegegeven als X-FACILITOR-API-Key
if (!APIKEY && Session("user_key") > 0)
var method = String(Request.ServerVariables("REQUEST_METHOD"));
if (method != "GET" && Session("stateless") != 1) // Vereis dan wel het CSRF token
{
user_key = Session("user_key"); // Hierdoor is de API intern te gebruiken zonder authenticatie
var method = String(Request.ServerVariables("REQUEST_METHOD"));
if (method != "GET") // Vereis dan wel het CSRF token
{
var token = Request.ServerVariables("HTTP_X_CSRF_TOKEN").Count // Meegegeven als X-CSRF-TOKEN
? String(Request.ServerVariables("HTTP_X_CSRF_TOKEN"))
: "";
protectRequest.validateToken(token);
}
var token = Request.ServerVariables("HTTP_X_CSRF_TOKEN").Count // Meegegeven als X-CSRF-TOKEN
? String(Request.ServerVariables("HTTP_X_CSRF_TOKEN"))
: "";
protectRequest.validateToken(token);
}
else
if (user_key < 0)
{
if (Session("user_key") > 0)
{} // Tijdens ontwikkeling heb je soms in tweede tab de GUI open. Laat dat ongemoeid.
else
Session.Abandon(); // Altijd, voor de zekerheid
var sql = "SELECT prs_perslid_key, prs_perslid_naam, prs_perslid_oslogin"
+ " FROM prs_perslid"
+ " WHERE prs_perslid_verwijder IS NULL"
+ " AND prs_perslid_apikey = " + safe.quoted_sql(APIKEY);
var oRs = Oracle.Execute(sql);
if (oRs.Eof || !APIKEY)
{
Response.Status = "401 Unauthorized";
// Sommige applicaties kunnen in reactie hierop een b64 encoded username:password sturen
// Die onderscheppen wij in LoginTry.asp uiteindelijk
if (S("basic_auth_realm"))
Response.AddHeader("WWW-Authenticate", "Basic realm=\"" + S("basic_auth_realm") + "\"");
Response.End;
};
__Log("API2 User is: {0} ({1})".format(oRs("prs_perslid_naam").Value, oRs("prs_perslid_oslogin").Value));
/* global */ user_key = oRs("prs_perslid_key").Value;
Response.Status = "401 Unauthorized";
// Sommige applicaties kunnen in reactie hierop een b64 encoded username:password sturen
// Die onderscheppen wij in LoginTry.asp uiteindelijk
if (S("basic_auth_realm"))
Response.AddHeader("WWW-Authenticate", "Basic realm=\"" + S("basic_auth_realm") + "\"");
Response.End;
if (typeof NO_ADDHEADER == "undefined" && Request.Servervariables("HTTP_FCLT_VERSION").Count > 0)
{ // wordt opgepikt door FCLTAPI.DLL voor in de logging en daarna gestript. Niet in Fiddler dus
@@ -93,7 +68,6 @@ api2_rest = {
oRs.Close()
}
/* global */ user = new Perslid(user_key); // wordt mogelijk nog overruled door imporsonate
CheckForLogging(Request.QueryString("logging")); // Nu pas kan autorisatie via user gecontroleerd worden
},

View File

@@ -53,6 +53,7 @@ function model_aut_idp_map(params)
+ ";9;" + L("lcl_prs_person_email")
+ ";10;" + L("lcl_prs_person_phone")
+ ";11;" + L("lcl_prs_person_mobile")
+ ";12;" + L("prs_perslid_externid")
// De foreign's
+ ";20;" + L("lcl_prs_person_function")

View File

@@ -92,7 +92,7 @@ function model_prs_perslid(params)
"label": L("lcl_prs_person_initials"),
"typ": "varchar"
},
"prefix": {
"middlename": {
"dbs": "prs_perslid_tussenvoegsel",
"label": L("lcl_prs_person_tussen"),
"typ": "varchar"
@@ -169,6 +169,11 @@ function model_prs_perslid(params)
"typ": "key",
"foreign": "prs_afdeling"
},
"externalid": {
"dbs": "prs_perslid_externid",
"label": L("prs_perslid_externid"),
"typ": "varchar"
},
"company": {
"dbs": "pa.prs_bedrijf_key",
"label": L("lcl_prs_company"),

View File

@@ -18,6 +18,7 @@
<!-- #include file="../api2/model_prs_perslid.inc" -->
<%
// Elders is prs_key geauthenticeerd. Registreer die hier als de actieve gebruiker.
// stateless komen we hier al niet
function doLogin(prs_key, params)
{
__Log("==== doLogin " + prs_key);
@@ -67,12 +68,6 @@ function doLogin(prs_key, params)
}
}
// Alvast nieuwe user_key loggen zodat je ziet wie er inlogt.
if (typeof NO_ADDHEADER == "undefined" && user_key != prs_key && Request.Servervariables("HTTP_FCLT_VERSION").Count > 0)
{ // wordt opgepikt door FCLTAPI.DLL voor in de logging en daarna gestript. Niet in Fiddler te zien dus
Response.AddHeader ("FCLT_USERID", customerId + "\\" + String(prs_key));
}
/* global */ user_key = prs_key;
//user_lang = oRs(1).Value; // globale moet er nog uit!
if (typeof LCL_Disable == "undefined")
@@ -99,7 +94,7 @@ function doLogin(prs_key, params)
var agent = String(Request.ServerVariables("HTTP_USER_AGENT"));
// Welbeschouwd gebruiken we het volgende FAC_SESSION record nooit, we werken
// altijd met ASPSESSION==>IIS SESSION==>user_key
// altijd met ASPSESSION cookie==>IIS SESSION==>user_key
var sql = "INSERT INTO fac_session"
+ " (fac_session_sessionid_hash,"
+ " prs_perslid_key,"
@@ -180,16 +175,6 @@ function doLogin(prs_key, params)
+ " )";
Oracle.Execute(sql, true);
}
else
{
__Log("Welcome.asp expired?");
var sql = "DELETE FROM fac_menu"
+ " WHERE fac_menu_altgroep = 5"
+ " AND fac_menu_alturl = " + safe.quoted_sql(S("fac_firstlogin_url"))
+ " AND prs_perslid_key = " + user_key
+ " AND fac_menu_aanmaak < SYSDATE - " + S("fac_firstlogin_expire");
Oracle.Execute(sql, true);
}
var fac_lang = getQParamSafe("fac_lang", "").toUpperCase(); // overrule via param
// Liever geen session maar m_connections heeft dit al nodig voor zijn fac.initsession
@@ -200,6 +185,14 @@ function doLogin(prs_key, params)
return true;
}
function doLoginStateless(prs_key, params)
{
/* global */ user_key = prs_key;
Session("user_key") = user_key; // Nu ben je pas *echt* ingelogd
/* global */ user = new Perslid(user_key); // wordt mogelijk nog overruled door imporsonate
Session("stateless") = 1;
Session.Abandon(); // Altijd, voor de zekerheid
}
// Session.Abondon is gevaarlijk: dan verlies je ook CustomerID etc.
// Bovendien krijg je met IIS dan nog steeds geen nieuwe ASPSESSIONID
@@ -258,7 +251,7 @@ function makeSessionCookie (sessionData)
+ "fac.makehash(" + safe.quoted_sql(sessionId) + "), "
+ user_key + ", "
+ safe.quoted_sql(sessionData) + ", "
+ " sysdate + " + S("login_remember_days") + ", " // sessie timeout op een half jaar.
+ " sysdate + " + S("login_remember_days") + ", " // sessie timeout op 30 dagen.
+ safe.quoted_sql(agent, 256) + ","
+ safe.quoted_sql(ip, 64) + " )"
Oracle.Execute(sql);
@@ -440,7 +433,7 @@ function testpassword(prs_key, wachtwoord, pmobile)
oRs.Close();
if (!found)
return false;
// else TODO upgraden!
// else iets verderop upgraden!
var workfactor = 0;
}
else // new style
@@ -487,11 +480,11 @@ function setpassword(prs_key, wachtwoord, expired)
{
var passsalt = shared.random(32);
var workfactor = S("prs_password_hash_factor");
var is_hash = pbkdf2(wachtwoord, passsalt, workfactor);
var new_hash = pbkdf2(wachtwoord, passsalt, workfactor);
var sql = "UPDATE prs_perslid" // Ooit expire op SYSDATE + fac.getsetting ('prs_password_expiration') als die is gevuld
+ " SET prs_perslid_wachtwoord_exp = " + (expired?"SYSDATE":"NULL")
+ " , prs_perslid_salt = " + safe.quoted_sql(passsalt)
+ " , prs_perslid_wachtwoord_hash = " + safe.quoted_sql('1${0}${1}'.format(workfactor, is_hash))
+ " , prs_perslid_wachtwoord_hash = " + safe.quoted_sql('1${0}${1}'.format(workfactor, new_hash))
+ " WHERE prs_perslid_key = " + prs_key;
Oracle.Execute(sql);
}
@@ -505,7 +498,6 @@ function testotp (prs_key, otprequest)
+ " WHERE prs_perslid_key = " + prs_key;
var oRs = Oracle.Execute(sql);
var otpsecret = oRs("prs_perslid_otpsecret").Value;
var otpcounter = oRs("prs_perslid_otpcounter").Value || -1;
oRs.Close();
@@ -549,6 +541,7 @@ function verify_otp (prs_key, otprequest, otpsecret, otpcounter)
return otp_oke;
}
// Op basis van usernaam/wachtwoord gaan we iemand authenticeren
function getIdentity(username, wachtwoord, params)
{
var result = { success: false, fail_reason: L("lcl_login_wrong") };
@@ -622,9 +615,9 @@ function getIdentity(username, wachtwoord, params)
{
logins.push(" upper(prs_perslid_email) = " + safe.quoted_sql_upper(username));
}
else if (getQParam("API", ""))
else if (getQParam("API", "") || getQParam("API2", ""))
{
logins.push(" prs_perslid_apikey = " + safe.quoted_sql_upper(username, 128));
logins.push(" prs_perslid_apikey = " + safe.quoted_sql(username, 128)); // TODO zorgen dat result.stateless gezet raakt
wachtwoord = null;
}
else
@@ -653,6 +646,7 @@ function getIdentity(username, wachtwoord, params)
var oSLNKDWF = new ActiveXObject("SLNKDWF.About");
var sleepmsec = Math.min(80000, tmicro / 1000 * 32);
oSLNKDWF.Sleep(sleepmsec);
oRs.Close();
return result;
}
@@ -660,7 +654,7 @@ function getIdentity(username, wachtwoord, params)
var otpcounter = oRs("prs_perslid_otpcounter").Value || -1;
var found = false;
if (/* nog niet vanuit SAML/default.asp params.noPassword && */ wachtwoord == null) // SSO
if (/* nog niet vanuit SAML/default.asp params.noPassword && */ wachtwoord === null) // SSO
found = true; // En zijn we verder wel klaar
else
found = testpassword(oRs("prs_perslid_key").Value, wachtwoord, params.mobile);
@@ -735,7 +729,12 @@ function tryLogin(username, wachtwoord, params)
return false;
if (ident.user_key > 0)
doLogin(ident.user_key, params);
{
if (ident.stateless || params.stateless)
doLoginStateless(ident.user_key, params);
else
doLogin(ident.user_key, params);
}
return true;
}
@@ -1015,11 +1014,6 @@ function SimpleSSO()
__Log('User#2a = '+username);
}
if (username !='' && username!='undefined') {
// Strip domain name
while( (i = username.indexOf('\\')) >= 0 ) {
l = username.length;
if( i < l-1 ) username = username.substring(i+1,l);
}
tryLogin(username, null, { noPassword: true });
}
}
@@ -1047,11 +1041,6 @@ function IntegratedSSO()
}
if (username !='' && username!='UNDEFINED')
{
// Strip domain name
while( (i = username.indexOf('\\')) >= 0 ) {
l = username.length;
if( i < l-1 ) username = username.substring(i+1,l);
}
tryLogin(username, null, { noPassword: true });
}
}
@@ -1370,14 +1359,14 @@ function process_claim(claim, idp_data, params)
{
case 1: // login
settings.overrule_setting("login_use_email", 0);
tryLogin(claim[idpm.from], null, { noPassword: true, idp_code: idp_data.code, noFacSession: params.by_bearer, isFACFACinternal: isFACFACinternal });
tryLogin(claim[idpm.from], null, { noPassword: true, idp_code: idp_data.code, stateless: params.by_bearer, isFACFACinternal: isFACFACinternal });
break;
case 9: // email
settings.overrule_setting("login_use_email", 1);
tryLogin(claim[idpm.from], null, { noPassword: true, idp_code: idp_data.code, noFacSession: params.by_bearer, isFACFACinternal: isFACFACinternal });
tryLogin(claim[idpm.from], null, { noPassword: true, idp_code: idp_data.code, stateless: params.by_bearer, isFACFACinternal: isFACFACinternal });
break;
case 99: // internal, prs_perslid_key
doLogin(parseInt(claim[idpm.from], 10), { noFacSession: params.by_bearer, idp_code: idp_data.code, isFACFACinternal: isFACFACinternal });
doLogin(parseInt(claim[idpm.from], 10), { stateless: params.by_bearer, idp_code: idp_data.code, isFACFACinternal: isFACFACinternal });
break;
default:
if (idpm.name.id > 1000) // Flexkenmerk
@@ -1394,7 +1383,7 @@ function process_claim(claim, idp_data, params)
var oRs = Oracle.Execute(sql);
if (!oRs.Eof)
{
doLogin(oRs("prs_perslid_key").Value, { noFacSession: params.by_bearer, idp_code: idp_data.code, isFACFACinternal: isFACFACinternal });
doLogin(oRs("prs_perslid_key").Value, { stateless: params.by_bearer, idp_code: idp_data.code, isFACFACinternal: isFACFACinternal });
}
oRs.Close();
}
@@ -1414,218 +1403,225 @@ function process_claim(claim, idp_data, params)
|| user_key > 0 && idp_data.autocreate.id & 2 // en/ of bijwerken
)
{
var persdata = { };
for (var i =0; i < idp_data.idpmappings.length; i++)
{
var idpm = idp_data.idpmappings[i];
var val = idpm["default"];
if (idpm.from in claim)
val = claim[idpm.from];
process_claim_update(claim, idp_data, params)
}
}
switch (idpm.name.id) // zie model_aut_idp_map.inc voor codering
function process_claim_update(claim, idp_data, params)
{
var isFACFACinternal = idp_data.internal != 0;
var persdata = { };
for (var i =0; i < idp_data.idpmappings.length; i++)
{
var idpm = idp_data.idpmappings[i];
var val = idpm["default"];
if (idpm.from in claim)
val = claim[idpm.from];
switch (idpm.name.id) // zie model_aut_idp_map.inc voor codering
{
case 1: persdata["login"] = val; break;
case 2: persdata["lastname"] = val; break;
case 3: persdata["firstname"] = val; break;
case 4: persdata["middlename"] = val; break;
case 5: persdata["initials"] = val; break;
case 6: persdata["gender"] = val; break;
case 7: persdata["phone"] = val; break;
case 8: persdata["title"] = val; break;
case 9: persdata["email"] = val; break;
case 10: persdata["phone"] = val; break;
case 11: persdata["mobile"] = val; break;
case 12: persdata["externalid"] = val; break;
// de foreigns
case 20: if (val)
persdata["function"] = { name: val }; break; // Kan omdat fields.function.desc_is_unique is gezet
case 21: if (val) // afdeling
{
case 1: persdata["login"] = val; break;
case 2: persdata["lastname"] = val; break;
case 3: persdata["firstname"] = val; break;
case 4: persdata["prefix"] = val; break;
case 5: persdata["initials"] = val; break;
case 6: persdata["gender"] = val; break;
case 7: persdata["phone"] = val; break;
case 8: persdata["title"] = val; break;
case 9: persdata["email"] = val; break;
case 10: persdata["phone"] = val; break;
case 11: persdata["mobile"] = val; break;
// de foreigns
case 20: if (val)
persdata["function"] = { name: val }; break; // Kan omdat fields.function.desc_is_unique is gezet
case 21: if (val) // afdeling
// Zoek afdeling
var sql = "SELECT prs_afdeling_key"
+ " FROM prs_v_afdeling"
+ " WHERE prs_afdeling_verwijder IS NULL"
+ " AND prs_afdeling_upper = " + safe.quoted_sql_upper(val);
if (idp_data.department)
{
// Zoek afdeling
var sql = "SELECT prs_afdeling_key"
+ " FROM prs_v_afdeling"
+ " WHERE prs_afdeling_verwijder IS NULL"
+ " AND prs_afdeling_upper = " + safe.quoted_sql_upper(val);
if (idp_data.department)
{
sql += " AND prs_afdeling_parentkey = " + idp_data.department.id;
}
else
{
if (idp_data.company)
sql += " AND prs_bedrijf_key = " + idp_data.company.id;
}
var oRs = Oracle.Execute(sql);
if (oRs.Eof)
{
__Log("Claimed department {0} not found".format(val));
// Er komt eventueel wel een fallback naar idp_data.department.id
}
else
{
var afd_key = oRs("prs_afdeling_key").Value;
oRs.MoveNext();
if (!oRs.Eof)
shared.internal_error("Claimed department {0} not unique".format(val));
persdata["department"] = afd_key;
}
oRs.Close();
break;
}
// De 1-n
case 100: persdata.authorisation = val; break;
case 101: persdata.workplace = val; break;
// case 102: persdata.workplacevirtual = val; break;
// case 103: reserved voor mandatering?
default:
if (idpm.name.id > 1000)
set_custom_field(persdata, idpm.name.id - 1000, val, "C");
break;
}
}
// Klantspecifieke check functie (hookfunction) voor de invoer
var pResult = new HookResult();
if (!custfunc.aut_process_claim(persdata, claim, idp_data, pResult))
{
abort_with_warning(pResult.errmsg);
}
if (!("department" in persdata))
{
if (!idp_data.department)
shared.internal_error("Department is not configured for Identity Provider {0} ({1})".format(idp_data.code, idp_data.name));
persdata["department"] = idp_data.department.id; // dan moet die ingevuld zijn
}
if (user_key < 0)
__Log("User automatically created with data:");
else
__Log("User automatically updated with data:");
__Log(persdata);
var persparams = {};
var person = new model_prs_perslid({ internal: true }); // Internal: true om dit (nog) anoniem te mogen doen
if (user_key > 0) // bijwerken
{
person.REST_PUT( persparams, persdata, user_key );
}
else // nieuwe
{
var prs = person.REST_POST( persparams, persdata );
__DoLog("Created user '{0} {1}' with key {2} for idp '{3}'".format(persdata["firstname"], persdata["lastname"], prs.key, idp_data.code));
// De nieuw aangemaakte gebruiker inloggen:
doLogin(prs.key, { idp_code: idp_data.code, isFACFACinternal: isFACFACinternal });
// En nu pas kunnen we tracken
shared.trackaction("PRSUPD", prs.key, "Created user '{0} {1}' for idp '{2}'".format(persdata["firstname"], persdata["lastname"], idp_data.code));
}
// Nu authorisatie groepen nog bijwerken
// Via het model was me even iets te hoog gegrepen: ik zou toch (nog) de id's er bij moeten halen
if ("authorisation" in persdata)
{ // authorisation bevat gebruikersgroepen gescheiden door '|' of ';'
/* SHIB: Within each CGI variable or header (see below), multiple attribute values
are separated by a semicolon, and semicolons in values are escaped with a backslash.
The data should be interpreted as UTF-8, which is a superset of ASCII.
*/
var autharr = persdata["authorisation"].toLowerCase().split(/[;\|]/); // lowerCase, insensitive dus
var sql = "DELETE FROM fac_gebruikersgroep"
+ " WHERE prs_perslid_key = " + user_key
+ " AND fac_groep_key NOT IN (SELECT fac_groep_key "
+ " FROM fac_groep"
+ " WHERE LOWER(fac_groep_omschrijving) IN ({0})".format(safe.quoted_sql_join(autharr))
+ " OR SUBSTR(fac_groep_omschrijving, 1, 1) = '_'" // Die blijven altijd
+ " )";
Oracle.Execute(sql);
var sql = "INSERT INTO fac_gebruikersgroep(prs_perslid_key, fac_groep_key)"
+ " SELECT " + user_key + ", fac_groep_key"
+ " FROM fac_groep fg"
+ " WHERE LOWER(fac_groep_omschrijving) IN ({0})".format(safe.quoted_sql_join(autharr))
+ " AND SUBSTR(fac_groep_omschrijving, 1, 1) <> '_'" // Die nooit
+ " AND NOT EXISTS (SELECT 1"
+ " FROM fac_gebruikersgroep fg2"
+ " WHERE fg2.fac_groep_key = fg.fac_groep_key"
+ " AND fg2.prs_perslid_key = " + user_key + ")";
Oracle.Execute(sql);
}
if ("workplace" in persdata)
{
// Eerst oude werkplekken ophalen
var sql = "SELECT pw.prs_werkplek_key, UPPER(alg_plaatsaanduiding) alg_plaatsaanduiding"
+ " FROM prs_perslidwerkplek pw, prs_werkplek wp, alg_v_plaatsaanduiding"
+ " WHERE pw.prs_perslid_key = " + user_key
+ " AND pw.prs_werkplek_key = wp.prs_werkplek_key"
+ " AND wp.prs_werkplek_type = 0" // alleen vaste plekken
+ " AND alg_onroerendgoed_keys = wp.prs_alg_ruimte_key"
+ " AND alg_onroerendgoed_type = 'R'";
var oRs = Oracle.Execute(sql);
var oldWP = {};
while (!oRs.Eof)
{
oldWP[oRs("alg_plaatsaanduiding").Value] = oRs("prs_werkplek_key").Value;
oRs.MoveNext();
}
oRs.Close();
// workplace bevat ruimtes gescheiden door '|' of ';'
// (we ondersteunen alleen impliciete werkplekken, geen 'named')
// Codering moet volgens alg_v_plaatsaanduiding zijn (locatiecode-gebouwcode-verdiepingcode-ruimtenr)
// Als er een '@' voor staat is het een virtuele werkplek
persdata["workplace"] = persdata["workplace"] || "";
var workplacearr = persdata["workplace"].split(/[;\|]/);
for (var i = 0; i < workplacearr.length; i++)
{
var wpcode = workplacearr[i];
var virtual = 0;
if (wpcode.substr(0, 1) == '@')
{
virtual = 1;
wpcode = wpcode.substr(1);
}
if (wpcode in oldWP)
{
delete oldWP[wpcode]; // Hoeven we straks niet te wissen
}
else // Toevoegen
{
var sql = "SELECT alg_onroerendgoed_keys"
+ " FROM alg_v_plaatsaanduiding"
+ " WHERE alg_onroerendgoed_type = 'R'"
+ " AND UPPER(alg_plaatsaanduiding) = " + safe.quoted_sql_upper(wpcode);
var oRs = Oracle.Execute(sql);
if (!oRs.Eof)
{
delete oldWP[wpcode.toUpperCase()]; // Die zal hergebruikt worden
var okey = oRs("alg_onroerendgoed_keys").Value;
sql = "BEGIN"
+ " prs.movetoruimte ({0}, {1}, '{2}', {3}); ".format(user_key, okey, 'G', virtual) // G want maar <20><>n werkplek per gebouw
+ "END;";
Oracle.Execute(sql);
}
else
__Log("Workplace '{0}' not found".format(workplacearr[i]));
oRs.Close();
}
}
for (wpcode in oldWP) // restant opruimen
{
__Log("Persoon verwijderen van WP {0}, wp-key {1}".format(wpcode, oldWP[wpcode]));
if (S("prs_werkplek_implicit") == 1)
{
var sql = "DELETE FROM prs_werkplek"
+ " WHERE prs_werkplek_key = " + oldWP[wpcode];
sql += " AND prs_afdeling_parentkey = " + idp_data.department.id;
}
else
{
var sql = "DELETE FROM prs_perslid_werkplek"
+ " WHERE prs_perslid_key = " + user_key
+ " AND prs_werkplek_key = " + oldWP[wpcode];
if (idp_data.company)
sql += " AND prs_bedrijf_key = " + idp_data.company.id;
}
Oracle.Execute(sql);
var oRs = Oracle.Execute(sql);
if (oRs.Eof)
{
__Log("Claimed department {0} not found".format(val));
// Er komt eventueel wel een fallback naar idp_data.department.id
}
else
{
var afd_key = oRs("prs_afdeling_key").Value;
oRs.MoveNext();
if (!oRs.Eof)
shared.internal_error("Claimed department {0} not unique".format(val));
persdata["department"] = afd_key;
}
oRs.Close();
break;
}
// De 1-n
case 100: persdata.authorisation = val; break;
case 101: persdata.workplace = val; break;
// case 102: persdata.workplacevirtual = val; break;
// case 103: reserved voor mandatering?
default:
if (idpm.name.id > 1000)
set_custom_field(persdata, idpm.name.id - 1000, val, "C");
break;
}
}
// Klantspecifieke check functie (hookfunction) voor de invoer
var pResult = new HookResult();
if (!custfunc.aut_process_claim(persdata, claim, idp_data, pResult))
{
abort_with_warning(pResult.errmsg);
}
if (!("department" in persdata))
{
if (!idp_data.department)
shared.internal_error("Department is not configured for Identity Provider {0} ({1})".format(idp_data.code, idp_data.name));
persdata["department"] = idp_data.department.id; // dan moet die ingevuld zijn
}
if (user_key < 0)
__Log("User automatically created with data:");
else
__Log("User automatically updated with data:");
__Log(persdata);
var persparams = {};
var person = new model_prs_perslid({ internal: true }); // Internal: true om dit (nog) anoniem te mogen doen
if (user_key > 0) // bijwerken
{
person.REST_PUT( persparams, persdata, user_key );
}
else // nieuwe
{
var prs = person.REST_POST( persparams, persdata );
__DoLog("Created user '{0} {1}' with key {2} for idp '{3}'".format(persdata["firstname"], persdata["lastname"], prs.key, idp_data.code));
// De nieuw aangemaakte gebruiker inloggen:
doLogin(prs.key, { idp_code: idp_data.code, isFACFACinternal: isFACFACinternal });
// En nu pas kunnen we tracken
shared.trackaction("PRSUPD", prs.key, "Created user '{0} {1}' for idp '{2}'".format(persdata["firstname"], persdata["lastname"], idp_data.code));
}
// Nu authorisatie groepen nog bijwerken
// Via het model was me even iets te hoog gegrepen: ik zou toch (nog) de id's er bij moeten halen
if ("authorisation" in persdata)
{ // authorisation bevat gebruikersgroepen gescheiden door '|' of ';'
/* SHIB: Within each CGI variable or header (see below), multiple attribute values
are separated by a semicolon, and semicolons in values are escaped with a backslash.
The data should be interpreted as UTF-8, which is a superset of ASCII.
*/
var autharr = persdata["authorisation"].toLowerCase().split(/[;\|]/); // lowerCase, insensitive dus
var sql = "DELETE FROM fac_gebruikersgroep"
+ " WHERE prs_perslid_key = " + user_key
+ " AND fac_groep_key NOT IN (SELECT fac_groep_key "
+ " FROM fac_groep"
+ " WHERE LOWER(fac_groep_omschrijving) IN ({0})".format(safe.quoted_sql_join(autharr))
+ " OR SUBSTR(fac_groep_omschrijving, 1, 1) = '_'" // Die blijven altijd
+ " )";
Oracle.Execute(sql);
var sql = "INSERT INTO fac_gebruikersgroep(prs_perslid_key, fac_groep_key)"
+ " SELECT " + user_key + ", fac_groep_key"
+ " FROM fac_groep fg"
+ " WHERE LOWER(fac_groep_omschrijving) IN ({0})".format(safe.quoted_sql_join(autharr))
+ " AND SUBSTR(fac_groep_omschrijving, 1, 1) <> '_'" // Die nooit
+ " AND NOT EXISTS (SELECT 1"
+ " FROM fac_gebruikersgroep fg2"
+ " WHERE fg2.fac_groep_key = fg.fac_groep_key"
+ " AND fg2.prs_perslid_key = " + user_key + ")";
Oracle.Execute(sql);
}
if ("workplace" in persdata)
{
// Eerst oude werkplekken ophalen
var sql = "SELECT pw.prs_werkplek_key, UPPER(alg_plaatsaanduiding) alg_plaatsaanduiding"
+ " FROM prs_perslidwerkplek pw, prs_werkplek wp, alg_v_plaatsaanduiding"
+ " WHERE pw.prs_perslid_key = " + user_key
+ " AND pw.prs_werkplek_key = wp.prs_werkplek_key"
+ " AND wp.prs_werkplek_type = 0" // alleen vaste plekken
+ " AND alg_onroerendgoed_keys = wp.prs_alg_ruimte_key"
+ " AND alg_onroerendgoed_type = 'R'";
var oRs = Oracle.Execute(sql);
var oldWP = {};
while (!oRs.Eof)
{
oldWP[oRs("alg_plaatsaanduiding").Value] = oRs("prs_werkplek_key").Value;
oRs.MoveNext();
}
oRs.Close();
// workplace bevat ruimtes gescheiden door '|' of ';'
// (we ondersteunen alleen impliciete werkplekken, geen 'named')
// Codering moet volgens alg_v_plaatsaanduiding zijn (locatiecode-gebouwcode-verdiepingcode-ruimtenr)
// Als er een '@' voor staat is het een virtuele werkplek
persdata["workplace"] = persdata["workplace"] || "";
var workplacearr = persdata["workplace"].split(/[;\|]/);
for (var i = 0; i < workplacearr.length; i++)
{
var wpcode = workplacearr[i];
var virtual = 0;
if (wpcode.substr(0, 1) == '@')
{
virtual = 1;
wpcode = wpcode.substr(1);
}
if (wpcode in oldWP)
{
delete oldWP[wpcode]; // Hoeven we straks niet te wissen
}
else // Toevoegen
{
var sql = "SELECT alg_onroerendgoed_keys"
+ " FROM alg_v_plaatsaanduiding"
+ " WHERE alg_onroerendgoed_type = 'R'"
+ " AND UPPER(alg_plaatsaanduiding) = " + safe.quoted_sql_upper(wpcode);
var oRs = Oracle.Execute(sql);
if (!oRs.Eof)
{
delete oldWP[wpcode.toUpperCase()]; // Die zal hergebruikt worden
var okey = oRs("alg_onroerendgoed_keys").Value;
sql = "BEGIN"
+ " prs.movetoruimte ({0}, {1}, '{2}', {3}); ".format(user_key, okey, 'G', virtual) // G want maar <20><>n werkplek per gebouw
+ "END;";
Oracle.Execute(sql);
}
else
__Log("Workplace '{0}' not found".format(workplacearr[i]));
oRs.Close();
}
}
for (wpcode in oldWP) // restant opruimen
{
__Log("Persoon verwijderen van WP {0}, wp-key {1}".format(wpcode, oldWP[wpcode]));
if (S("prs_werkplek_implicit") == 1)
{
var sql = "DELETE FROM prs_werkplek"
+ " WHERE prs_werkplek_key = " + oldWP[wpcode];
}
else
{
var sql = "DELETE FROM prs_perslid_werkplek"
+ " WHERE prs_perslid_key = " + user_key
+ " AND prs_werkplek_key = " + oldWP[wpcode];
}
Oracle.Execute(sql);
}
}
}

View File

@@ -6,11 +6,24 @@
Met vernieuwde kennis zou ik dit bestand authenticate.asp noemen
We weten niet wie de gebruiker is.
Probeer op allerlei manieren SSO
Probeer op allerlei manieren te authentiseren
Als het lukt geven we een user_key terug in Session("user_key");
Als het niet lukt zal doorgaans door common.inc verder gegaan worden in de interactieve Logon.asp
LET OP: Dit bestand wordt via Server.Transfer vanuit Common.inc aangeroepen
We onderscheiden twee soorten authenticatie
Statefull
Dit is voor een interactieve gebruiker met een browser. Initieel wordt op
allerlei manieren authenticatie geprobeerd maar daarna wordt de user_key
in een Session opgeslagen en de volgende keer wordt via een Session-coolie
vanuit die session de authenticatie gedaan
In prs_perslid_login wordt het laatste moment van inloggen bijgewrkt
Er wordt een fac_session record aangemaakt (waar we verder weinig mee doen)
Stateless
Dit is voor API aanroepen. ELKE aanroep komt de authenticatie opnieuw
mee. Dit wordt niet geregistreerd in prs_perslid_login
Er wordt een Session.abandon gedaan om niet te veel IIS sessies te houden
*/
DOCTYPE_Disable = 1;
ANONYMOUS_Allowed = 1;
@@ -46,19 +59,28 @@ if (typeof Session("sso_sgf") == "string") // Vanuit FACWS001-portal/ sso_sgf.as
Session.Contents.Remove("sso_sgf_realuser");
}
// De stateless varianten proberen we eerst, die worden tenslotte potentieel vaak uitgevoerd
if (user_key < 0)
SimpleSSO(); // de base64 simple sso
// Ingescande QR-code bookmark gaat naar \appl\prs\prs_perslid_qr_confirm.asp
if (user_key < 0) // Probeer de user_key uit een cookie te halen
{
var FcltId = "" + Request.Cookies("fcltid");
if (FcltId != null && FcltId != "")
var APIKEY;
if (S("fac_api_key_in_url"))
APIKEY = getQParam("APIKEY", "");
if (!APIKEY && Request.ServerVariables("HTTP_X_FACILITOR_API_KEY").Count)
APIKEY = String(Request.ServerVariables("HTTP_X_FACILITOR_API_KEY")); // Meegegeven als X-FACILITOR-API-Key
if (APIKEY)
{
setUserFromSession (FcltId);
if (user_key > 0)
makeSessionCookie("Remember Login"); // Atijd nieuwe
var sql = "SELECT prs_perslid_key, prs_perslid_naam, prs_perslid_oslogin"
+ " FROM prs_perslid"
+ " WHERE prs_perslid_verwijder IS NULL"
+ " AND prs_perslid_apikey = " + safe.quoted_sql(APIKEY);
var oRs = Oracle.Execute(sql);
if (!oRs.Eof)
{
__Log("API2 User is: {0} ({1})".format(oRs("prs_perslid_naam").Value, oRs("prs_perslid_oslogin").Value));
doLoginStateless(oRs("prs_perslid_key").Value);
}
// else negeren
oRs.Close()
}
}
@@ -74,11 +96,27 @@ if (user_key < 0)
{
var ww = plain.split(":");
ww.shift();
tryLogin(plain.split(":")[0], ww.join(":")); // Behoudt eventuele ':' in wachtwoord
tryLogin(plain.split(":")[0], ww.join(":"), { stateless: true }); // Behoudt eventuele ':' in wachtwoord
}
}
}
if (user_key < 0)
SimpleSSO(); // de base64 simple sso
// Ingescande QR-code bookmark gaat naar \appl\prs\prs_perslid_qr_confirm.asp
if (user_key < 0) // Probeer de user_key uit een cookie te halen
{
var FcltId = "" + Request.Cookies("fcltid");
if (FcltId != null && FcltId != "")
{
setUserFromSession (FcltId);
if (user_key > 0)
makeSessionCookie("Remember Login"); // Atijd nieuwe
}
}
if (user_key < 0)
{
var auth = String(Request.ServerVariables("HTTP_X_FACILITOR_ACCESS_TOKEN"));
@@ -269,7 +307,7 @@ if (user_key < 0 && APIname)
var API = new API_func(); // controleert vanzelf
if (API.apidata.prs_perslid_key)
doLogin(API.apidata.prs_perslid_key, { noFacSession: true });
doLogin(API.apidata.prs_perslid_key, { stateless: true });
}
// LogOff.asp kan Session("no_sso") gezet hebben
@@ -297,6 +335,15 @@ if (user_key < 0 && S("os_logon")
//if (user_key < 0)
// trySSO("DEFAULT"); // zal je standaard naar het loginscherm sturen
if (user_key > 0) // dan hebben we (nu) een nieuwe user
{
// Alvast nieuwe user_key loggen zodat je ziet wie er inlogt.
if (typeof NO_ADDHEADER == "undefined" && Request.Servervariables("HTTP_FCLT_VERSION").Count > 0)
{ // wordt opgepikt door FCLTAPI.DLL voor in de logging en daarna gestript. Niet in Fiddler dus
Response.AddHeader ("FCLT_USERID", customerId + "\\" + String(user_key));
}
}
__Log("== Leaving loginTry.asp ==");
%>

View File

@@ -74,6 +74,14 @@
}
// einde conversie user_options naar fac_menu
__Log("Welcome.asp expired?");
var sql = "DELETE FROM fac_menu"
+ " WHERE fac_menu_altgroep = 5"
+ " AND fac_menu_alturl = " + safe.quoted_sql(S("fac_firstlogin_url"))
+ " AND prs_perslid_key = " + user_key
+ " AND fac_menu_aanmaak < SYSDATE - " + S("fac_firstlogin_expire");
Oracle.Execute(sql, true);
// autoopen ophalen uit database
var autoopen = [];
var sql = "SELECT fac_menu_altlabel"

View File

@@ -22,6 +22,8 @@
<!--#include file="../Shared/iface.inc" -->
<%
debugger;
FCLTHeader.Requires({plugins:["suggest","jQuery"], js: ["jquery-ui.js"]})
var submitting = getQParamInt("submit", 0) == 1;

View File

@@ -42,4 +42,18 @@
<match url="^melding/(\d+)" />
<action type="Rewrite" url="default.asp?u=melding&amp;k={R:1}" appendQueryString="true" />
</rule>
<rule name="SCIMUsers" stopProcessing="true">
<match url="^SCIM/Users" />
<action type="Rewrite" url="default.asp?api2=persons&amp;format=json&amp;plugin=scimusers&amp;include=lastchange,authorization" appendQueryString="true" />
</rule>
<!--
<rule name="Check file exists">
<match url="^([^.]+)\.([a-zA-Z]+)" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="/appl/shared/404_error.asp?url404={R:1}.{R:2}" appendQueryString="true" />
</rule>
-->
</rules>