DJIN#36213 SAML/Authenticatie verbeteringen.

svn path=/Website/trunk/; revision=33179
This commit is contained in:
Jos Groot Lipman
2017-03-16 19:46:30 +00:00
parent 79f50d2716
commit f488ba11bc
10 changed files with 590 additions and 103 deletions

View File

@@ -732,10 +732,28 @@ api2 = {
switch (field.typ) switch (field.typ)
{ {
case "key": // De foreign keys action { "id": "5", "name": "afhalen" } case "key": // De foreign keys action { "id": "5", "name": "afhalen" }
if (newval && typeof newval == "object" && "id" in newval) if (newval && typeof newval == "object")
{ // dereference {
newval = newval.id; if ("id" in newval)
jsondata[fld] = newval; { // dereference
newval = newval.id;
jsondata[fld] = newval;
}
else if ("name" in newval && field.foreign && typeof field.foreign != 'function')
{
if (typeof field.foreign == 'string')
{
field.foreign = foreignKeyTable(field.foreign);
}
if (field.foreign.desc_is_unique) // Dan mag je die bij saven ook opgeven
{
field.typ = "sql";
newval = "(SELECT {0} FROM {1} WHERE {2} = {3})".format(field.foreign.key,
field.foreign.tbl,
field.foreign.desc,
safe.quoted_sql(newval.name));
}
}
} }
break; break;
case "date": case "date":
@@ -1433,8 +1451,10 @@ function generic_REST_POST(model, gparams)
{ {
params.isNew = true; // negeer eventuele bestaande keys params.isNew = true; // negeer eventuele bestaande keys
if (model.autfunction !== false) if (model.autfunction !== false)
{
var autparams = user.checkAutorisation(model.autfunction); var autparams = user.checkAutorisation(model.autfunction);
user.auth_required_or_abort(autparams.PRSwritelevel < 9 && autparams.ALGwritelevel < 9); user.auth_required_or_abort(autparams.PRSwritelevel < 9 && autparams.ALGwritelevel < 9);
}
if ("disc_params" in model) if ("disc_params" in model)
{ {
@@ -1496,8 +1516,10 @@ function generic_REST_PUT(model, gparams)
return function _generic_REST_PUT(params, jsondata, the_key) return function _generic_REST_PUT(params, jsondata, the_key)
{ {
if (model.autfunction !== false) if (model.autfunction !== false)
{
var autparams = user.checkAutorisation(model.autfunction); var autparams = user.checkAutorisation(model.autfunction);
user.auth_required_or_abort(autparams.PRSwritelevel < 9 && autparams.ALGwritelevel < 9); user.auth_required_or_abort(autparams.PRSwritelevel < 9 && autparams.ALGwritelevel < 9);
}
if ("disc_params" in model) if ("disc_params" in model)
{ {
@@ -1524,6 +1546,8 @@ function generic_REST_PUT(model, gparams)
if (err.friendlyMsg) if (err.friendlyMsg)
abort_with_warning(err.friendlyMsg); abort_with_warning(err.friendlyMsg);
var inctrack = api2.process_includes(params, this, jsondata, the_key);
if ("disc_params" in model) if ("disc_params" in model)
{ {
// Nu de one-on-one tabel // Nu de one-on-one tabel
@@ -1546,8 +1570,10 @@ function generic_REST_DELETE(model, gparams)
return function _generic_REST_DELETE(params, the_key) return function _generic_REST_DELETE(params, the_key)
{ {
if (model.autfunction !== false) if (model.autfunction !== false)
{
var autparams = user.checkAutorisation(model.autfunction); var autparams = user.checkAutorisation(model.autfunction);
user.auth_required_or_abort(autparams.PRSwritelevel < 9 && autparams.ALGwritelevel < 9); user.auth_required_or_abort(autparams.PRSwritelevel < 9 && autparams.ALGwritelevel < 9);
}
if (model.soft_delete) if (model.soft_delete)
{ {

View File

@@ -7,6 +7,9 @@
Notes: Documentatie in de wiki onder Authenticeren Notes: Documentatie in de wiki onder Authenticeren
*/ */
%>
<!-- #include file="./model_fac_idp_map.inc" -->
<%
function fac_idp() function fac_idp()
{ {
this.records_name = "identityproviders"; this.records_name = "identityproviders";
@@ -17,6 +20,8 @@ function fac_idp()
this.record_title = L("fac_idp"); this.record_title = L("fac_idp");
this.records_title = L("fac_idp_m"); this.records_title = L("fac_idp_m");
this.askfirst = "type";
this.fields = { this.fields = {
"id": { "id": {
"dbs": "fac_idp_key", "dbs": "fac_idp_key",
@@ -40,6 +45,7 @@ function fac_idp()
"label": L("fac_idp_type"), "label": L("fac_idp_type"),
"typ": "key", "typ": "key",
"required": true, "required": true,
"insertonly": true,
"LOV": L("fac_idp_typeLOV") "LOV": L("fac_idp_typeLOV")
}, },
"remark": { "remark": {
@@ -107,21 +113,26 @@ function fac_idp()
"label": L("fac_idp_ipauto"), "label": L("fac_idp_ipauto"),
"typ": "check0" "typ": "check0"
}, },
/* "autocreate": {
"dbs": "fac_idp_autocreate",
"label": L("fac_idp_autocreate"),
"typ": "key",
"required": "true",
"LOV": "0;Weigeren bij onbekend;1;Aanmaken;2;Alleen bijwerken;3;Aanmaken en bijwerken" ///L("fac_idp_autocreateLOV")
},
"company": { "company": {
"dbs": "prs_bedrijf_key", "dbs": "prs_bedrijf_key",
"typ": "key", "typ": "key",
"foreign": "prs_bedrijf", "foreign": "prs_bedrijf",
"label": L("lcl_idp_company") "label": L("lcl_idp_company")
} },
,
"department": { "department": {
"dbs": "prs_afdeling_key", "dbs": "prs_afdeling_key",
"typ": "key", "typ": "key",
"foreign": "prs_afdeling", "foreign": "prs_afdeling",
"label": L("lcl_idp_department") "label": L("lcl_idp_department")
}, },
"authorization": { /* "authorization": {
"dbs": "fac_functie_key", "dbs": "fac_functie_key",
"label": L("fac_idp_functie_key"), "label": L("fac_idp_functie_key"),
"typ": "key", "typ": "key",
@@ -135,6 +146,12 @@ function fac_idp()
"readonly": true "readonly": true
} }
} }
this.includes =
{"idpmappings": { model: new model_fac_idp_map(),
joinfield: "identityprovider",
enable_update: true
}
};
this.REST_GET = generic_REST_GET(this); this.REST_GET = generic_REST_GET(this);
this.REST_POST = generic_REST_POST(this); this.REST_POST = generic_REST_POST(this);

View File

@@ -0,0 +1,72 @@
<% /*
$Revision$
$Id$
File: model_fac_idp_map.inc
Description:
Notes:
*/
function model_fac_idp_map()
{
this.records_name = "idpmappings";
this.record_name = "idpmapping";
this.table = "fac_idp_map";
this.primary = "fac_idp_map_key";
this.autfunction = "WEB_FACFAC";
this.record_title = L("fac_idp_map");
this.records_title = L("fac_idp_map_m");
this.fields = {
"id": {
"dbs": "fac_idp_map_key",
"label": L("lcl_key"),
"typ": "key",
"seq": "fac_s_fac_idp_map_key"
},
"identityprovider": {
"dbs": "fac_idp_key",
"label": L("fac_idp"),
"typ": "key",
"hidden_fld": true,
"required": true
},
"identify": {
"dbs": "fac_idp_map_identify",
"label": L("fac_idp_map_identify"),
"typ": "check0"
},
"name": {
"dbs": "fac_idp_map_to",
"label": L("fac_idp_map_to"),
"typ": "key",
"required": true,
"LOV": "1;Login;2;Achternaam;3;Voornaam;4;E-mail;5;Afdeling;6;Kostenplaats;7;Functie;100;*Werkplekken;101;*Authorisatiegroepen" ///L("fac_idp_map_toLOV")
},
"from": {
"dbs": "fac_idp_map_from",
"label": L("fac_idp_map_from"),
"typ": "varchar",
"required": true
},
"default": {
"dbs": "fac_idp_map_default",
"label": L("fac_idp_map_default"),
"typ": "varchar"
}
}
this.edit = {
"modal": true
};
this.list = {
"columns": ["identify", "name", "from", "default"]
};
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);
}
%>

159
APPL/API2/model_fac_sp.inc Normal file
View File

@@ -0,0 +1,159 @@
<% /*
$Revision$
$Id$
File: model_fac_sp.inc
Description:
Notes:
*/
%>
<!-- #include file="./model_fac_sp_map.inc" -->
<%
function fac_sp()
{
this.records_name = "identityproviders";
this.record_name = "identityprovider";
this.table = "fac_sp";
this.primary = "fac_sp_key";
this.autfunction = "WEB_FACFAC";
this.record_title = L("fac_sp");
this.records_title = L("fac_sp_m");
this.fields = {
"id": {
"dbs": "fac_sp_key",
"label": L("lcl_key"),
"typ": "key",
"seq": "fac_s_fac_sp_key"
},
"code": {
"dbs": "fac_sp_code",
"label": L("fac_sp_code"),
"typ": "varchar"
},
"name": {
"dbs": "fac_sp_omschrijving",
"label": L("fac_sp_omschrijving"),
"typ": "varchar",
"required": true
},
"type": {
"dbs": "fac_sp_type",
"label": L("fac_sp_type"),
"typ": "key",
"required": true,
"LOV": L("fac_idp_typeLOV") // TODO?
},
"remark": {
"dbs": "fac_sp_opmerking",
"label": L("fac_sp_opmerking"),
"typ": "memo"
},
"secret": {
"dbs": "fac_sp_secret",
"label": L("fac_sp_secret"),
"typ": "varchar",
"defaultvalue": shared.random(32),
"secret": true
},
"audience": {
"dbs": "fac_sp_audience",
"label": L("fac_sp_audience"),
"typ": "varchar",
"placeholder": customerId + ".facilitor.nl"
},
"issuer": {
"dbs": "fac_sp_issuer",
"label": L("fac_sp_issuer"),
"typ": "varchar"
},
"algorithm": {
"dbs": "fac_sp_algorithm",
"label": L("fac_sp_algorithm"),
"typ": "varchar"
},
"timeout": {
"dbs": "fac_sp_clockskew",
"label": L("fac_sp_clockskew"),
"typ": "number",
"defaultvalue": 30
},
"duration": {
"dbs": "fac_sp_duration",
"label": L("fac_sp_duration"),
"typ": "number"
},
"remoteloginurl": {
"dbs": "fac_sp_remote_loginurl",
"label": L("fac_sp_remote_loginurl"),
"typ": "varchar"
},
"remotelogouturl": {
"dbs": "fac_sp_remote_logouturl",
"label": L("fac_sp_remote_logouturl"),
"typ": "varchar"
},
"usermapping": {
"dbs": "fac_sp_usermapping",
"label": L("fac_sp_usermapping"),
"typ": "varchar"
},
"ipfilter": {
"dbs": "fac_sp_ipfilter",
"label": L("fac_sp_ipfilter"),
"typ": "varchar"
},
"_currentIP" : {
"dbs": "",
"label": "Current IP",
"typ": "label",
"labelvalue": String(Request.ServerVariables("REMOTE_ADDR"))
},
"ipauto": {
"dbs": "fac_sp_ipauto",
"label": L("fac_sp_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_sp_functie_key"),
"typ": "key",
"foreign": "fac_functie"
},
*/
"internal": {
"dbs": "fac_sp_internal",
"label": L("fac_sp_internal"),
"typ": "check0",
"readonly": true
}
}
this.includes =
{"spmappings": { model: new model_fac_sp_map(),
joinfield: "serviceprovider",
enable_update: 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);
}
%>

View File

@@ -0,0 +1,71 @@
<% /*
$Revision$
$Id$
File: model_fac_sp_map.inc
Description: Door sp 'released attributes'
Notes:
*/
function model_fac_sp_map()
{
this.records_name = "idpappings";
this.record_name = "idpapping";
this.table = "fac_sp_map";
this.primary = "fac_sp_map_key";
this.autfunction = "WEB_FACFAC";
this.record_title = L("fac_sp_map");
this.records_title = L("fac_sp_map_m");
this.fields = {
"id": {
"dbs": "fac_sp_map_key",
"label": L("lcl_key"),
"typ": "key",
"seq": "fac_s_fac_sp_map_key"
},
"serviceprovider": {
"dbs": "fac_sp_key",
"label": L("fac_sp"),
"typ": "key",
"hidden_fld": true,
"required": true
},
"name": {
"dbs": "fac_sp_map_from",
"label": L("fac_sp_map_from"),
"typ": "key",
"required": true,
"LOV": "1;" + L("lcl_prs_person_login")
+ ";2;" + L("lcl_prs_person_achternaam")
+ ";3;" + L("lcl_prs_person_voornaam")
+ ";4;" + L("lcl_prs_person_email")
+ ";5;" + L("lcl_prs_organisatie")
+ ";6;" + L("lcl_account")
+ ";7;" + L("lcl_prs_person_function")
+ ";8;" + L("lcl_lcl_taal")
+ ";100;" + L("lcl_workplace")
+ ";101;" + L("fac_groeprechten_m")
},
"to": {
"dbs": "fac_sp_map_to",
"label": L("fac_sp_map_to"),
"typ": "varchar",
"required": true
}
}
this.edit = {
"modal": true
};
this.list = {
"columns": ["name", "to"]
};
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);
}
%>

View File

@@ -33,7 +33,7 @@ function genderLOV()
return s; return s;
} }
function model_persons() function model_prs_perslid()
{ {
this.records_name = "persons"; this.records_name = "persons";
this.record_name = "person"; this.record_name = "person";
@@ -55,14 +55,14 @@ function model_persons()
this.primary = "prs_perslid_key"; this.primary = "prs_perslid_key";
this.record_title = L("prs_perslid"); this.record_title = L("prs_perslid");
this.records_title = L("prs_perslid_m"); this.records_title = L("prs_perslid_m");
this.autfunction = false; // we controleren zelf
this.fields = { this.fields = {
"id": { "id": {
"dbs": "prs_perslid_key", "dbs": "prs_perslid_key",
"label": L("lcl_key"), "label": L("lcl_key"),
"typ": "key", "typ": "key",
"filter": "exact" "seq": "prs_s_prs_alluitvoerende_keys"
}, },
"name": { "name": {
"dbs": "pf.prs_perslid_naam_friendly", "dbs": "pf.prs_perslid_naam_friendly",
@@ -152,13 +152,15 @@ function model_persons()
"foreign": { "foreign": {
"tbl": "prs_srtperslid", "tbl": "prs_srtperslid",
"key": "prs_srtperslid_key", "key": "prs_srtperslid_key",
"desc": "prs_srtperslid_omschrijving" "desc": "prs_srtperslid_omschrijving",
"desc_is_unique": true
} }
}, },
"department": { "department": {
"dbs": "prs_afdeling_key", "dbs": "prs_afdeling_key",
"label": L("lcl_prs_organisatie"), "label": L("lcl_prs_organisatie"),
"typ": "key", "foreign": "prs_afdeling" "typ": "key",
"foreign": "prs_afdeling"
}, },
"company": { "company": {
"dbs": "pa.prs_bedrijf_key", "dbs": "pa.prs_bedrijf_key",
@@ -198,7 +200,6 @@ function model_persons()
"model": new model_fac_gebruikersgroep(), "model": new model_fac_gebruikersgroep(),
"joinfield": "person", "joinfield": "person",
"multiadd": "authorizationgroup" "multiadd": "authorizationgroup"
}, },
"customfields" : { "customfields" : {
"model": new model_custom_fields(this, "PRS", { readman: true, readuse: true, pNiveau: "P" }), "model": new model_custom_fields(this, "PRS", { readman: true, readuse: true, pNiveau: "P" }),
@@ -274,17 +275,9 @@ function model_persons()
return json; return json;
}; };
this.PUT = function (params) /* update perslid */
{ this.REST_POST = generic_REST_POST(this);
// Nog niet ondersteund this.REST_PUT = generic_REST_PUT(this);
}; this.REST_DELETE = generic_REST_DELETE(this);
this.POST = function (params) /* new perslid */
{
// Nog niet ondersteund
};
this.DELETE = function (params) /* delete perslid */
{
// Nog niet ondersteund
};
} }
%> %>

View File

@@ -42,14 +42,14 @@ function doLogin(prs_key, params)
if (deze.has("WEB_FACFAC") && !params.isFACFACinternal) if (deze.has("WEB_FACFAC") && !params.isFACFACinternal)
{ {
__DoLog("Illegal login WEB_FACFAC"); __DoLog("Illegal login WEB_FACFAC");
shared.internal_error("This IDP cannot be used for users with WEB_FACFAC (prs_key={0}).".format(prs_key)); shared.internal_error("IDP '{0}' cannot be used for users with WEB_FACFAC (prs_key={1}).".format(params.idp_code, prs_key));
} }
// Als fac_idp_internal aan staat mag alleen je alleen SSO doen naar een FACFAC gebruiker // Als fac_idp_internal aan staat mag alleen je alleen SSO doen naar een FACFAC gebruiker
// Tenzij S("idp_internal_anyuser") true is, dan mag je toch naar iedereen // Tenzij S("idp_internal_anyuser") true is, dan mag je toch naar iedereen
// Dat doen we op OTA via custenc.wsc, dat doen we niet in PROD // Dat doen we op OTA via custenc.wsc, dat doen we niet in PROD
if (params.isFACFACinternal && !S("idp_internal_anyuser") && !deze.has("WEB_FACFAC")) if (params.isFACFACinternal && !S("idp_internal_anyuser") && !deze.has("WEB_FACFAC"))
{ {
shared.internal_error("This IDP can only be used for users with WEB_FACFAC (prs_key={0}).".format(prs_key)); shared.internal_error("IDP '{0}' can only be used for users with WEB_FACFAC (prs_key={1}).".format(params.idp_code, prs_key));
} }
} }
@@ -958,90 +958,107 @@ function IntegratedSSO()
} }
// aud is identificatie van de partij die de informatie *wil weten* // aud is identificatie van de partij die de informatie *wil weten*
// of het is een hash van usermapping, iss, aud en secret function jwt_create(perslid_key, aud)
// dat gebruiken we hardcoded vanuit login_save.asp
function jwt_create(perslid_key, aud_or_prop)
{ {
var thisPrs = new Perslid(perslid_key) var thisPrs = new Perslid(perslid_key)
var params = aud_or_prop; var params = aud_or_prop;
if (typeof aud_or_prop == "string") // dan is het een audience naam var sp_key = -1;
{
var sql = "SELECT *" var sql = "SELECT *"
+ " FROM fac_sp" + " FROM fac_sp"
+ " WHERE fac_sp_audience = " + safe.quoted_sql(aud); // TODO ook issuer meenemen? + " WHERE fac_sp_audience = " + safe.quoted_sql(aud); // TODO ook issuer meenemen?
var oRs = Oracle.Execute(sql); var oRs = Oracle.Execute(sql);
if (oRs.Eof) if (oRs.Eof)
shared.internal_error("Service provider for '{0}' is not configured for {1}".format(aud, customerId)); shared.internal_error("Service provider for '{0}' is not configured for {1}".format(aud, customerId));
params = { sp_key = oRs("fac_sp_key").value;
var params = {
usermapping: oRs("fac_sp_usermapping").Value, usermapping: oRs("fac_sp_usermapping").Value,
iss: oRs("fac_sp_issuer").Value, iss: oRs("fac_sp_issuer").Value,
aud: aud, aud: aud,
secret: oRs("fac_sp_secret").Value secret: oRs("fac_sp_secret").Value
}; };
oRs.Close(); oRs.Close();
}
var claim = var claim =
{ {
jti: "#" + (perslid_key) + "#" + new Date().getTime() jti: "#" + (perslid_key) + "#" + new Date().getTime(),
iat: Math.round(new Date().getTime() / 1000),
iss: params.iss,
aud: params.aud
} }
// usermapping bevat de attributen die wij vrijgeven voor deze SP // fac_sp_map bevat de attributen die wij vrijgeven voor deze SP
// Het kunnen er meerdere zijn gescheiden door een komma.
// Het is telkens in het formaat 'username->username' waarbij de linker if (sp_key > 0)
// usernaam onze interne code is (zie verderop de switch) en de rechter
// username hoe hij in de jwt genoemd wordt. Als ze gelijk zijn volstaat
// gewoon 'username'
// TODO: Beter gewoon JSON formaat doen?
var usermapping = params.usermapping || "preferred_username->username";
var arr = usermapping.split(",");
for (var i = 0; i < arr.length; i++)
{ {
var spl = arr[i].split('->'); var sql = "SELECT *"
var attr = spl[0]; + " FROM fac_sp_map"
if (spl.length > 1) + " WHERE fac_sp_key = " + sp_key;
var clm = spl[1] var oRs = Oracle.Execute(sql);
else while (!oRs.Eof)
clm = attr;
switch (attr)
{ {
// Zo veel mogelijk volgens http://openid.net/specs/openid-connect-basic-1_0.html#StandardClaims var clm = oRs("fac_sp_map_to").Value; // zo gaat hij heten in de JWT
case "preferred_username": switch (oRs("fac_sp_map_from").Value) // zie model_fac_sp_map.inc voor codering
claim[clm] = thisPrs.oslogin(); {
break; // Zo veel mogelijk volgens http://openid.net/specs/openid-connect-basic-1_0.html#StandardClaims
case "sub": claim[clm] = String(perslid_key); // Als enige gegarandeerd en blijvend uniek voor deze issuer case 1: claim[clm] = thisPrs.oslogin();
break; // http://openid.net/specs/openid-connect-basic-1_0.html#ClaimStability break;
case "given_name": claim[clm] = thisPrs.prs_perslid_voornaam(); case "sub": claim[clm] = String(perslid_key); // Als enige gegarandeerd en blijvend uniek voor deze issuer
break; break; // http://openid.net/specs/openid-connect-basic-1_0.html#ClaimStability
case "family_name": claim[clm] = thisPrs.prs_perslid_achternaam(); case 3: claim[clm] = thisPrs.prs_perslid_voornaam();
break; break;
case "middle_name": claim[clm] = thisPrs.prs_perslid_tussenvoegsel(); case 2: claim[clm] = thisPrs.prs_perslid_achternaam();
break; break;
case "name": claim[clm] = thisPrs.naam(); // case "middle_name": claim[clm] = thisPrs.prs_perslid_tussenvoegsel();
break; // break;
case "email": claim[clm] = thisPrs.prs_perslid_email(); // case "name": claim[clm] = thisPrs.naam();
break; // break;
case "gender": claim[clm] = { "0": "female", "1": "male" }[thisPrs.prs_perslid_geslacht()] || ""; case 4: claim[clm] = thisPrs.prs_perslid_email();
break; break;
case "locale": claim[clm] = { "nl": "nl-NL", // RFC5646 // case "gender": claim[clm] = { "0": "female", "1": "male" }[thisPrs.prs_perslid_geslacht()] || "";
"en": "en-GB", // break;
"de": "de-DE", case "locale": claim[clm] = { "nl": "nl-NL", // RFC5646
"fr": "fr-FR", "en": "en-GB",
"no": "nn-NO", "de": "de-DE",
"sv": "sv-SE", "fr": "fr-FR",
"da": "da-DK", "no": "nn-NO",
"fi": "fi-FI" }[String(thisPrs.dblang()).toLowerCase()] || ""; "sv": "sv-SE",
break; "da": "da-DK",
case "zoneinfo": claim[clm] = thisPrs.prs_perslid_timezone(); "fi": "fi-FI" }[String(thisPrs.dblang()).toLowerCase()] || "";
break; break;
// case "zoneinfo": claim[clm] = thisPrs.prs_perslid_timezone();
// break;
// de custom claims
case 101: /* fclt_authorization */
var sql = "SELECT fac_groep_omschrijving"
+ " FROM fac_gebruikersgroep fgg, fac_groep fg"
+ " WHERE fgg.fac_groep_key = fg.fac_groep_key"
+ " AND SUBSTR(fac_groep_omschrijving, 1, 1) <> '_'"
+ " AND prs_perslid_key = " + user_key;
var oRs2 = Oracle.Execute(sql);
var aarr = [];
while (!oRs2.Eof)
{
aarr.push(oRs2("fac_groep_omschrijving").value);
oRs2.MoveNext();
}
oRs2.Close();
claim[clm] = aarr.join("|");
break;
case 100: /* fclt_occupation */
var wps = user.werkplekken();
var warr = [];
for (var i2 = 0; i2 < wps.length; i2++)
warr.push(wps[i2].prs_werkplek_aanduiding());
claim[clm] = warr.join("|");
break;
}
oRs.MoveNext();
} }
oRs.Close();
} }
__Log(claim);
claim.iat = Math.round(new Date().getTime() / 1000);
claim.iss = params.iss;
claim.aud = params.aud;
return jwt_encode(claim, params.secret); return jwt_encode(claim, params.secret);
} }
@@ -1178,7 +1195,7 @@ function trySSO(ssocode)
} }
if (!ip_ok) if (!ip_ok)
shared.internal_error("IP {0} not allowed for this IDP".format(ip)); // TODO of 400 code forbidden? shared.internal_error("IP {0} not allowed for IDP '{0}'".format(ip, ssocode)); // TODO of 400 code forbidden?
if (oRs("fac_idp_type").Value == 3) // Oldstyle SecureSSO, die doet het verder zelf if (oRs("fac_idp_type").Value == 3) // Oldstyle SecureSSO, die doet het verder zelf
{ {

View File

@@ -24,6 +24,8 @@ if (Response.Expires > 0)
<!-- #include file="../Shared/common.inc" --> <!-- #include file="../Shared/common.inc" -->
<!-- #include file="./login.inc" --> <!-- #include file="./login.inc" -->
<!-- #include file="../api/api.inc" --> <!-- #include file="../api/api.inc" -->
<!-- #include file="../api2/api2.inc" -->
<!-- #include file="../api2/model_prs_perslid.inc" -->
<% <%
__Log("== Entering loginTry.asp =="); __Log("== Entering loginTry.asp ==");
@@ -137,6 +139,7 @@ if ((user_key < 0 || getQParamInt("jwtforce", 0) == 1) && jwt)
} }
// en claim.jit registreren/ controleren in fac_session // en claim.jit registreren/ controleren in fac_session
var idp_code = oRs("fac_idp_code").Value;
var isFACFACinternal = oRs("fac_idp_internal").Value != 0; var isFACFACinternal = oRs("fac_idp_internal").Value != 0;
if (isFACFACinternal && !claim.payload.fclt_realuser && !by_bearer) if (isFACFACinternal && !claim.payload.fclt_realuser && !by_bearer)
{ {
@@ -147,26 +150,111 @@ if ((user_key < 0 || getQParamInt("jwtforce", 0) == 1) && jwt)
if (claim.payload.username) // je mag username meegeven if (claim.payload.username) // je mag username meegeven
{ {
settings.overrule_setting("login_use_email", 0); settings.overrule_setting("login_use_email", 0);
tryLogin(claim.payload.username, null, { noPassword: true, noFacSession: by_bearer, isFACFACinternal: isFACFACinternal }); tryLogin(claim.payload.username, null, { noPassword: true, idp_code: idp_code, noFacSession: by_bearer, isFACFACinternal: isFACFACinternal });
if (user_key < 0) if (user_key < 0)
__DoLog("JWT Claimed username not found: {0}".format(claim.payload.username)) __DoLog("JWT Claimed username not found: {0}".format(claim.payload.username))
} }
if (user_key < 0 && claim.payload.email) // je mag email meegeven if (user_key < 0 && claim.payload.email) // je mag email meegeven
{ {
settings.overrule_setting("login_use_email", 1); settings.overrule_setting("login_use_email", 1);
tryLogin(claim.payload.email, null, { noPassword: true, noFacSession: by_bearer, isFACFACinternal: isFACFACinternal }); tryLogin(claim.payload.email, null, { noPassword: true, noFacSession: by_bearer, idp_code: idp_code, isFACFACinternal: isFACFACinternal });
if (user_key < 0) if (user_key < 0)
__DoLog("JWT Claimed email not found: {0}".format(claim.payload.email)) __DoLog("JWT Claimed email not found: {0}".format(claim.payload.email))
} }
if (user_key < 0 && claim.payload.perslid_key > 0) if (user_key < 0 && claim.payload.perslid_key > 0)
{ {
doLogin(claim.payload.perslid_key, { noFacSession: by_bearer, isFACFACinternal: isFACFACinternal }); // je mag ook key meegeven doLogin(claim.payload.perslid_key, { noFacSession: by_bearer, idp_code: idp_code, isFACFACinternal: isFACFACinternal }); // je mag ook key meegeven
if (user_key < 0) if (user_key < 0)
__DoLog("JWT Claimed perslid_key not found: {0}".format(claim.payload.perslid_key)) __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) 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 if (!oRs("fac_idp_duration").Value) // single use tokens wil ik niet weer zien
{ // ook al zijn ze alleen geldig van -clockskew tot +clockskew { // ook al zijn ze alleen geldig van -clockskew tot +clockskew
// Ongeldige lukken de volgende keer ook niet. Geldige wil ik niet weer zien // Ongeldige lukken de volgende keer ook niet. Geldige wil ik niet weer zien
@@ -191,6 +279,7 @@ if ((user_key < 0 || getQParamInt("jwtforce", 0) == 1) && jwt)
// Onthouden hoe je bent binnengekomen zodat logout naar logout_url kan leiden // Onthouden hoe je bent binnengekomen zodat logout naar logout_url kan leiden
Session("idp_key") = oRs("fac_idp_key").Value; Session("idp_key") = oRs("fac_idp_key").Value;
oRs.Close(); // nu niet meer nodig
if (claim.payload.fclt_realuser) if (claim.payload.fclt_realuser)
shared.trackaction("PRSLOG", user_key, L("lcl_logged_on_sso").format(claim.payload.fclt_realuser, Request.ServerVariables("REMOTE_ADDR"))); shared.trackaction("PRSLOG", user_key, L("lcl_logged_on_sso").format(claim.payload.fclt_realuser, Request.ServerVariables("REMOTE_ADDR")));

43
APPL/MGT/fac_sp.asp Normal file
View File

@@ -0,0 +1,43 @@
<%@language = "javascript" %>
<% /*
$Revision$
$Id$
File: fac_sp.asp
Description:
Context:
Notes:
*/
%>
<!-- #include file="../scf/scaffolding.inc" -->
<!-- #include file="../mgt/mgt_tools.inc" -->
<!-- #include file="../api2/model_fac_sp.inc" -->
<%
var this_model = new fac_sp();
scaffolding(this_model,
{
"search": {
"autosearch": true,
"filters": [
"name",
"action"
]
},
"list": {
"columns": [
"id",
"code",
"name",
"type",
"remoteloginurl"
]
},
"edit": {
"modal": false
}
});
%>

View File

@@ -16,7 +16,7 @@ if (mode == 'list')
{ {
Oracle.Execute("alter session set nls_comp = 'LINGUISTIC' NLS_SORT = 'BINARY_AI'"); // Zodat m<>ller gevonden wordt Oracle.Execute("alter session set nls_comp = 'LINGUISTIC' NLS_SORT = 'BINARY_AI'"); // Zodat m<>ller gevonden wordt
} }
var this_model = new model_persons(); var this_model = new model_prs_perslid();
scaffolding(this_model, scaffolding(this_model,
{ {