365 lines
15 KiB
Plaintext
365 lines
15 KiB
Plaintext
<%@language = "javascript" %>
|
||
<% /*
|
||
$Revision$
|
||
$Id$
|
||
|
||
Met vernieuwde kennis zou ik dit bestand authenticate.asp noemen
|
||
|
||
We weten niet wie de gebruiker is.
|
||
Probeer op allerlei manieren SSO
|
||
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
|
||
*/
|
||
DOCTYPE_Disable = 1;
|
||
ANONYMOUS_Allowed = 1;
|
||
LOGIN_try = 1; // prevent recursion
|
||
NO_ADDHEADER = 1; // common.inc voert wat globale acties hierdoor niet meer uit
|
||
THIS_FILE = 'appl/shared/logintry.asp';
|
||
|
||
if (Response.Expires > 0)
|
||
FCLTEXPIRES = Response.Expires; // Aanroeper wist het beter?
|
||
%>
|
||
<!-- #include file="../Shared/common.inc" -->
|
||
<!-- #include file="./login.inc" -->
|
||
<!-- #include file="../api/api.inc" -->
|
||
<!-- #include file="../api2/api2.inc" -->
|
||
<!-- #include file="../api2/model_prs_perslid.inc" -->
|
||
<%
|
||
__Log("== Entering loginTry.asp ==");
|
||
|
||
if (typeof Session("sso_sgf") == "string") // Vanuit FACWS001-portal/ sso_sgf.asp
|
||
{
|
||
Session.Contents.Remove("ASPFIXATION"); // Niet moeilijk doen
|
||
settings.overrule_setting("login_use_email", 0); // We hebben altijd login gescanned namelijk
|
||
tryLogin(String(Session("sso_sgf")), null, { noPassword: true });
|
||
if (user_key < 0 && parseInt(String(Session("sso_sgf")), 10))
|
||
doLogin(parseInt(String(Session("sso_sgf")), 10)); // je mag ook key meegeven
|
||
|
||
var realuser = Session("sso_sgf_realuser");
|
||
if (user_key > 0 && realuser)
|
||
shared.trackaction("PRSLOG", user_key, L("lcl_logged_on_sso").format(realuser, Request.ServerVariables("REMOTE_ADDR")));
|
||
Session.Contents.Remove("sso_sgf");
|
||
Session.Contents.Remove("sso_sgf_realuser");
|
||
}
|
||
|
||
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_AUTHORIZATION"));
|
||
if (auth.match(/^Basic /))
|
||
{
|
||
__Log("Found Authorization: Basic");
|
||
var b64 = auth.substring(6);
|
||
var plain = decode_b64(b64);
|
||
if (plain.split(":").length > 1)
|
||
{
|
||
var ww = plain.split(":");
|
||
ww.shift();
|
||
tryLogin(plain.split(":")[0], ww.join(":")); // Behoudt eventuele ':' in wachtwoord
|
||
}
|
||
}
|
||
}
|
||
|
||
if (user_key < 0)
|
||
{
|
||
// Deeplink met &userauth=27399&userhmac=1387370160%3AECQXKFpi8RU5WTK2pfJ0zRnc7QY
|
||
if (Request.QueryString("userauth").Count > 0)
|
||
{
|
||
var userauth = getQParamInt("userauth"); // Zal een perslid_key zijn
|
||
var userhmac = getQParam("userhmac");
|
||
protectHMAC.verify(String(userauth), userhmac);
|
||
doLogin(userauth);
|
||
}
|
||
}
|
||
// jwt claim
|
||
// Niet zo maar een getFParam proberen. Dat nekt API2/PUT's binaryRead
|
||
var jwt = getQParam("jwt", "");
|
||
if (user_key < 0 && !jwt)
|
||
{
|
||
var auth = String(Request.ServerVariables("HTTP_AUTHORIZATION"));
|
||
if (auth.match(/^Bearer /))
|
||
{
|
||
__Log("Found Authorization: Bearer");
|
||
jwt = auth.substring(7);
|
||
var by_bearer = true; // deze is stateless dus geen sessie aanmaken.
|
||
Session.Abandon();
|
||
}
|
||
}
|
||
if ((user_key < 0 || getQParamInt("jwtforce", 0) == 1) && jwt)
|
||
{
|
||
var claim = jwt_decode(jwt);
|
||
|
||
if (claim.err)
|
||
shared.internal_error("Invalid JWT: " + claim.err);
|
||
|
||
__Log(claim.payload);
|
||
|
||
var sql = "SELECT *"
|
||
+ " FROM fac_idp"
|
||
+ " WHERE fac_idp_type = 4" // JWT
|
||
+ " AND fac_idp_issuer = " + safe.quoted_sql(claim.payload.iss)
|
||
+ " AND fac_idp_audience = " + safe.quoted_sql(claim.payload.aud);
|
||
var oRs = Oracle.Execute(sql);
|
||
if (oRs.Eof)
|
||
shared.internal_error("Unknown JWT issuer {0} for audience {1}".format(claim.payload.iss, claim.payload.aud));
|
||
|
||
var verify = jwt_verify(claim, oRs("fac_idp_secret").Value, oRs("fac_idp_clockskew").Value, oRs("fac_idp_duration").Value);
|
||
if (verify.err)
|
||
shared.internal_error("Invalid JWT: " + verify.err);
|
||
|
||
if (!oRs("fac_idp_duration").Value) // single use tokens wil ik niet weer zien
|
||
{
|
||
// Voorkomt alle replay-aanvallen
|
||
// Iets verderop onthouden we signature
|
||
var sql = "SELECT prs_perslid_key, fac_session_data "
|
||
+ " FROM fac_session "
|
||
+ " WHERE fac_session_expire > sysdate "
|
||
+ " AND fac_session_sessionid_hash = " + safe.quoted_sql(claim.signature64);
|
||
var oRs2 = Oracle.Execute( sql );
|
||
if (!oRs2.eof)
|
||
shared.internal_error("Invalid JWT: it has been used before.");
|
||
oRs2.Close();
|
||
}
|
||
|
||
// en claim.jit registreren/ controleren in fac_session
|
||
var idp_code = oRs("fac_idp_code").Value;
|
||
var isFACFACinternal = oRs("fac_idp_internal").Value != 0;
|
||
if (isFACFACinternal && !claim.payload.fclt_realuser && !by_bearer)
|
||
{
|
||
shared.internal_error("Missing fclt_realuser in claim. It is required for IDP_internal.");
|
||
}
|
||
|
||
// Ok, de claim is geldig. Nu kijken of we er iets mee kunnen
|
||
if (claim.payload.username) // je mag username meegeven
|
||
{
|
||
settings.overrule_setting("login_use_email", 0);
|
||
tryLogin(claim.payload.username, null, { noPassword: true, idp_code: idp_code, noFacSession: by_bearer, isFACFACinternal: isFACFACinternal });
|
||
if (user_key < 0)
|
||
__DoLog("JWT Claimed username not found: {0}".format(claim.payload.username))
|
||
}
|
||
if (user_key < 0 && claim.payload.email) // je mag email meegeven
|
||
{
|
||
settings.overrule_setting("login_use_email", 1);
|
||
tryLogin(claim.payload.email, null, { noPassword: true, noFacSession: by_bearer, idp_code: idp_code, isFACFACinternal: isFACFACinternal });
|
||
if (user_key < 0)
|
||
__DoLog("JWT Claimed email not found: {0}".format(claim.payload.email))
|
||
}
|
||
if (user_key < 0 && claim.payload.perslid_key > 0)
|
||
{
|
||
doLogin(claim.payload.perslid_key, { noFacSession: by_bearer, idp_code: idp_code, isFACFACinternal: isFACFACinternal }); // je mag ook key meegeven
|
||
if (user_key < 0)
|
||
__DoLog("JWT Claimed perslid_key not found: {0}".format(claim.payload.perslid_key));
|
||
}
|
||
|
||
if ( user_key < 0 && oRs("fac_idp_autocreate").Value & 1 // Misschien dan maar aanmaken?
|
||
|| user_key > 0 && oRs("fac_idp_autocreate").Value & 2 // en/ of bijwerken
|
||
)
|
||
{
|
||
__Log("JWT user automatically created with data:");
|
||
__Log(claim.payload);
|
||
|
||
// Tot nu toe waren we nog anoniem. Om personen aan te maken of bij te werken
|
||
// (via de API) mogen we echt(er) niet meer anoniem zijn.
|
||
// De API2 controleert daar (terecht) op
|
||
// /*global*/ user_key = 33083; // Moet PRSSYS hebben
|
||
// /*global*/ user = new Perslid(user_key);
|
||
|
||
var person = new model_prs_perslid();
|
||
var persdata = {};
|
||
var sql = "SELECT *"
|
||
+ " FROM fac_idp_map"
|
||
+ " WHERE fac_idp_key = " + oRs("fac_idp_key").Value;
|
||
var oRsMap = Oracle.Execute(sql);
|
||
while (!oRsMap.Eof)
|
||
{
|
||
var val = oRsMap("fac_idp_map_default").Value;
|
||
if (oRsMap("fac_idp_map_from").Value in claim.payload)
|
||
val = claim.payload[oRsMap("fac_idp_map_from").Value];
|
||
switch (oRsMap("fac_idp_map_to").Value) // zie model_fac_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["email"] = val; break;
|
||
case 5: if (val) persdata["department"] = { name: val }; break;
|
||
// kostenplaats case 6: persdata["costcenter"] = { name: val }; break;
|
||
case 7: if (val) persdata["function"] = { name: val }; break;
|
||
//case 100: persdata.werkplekken = val; break;
|
||
case 101: persdata.authorisation = val; break;
|
||
}
|
||
|
||
oRsMap.MoveNext();
|
||
}
|
||
oRsMap.Close();
|
||
if (!("department" in persdata))
|
||
persdata["department"] = oRs("prs_afdeling_key").Value; // dan moet die ingevuld zijn
|
||
|
||
var persparams = {};
|
||
|
||
if (user_key > 0) // bijwerken
|
||
{
|
||
person.REST_PUT( persparams, persdata, user_key );
|
||
}
|
||
else // nieuwe
|
||
{
|
||
var res = person.REST_POST( persparams, persdata);
|
||
// user = user_key = null;
|
||
__DoLog("Created user '{0} {1}' with key {2} for idp '{3}'".format(persdata["firstname"], persdata["lastname"], res.key, idp_code));
|
||
doLogin(res.key, { noFacSession: by_bearer, idp_code: idp_code, isFACFACinternal: isFACFACinternal });
|
||
}
|
||
// 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)
|
||
{
|
||
var autharr = persdata["authorisation"].toLowerCase().split("|");
|
||
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);
|
||
}
|
||
// TODO: werkplekken verwerken
|
||
}
|
||
|
||
if (user_key > 0)
|
||
{
|
||
// TODO: Als prs_perslid_credentials_datum > claim.payload.iat dan toch niet accepteren
|
||
|
||
if (!oRs("fac_idp_duration").Value) // single use tokens wil ik niet weer zien
|
||
{ // ook al zijn ze alleen geldig van -clockskew tot +clockskew
|
||
// Ongeldige lukken de volgende keer ook niet. Geldige wil ik niet weer zien
|
||
// De expiretijd gaat er alleen over wanneer ik mag opruimen. Neem daarbij uur speling
|
||
var agent = String(Request.ServerVariables("HTTP_USER_AGENT"));
|
||
var ip = String(Request.ServerVariables("REMOTE_ADDR"));
|
||
var sql = "INSERT INTO fac_session"
|
||
+ " (fac_session_sessionid_hash,"
|
||
+ " fac_session_data,"
|
||
+ " prs_perslid_key,"
|
||
+ " fac_session_expire,"
|
||
+ " fac_session_useragent,"
|
||
+ " fac_session_ip)"
|
||
+ " VALUES(" + safe.quoted_sql(claim.signature64) + ", "
|
||
+ " 'JWT replay preventer', "
|
||
+ user_key + ", "
|
||
+ " SYSDATE + 1/24 + 1/24/60/60 * " + oRs("fac_idp_clockskew").Value + ", "
|
||
+ safe.quoted_sql(agent, 256) + ", "
|
||
+ safe.quoted_sql(ip, 64) + ")";
|
||
Oracle.Execute(sql);
|
||
}
|
||
|
||
// Onthouden hoe je bent binnengekomen zodat logout naar logout_url kan leiden
|
||
Session("idp_key") = oRs("fac_idp_key").Value;
|
||
oRs.Close(); // nu niet meer nodig
|
||
|
||
if (claim.payload.fclt_realuser)
|
||
shared.trackaction("PRSLOG", user_key, L("lcl_logged_on_sso").format(claim.payload.fclt_realuser, Request.ServerVariables("REMOTE_ADDR")));
|
||
|
||
if (!by_bearer) // bearer is stateless/ single request dus geen redirect
|
||
{
|
||
var return_to = getQParam("return_to", "/") || "/";
|
||
// validate: enkele / voor root, /? voor root met params
|
||
// en anders iets in de /appl folder. Andere redirects kennen we niet
|
||
if (return_to != "/" &&
|
||
!return_to.match(/^\/\?/i) &&
|
||
!return_to.match(/^\/appl\/?/i)
|
||
)
|
||
{
|
||
__DoLog("Invalid return_to: " + return_to, "#f00");
|
||
return_to = "/";
|
||
}
|
||
// Ga weer helemaal terug naar de pagina waar je mee begon.
|
||
// Ook mooi als iemand er een bookmark naar legt.
|
||
Response.Redirect(rooturl + return_to);
|
||
}
|
||
}
|
||
}
|
||
|
||
var sso = getQParam("sso", "");
|
||
if (user_key < 0 && sso && sso != "0") // "0" is een hardcoded special case
|
||
trySSO(sso); // keert niet terug bij geldige ssocode
|
||
|
||
if (user_key < 0)
|
||
{
|
||
if (Session("fallback_user_key") > 0) // (QRC) bookmark met fallback user_key
|
||
{
|
||
__Log("Login by fallback_user_key {0}".format(Session("fallback_user_key")));
|
||
doLogin(Session("fallback_user_key"), { noFacSession: true });// gezet in Shorturl.asp
|
||
Session("login_by_fallback") = true; // fac_like_deep.asp wist dan sessie
|
||
Session.Contents.Remove("fallback_user_key");
|
||
}
|
||
}
|
||
|
||
// Pas h<><68>l laat api_user_key zetten om te voorkomen dat je
|
||
// bestaande sessie ongeldig wordt (Vinder/ telefoongids)
|
||
// JGL (later) maar volgens mij komt je dan hier helemaal niet dus is het niet echt relevant
|
||
var APIname = getQParam("API", "");
|
||
if (user_key < 0 && APIname)
|
||
{
|
||
var API = new API_func(); // controleert vanzelf
|
||
|
||
if (API.apidata.prs_perslid_key)
|
||
user_key = API.apidata.prs_perslid_key;
|
||
}
|
||
|
||
// LogOff.asp kan Session("no_sso") gezet hebben
|
||
// Ook: met &sso=0
|
||
if (Request.QueryString("sso") == "0")
|
||
Session("no_sso") = 1;
|
||
|
||
// Integrated authentication?
|
||
if (user_key < 0 && S("os_logon")
|
||
&& typeof Session("no_sso") == "undefined"
|
||
&& !Request.ServerVariables("HTTP_X_FACILITOR_API_KEY").Count
|
||
&& !Request.QueryString("APIKEY").Count)
|
||
{
|
||
var extern=false;
|
||
var i;
|
||
for (var i in S("os_logon_exclude")) // via proxy binnen?
|
||
{
|
||
if (Request.ServerVariables(S("os_logon_exclude")[i]).count>0)
|
||
extern = true;
|
||
}
|
||
if (!extern)
|
||
IntegratedSSO(); // Voor licentieklanten
|
||
}
|
||
|
||
//if (user_key < 0)
|
||
// trySSO("DEFAULT"); // zal je standaard naar het loginscherm sturen
|
||
|
||
if (user_key > 0)
|
||
{ // gelukt, teruggeven aan aanroeper
|
||
Session("user_key") = user_key;
|
||
}
|
||
__Log("== Leaving loginTry.asp ==");
|
||
|
||
%> |