diff --git a/APPL/API2/model_fac_idp.inc b/APPL/API2/model_fac_idp.inc new file mode 100644 index 0000000000..8d361ac803 --- /dev/null +++ b/APPL/API2/model_fac_idp.inc @@ -0,0 +1,132 @@ +<% /* + $Revision$ + $Id$ + + File: model_fac_idp.inc + Description: + Notes: Documentatie in de wiki onder Authenticeren +*/ + +function fac_idp() +{ + this.table = "fac_idp"; + this.primary = "fac_idp_key"; + this.records_name = "idps"; + this.record_name = "idp"; + this.autfunction = "WEB_FACFAC"; + this.record_title = L("fac_idp"); + this.records_title = L("fac_idp_m"); + + this.fields = { + "id": { + "dbs": "fac_idp_key", + "label": "Key", + "typ": "key", + "seq": "fac_s_fac_idp_key" + }, + "code": { + "dbs": "fac_idp_code", + "label": L("fac_idp_code"), + "typ": "varchar" + }, + "name": { + "dbs": "fac_idp_omschrijving", + "label": L("fac_idp_omschrijving"), + "typ": "varchar", + "required": true + }, + "type": { + "dbs": "fac_idp_type", + "label": L("fac_idp_type"), + "typ": "key", + "required": true, + "LOV": L("fac_idp_typeLOV") + }, + "remark": { + "dbs": "fac_idp_opmerking", + "label": L("fac_idp_opmerking"), + "typ": "memo" + }, + "secret": { + "dbs": "fac_idp_secret", + "label": L("fac_idp_secret"), + "typ": "varchar" + }, + "audience": { + "dbs": "fac_idp_audience", + "label": L("fac_idp_audience"), + "typ": "varchar", + "placeholder": customerId + ".facilitor.nl" + }, + "issuer": { + "dbs": "fac_idp_issuer", + "label": L("fac_idp_issuer"), + "typ": "varchar" + }, + "algorithm": { + "dbs": "fac_idp_algorithm", + "label": L("fac_idp_algorithm"), + "typ": "varchar" + }, + "timeout": { + "dbs": "fac_idp_timeout", + "label": L("fac_idp_timeout"), + "typ": "number" + }, + "remote_loginurl": { + "dbs": "fac_idp_remote_loginurl", + "label": L("fac_idp_remote_loginurl"), + "typ": "varchar" + }, + "remote_logouturl": { + "dbs": "fac_idp_remote_logouturl", + "label": L("fac_idp_remote_logouturl"), + "typ": "varchar" + }, + "usermapping": { + "dbs": "fac_idp_usermapping", + "label": L("fac_idp_usermapping"), + "typ": "varchar" + }, + "ipfilter": { + "dbs": "fac_idp_ipfilter", + "label": L("fac_idp_ipfilter"), + "typ": "varchar" + }, + "ipauto": { + "dbs": "fac_idp_ipauto", + "label": L("fac_idp_ipauto"), + "typ": "check0" + }, + "company": { + "dbs": "prs_bedrijf_key", + "typ": "key", + "foreign": "prs_bedrijf", + "label": L("lcl_idp_company") + }, + "department": { + "dbs": "prs_afdeling_key", + "typ": "key", + "foreign": "prs_afdeling", + "label": L("lcl_idp_department") + }, + "authorization": { + "dbs": "fac_functie_key", + "label": L("fac_idp_functie_key"), + "typ": "key", + "foreign": fac_functie_foreign() + }, + "internal": { + "dbs": "fac_idp_internal", + "label": L("fac_idp_internal"), + "typ": "check0", + "readonly": true + } + } + + this.REST_GET = generic_REST_GET(this); + this.REST_POST = generic_REST_POST(this); + this.REST_PUT = generic_REST_PUT(this); + this.REST_DELETE = generic_REST_DELETE(this); +} +%> \ No newline at end of file diff --git a/APPL/FAC/header.inc b/APPL/FAC/header.inc index 8f3dc8d7ac..a78d36e106 100644 --- a/APPL/FAC/header.inc +++ b/APPL/FAC/header.inc @@ -166,7 +166,7 @@ function generateHeaderFunctions (params) function logOffCallback(json, textStatus) { - parent.location.href="<%=S("logoff_return_url")%>"; + parent.location.href = json.return_url; }; function logOff() diff --git a/APPL/MGT/fac_idp.asp b/APPL/MGT/fac_idp.asp new file mode 100644 index 0000000000..5eb36fe586 --- /dev/null +++ b/APPL/MGT/fac_idp.asp @@ -0,0 +1,42 @@ +<%@language = "javascript" %> +<% /* + $Revision$ + $Id$ + + File: fac_idp.asp + + Description: + + Context: + + Notes: +*/ +%> + + + +<% +var this_model = new fac_idp(); + +scaffolding(this_model, + { + "search": { + "autosearch": true, + "filters": [ + "name", + "action" + ] + }, + "list": { + "columns": [ + "id", + "name", + "type", + "remote_loginurl" + ] + }, + "edit": { + "modal": false + } + }); +%> diff --git a/APPL/Shared/Common.inc b/APPL/Shared/Common.inc index 6af8d857cc..786593b0d7 100644 --- a/APPL/Shared/Common.inc +++ b/APPL/Shared/Common.inc @@ -251,7 +251,7 @@ if (user_key < 0 && typeof ANONYMOUS_Allowed == "undefined") } var url = Session("unauth_url") || S("login_url"); // unauth_url uit shorturl.asp - if (getQParamInt("sso", -1) == 0) // forceer de default + if (getQParam("sso", "") == "0") // forceer de default url = 'appl/shared/login.asp'; if (!url.match(/^http/)) diff --git a/APPL/Shared/LogOff.asp b/APPL/Shared/LogOff.asp index 645463638e..9e611eaa4d 100644 --- a/APPL/Shared/LogOff.asp +++ b/APPL/Shared/LogOff.asp @@ -15,11 +15,23 @@ var JSON_Result = true; <% protectRequest.validateToken(); -var result = { success: true }; +var result = { success: true, + return_url: S("logoff_return_url") + }; // FACFAC tracken we altijd if (user.has("WEB_FACFAC")) shared.trackaction("PRSLOG", user_key, L("lcl_logged_off").format(Session("ASPFIXATION").slice(-6))); +if (Session("idp_key") > 0) +{ + var sql = "SELECT fac_idp_remote_logouturl" + + " FROM fac_idp" + + " WHERE fac_idp_key = " + Session("idp_key"); + var oRs = Oracle.Execute(sql); + if (oRs("fac_idp_remote_logouturl").Value) + result.return_url = oRs("fac_idp_remote_logouturl").Value; +} + if (Session("org_user_key") > 0) { var was_key = user_key; diff --git a/APPL/Shared/Login.inc b/APPL/Shared/Login.inc index 71730fef80..b71b027fd1 100644 --- a/APPL/Shared/Login.inc +++ b/APPL/Shared/Login.inc @@ -586,9 +586,9 @@ function SecureSSO(ssoProps) strReturnURL= strReturnURL.replace("<", ""); strReturnURL= strReturnURL.replace(">", ""); strAction = getFParam("action", ""); - if (!strAction && ssoProps.sso > 0) // we zijn begonnen in Facilitor + if (!strAction && ssoProps.ssoURL) // we zijn begonnen in Facilitor en moeten nog naar de klant { - strReturnURL = ssoProps.sso==1?S("sso_advanced_url"):S("sso_advanced_url_alt"); + strReturnURL = ssoURL; if (!strReturnURL) { __DoLog("Secure SSO login error 0"); @@ -867,6 +867,90 @@ function IntegratedSSO() tryLogin(username,null); } } + +/* resultaat: + { err: "Iets niet goed" } + of { header: header, + payload: payload (claim) + signature: signature + } + LET OP: signature is nog niet gevalideerd! +*/ +function jwt_decode(token) +{ + // check token + if (!token) { + return { err: 'No token supplied' }; + } + // check segments + var segments = token.split('.'); + if (segments.length !== 3) { + return { err: 'Not enough or too many segments' }; + } + + // All segment should be base64 + var result = { headerSeg: segments[0], + payloadSeg: segments[1], + signature64: segments[2] + } + + var oCrypto = new ActiveXObject("SLNKDWF.Crypto"); + + try + { + // base64 decode and parse JSON + result.header = JSON.parse(oCrypto.base64_decode(result.headerSeg)); + result.payload = JSON.parse(oCrypto.base64_decode(result.payloadSeg)); + } + catch (s) + { + return { err: "Invalid JSON: " + e.description }; + } + + var now = new Date().getTime() / 1000; + + // Support for nbf and exp claims. + // According to the RFC, they should be in seconds. + if (result.payload.nbf && now < result.payload.nbf) { + return { err: 'Token not yet active' }; + } + + if (result.payload.exp && now > result.payload.exp) { + return { err: 'Token expired' }; + } + + return result; +}; + +function jwt_verify(decoded_jwt, secret, skew) +{ + if (decoded_jwt.header.alg != "HS256") + return { err: "Only HS256 is supported" }; + + var oCrypto = new ActiveXObject("SLNKDWF.Crypto"); + var sig = oCrypto.hex_hmac_sha256(secret, decoded_jwt.headerSeg + "." + decoded_jwt.payloadSeg); + var sig64 = oCrypto.hex2base64(sig, false, true); // no padding, urlsafe + + var now = new Date().getTime() / 1000; + if (claim.payload.iat) + { + var from = now - skew; + var to = now + skew; + if (claim.payload.iat < from) { + __DoLog("Token expired. Now is {0}, got {1}".format(toDateTimeString(new Date(now * 1000), true), toDateTimeString(new Date(claim.payload.iat * 1000), true))); + return { err: 'Token expired' }; + } + if (claim.payload.iat > to) { + __DoLog("Token not yet active. Now is {0}, got {1}".format(toDateTimeString(new Date(now * 1000), true), toDateTimeString(new Date(claim.payload.iat * 1000), true))); + return { err: 'Token not yet active' }; + } + } + if (decoded_jwt.signature64 == sig64) + return { success: true } + + return { err: "Token signature did not verify" }; +} + %>