@@ -200,19 +200,32 @@ exports.onExecutePostLogin = async (event, api) => {
200200 } ;
201201 } ;
202202
203- // Process the access cache decision
203+ // Process the access cache decision.
204+ // Note that applications may be defined multiple times in the access rules.
205+ //
206+ // When access is granted, the AAL from the rule is used, meaning different
207+ // groups can be subjected to different MFA requirements.
208+ //
209+ // The one exception is that: if any apps say _no_ users nor groups should
210+ // have access, then we bail early.
204211 const access_decision = ( groups , access_rules , access_file_conf ) => {
205212 // This is used for authorized user/groups
206213 let authorized = false ;
207214
208215 // Defaut app requested aal to MEDIUM for all apps which do not have
209216 // this set in access file
210- let required_aal = "MEDIUM" ;
217+ const default_aal = "MEDIUM" ;
211218
212- const apps = access_rules . filter (
213- ( a ) =>
214- ( a . application . client_id ?? "" ) . indexOf ( event . client . client_id ) >= 0
215- ) ;
219+ // The AAL from the matched authorization rule is used.
220+ let required_aal ;
221+
222+ // Only look at rules which match our client_id.
223+ const apps = access_rules
224+ . filter (
225+ ( a ) =>
226+ ( a . application . client_id ?? "" ) . indexOf ( event . client . client_id ) >= 0
227+ )
228+ . map ( ( a ) => a . application ) ;
216229
217230 // Default deny for apps we don't define in
218231 // https://github.com/mozilla-iam/sso-dashboard-configuration/blob/master/apps.yml
@@ -221,68 +234,66 @@ exports.onExecutePostLogin = async (event, api) => {
221234 return deny ( "notingroup" ) ;
222235 }
223236
224- // Check users and groups.
225- for ( let i = 0 ; i < apps . length ; i ++ ) {
226- let app = apps [ i ] . application ;
237+ // XXX This needs to be fixed in the dashboard first. Empty users
238+ // or groups (length == 0) means no access in the dashboard
239+ // apps.yml world.
240+ const deny_all =
241+ apps . find (
242+ ( a ) =>
243+ a . authorized_users . length === 0 && a . authorized_groups . length === 0
244+ ) !== undefined ;
245+ if ( deny_all ) {
246+ console . log (
247+ `Access denied to ${ event . client . client_id } for user ` +
248+ `${ event . user . email } (${ event . user . user_id } )` +
249+ ` - this app denies ALL users and ALL groups")`
250+ ) ;
251+ return deny ( "notingroup" ) ;
252+ }
227253
254+ // Check users and groups.
255+ for ( const app of apps ) {
228256 //Handy for quick testing in dev (overrides access rules)
229257 //var app = {'client_id': 'pCGEHXW0VQNrQKURDcGi0tghh7NwWGhW', // This is testrp social-ldap-pwless
230258 // 'authorized_users': ['gdestuynder@mozilla.com'],
231259 // 'authorized_groups': ['okta_mfa'],
232260 // 'aal': 'LOW'
233261 // };
234262
235- if ( app . client_id && app . client_id . indexOf ( event . client . client_id ) >= 0 ) {
236- // If there are multiple applications in apps.yml with the same
237- // client_id then this expiration of access check will only run
238- // against the first one encountered. This matters if there are
239- // multiple applications, using the same client_id, and asserting
240- // different expire_access_when_unused_after values.
241-
242- // Set app AAL (AA level) if present
243- required_aal = app . AAL || required_aal ;
244-
245- // AUTHORIZED_{GROUPS,USERS}
246- //
247- // XXX this authorized_users SHOULD BE REMOVED as it's unsafe (too
248- // easy to make mistakes). USE GROUPS.
249- //
250- // XXX This needs to be fixed in the dashboard first. Empty users
251- // or groups (length == 0) means no access in the dashboard
252- // apps.yml world.
253- if (
254- app . authorized_users . length === 0 &&
255- app . authorized_groups . length === 0
256- ) {
257- const msg =
258- `Access denied to ${ event . client . client_id } for user ${ event . user . email } (${ event . user . user_id } )` +
259- ` - this app denies ALL users and ALL groups")` ;
260- console . log ( msg ) ;
261- return deny ( "notingroup" ) ;
262- }
263+ // AUTHORIZED_{GROUPS,USERS}
264+ //
265+ // XXX this authorized_users SHOULD BE REMOVED as it's unsafe (too
266+ // easy to make mistakes). USE GROUPS.
263267
264- // Check if the user is authorized to access
265- // A user is authorized if they are a member of any authorized_groups or if they are one of the authorized_users
266- if (
267- app . authorized_users . length > 0 &&
268- app . authorized_users . indexOf ( event . user . email ) >= 0
269- ) {
270- authorized ||= true ;
271- // Same dance as above, but for groups
272- } else if (
273- app . authorized_groups . length > 0 &&
274- hasCommonElements ( app . authorized_groups , groups )
275- ) {
276- authorized ||= true ;
277- }
278- } // correct client id / we matched the current RP
268+ // Check if the user is authorized to access.
269+ // A user is authorized if they are a member of any authorized_groups
270+ // or if they are one of the authorized_users.
271+ if (
272+ app . authorized_users . length > 0 &&
273+ app . authorized_users . indexOf ( event . user . email ) >= 0
274+ ) {
275+ console . log ( `${ event . user . user_id } was in authorized_users` ) ;
276+ required_aal = app . AAL || default_aal ;
277+ authorized = true ;
278+ break ;
279+ // Same dance as above, but for groups
280+ } else if (
281+ app . authorized_groups . length > 0 &&
282+ hasCommonElements ( app . authorized_groups , groups )
283+ ) {
284+ console . log ( `${ event . user . user_id } was in authorized_groups` ) ;
285+ required_aal = app . AAL || default_aal ;
286+ authorized = true ;
287+ break ;
288+ }
279289 } // for loop / next rule in apps.yml
280290
281291 if ( ! authorized ) {
282- const msg =
283- `Access denied to ${ event . client . client_id } for user ${ event . user . email } (${ event . user . user_id } )` +
284- ` - not in authorized group or not an authorized user` ;
285- console . log ( msg ) ;
292+ console . log (
293+ `Access denied to ${ event . client . client_id } for user ` +
294+ `${ event . user . email } (${ event . user . user_id } ) - not in ` +
295+ "authorized group or not an authorized user"
296+ ) ;
286297 return deny ( "notingroup" ) ;
287298 }
288299
0 commit comments