Thursday, 19 January 2017

Re-evaluating APEX Authorization Schemes

Authorization schemes in Oracle APEX are used to control access to page, buttons, and all sorts of other components.

In my experience, these are best defined at a privilege level, where the same privilege could be allocated to multiple business roles, but that's for another post.

In this post, I want to mention a cool API function called apex_authorization.reset_cache, which helps control the behaviour of these authorization schemes.

Preface

While googling something else I stumbled across an interesting function called apex_util.reset_authorizations, only to find it was deprecated in 5.1, replaced with the same (but renamed) function in another package.

APEX_UTIL was getting big, and even though the team was trying to manage it, 5.1 was the first time I noticed it reduce the number of procedures. Too many procedures mean some gold nuggets get lost, perhaps until they're moved to a more specific package.

I'd say we're all guilty of putting a procedure in the inappropriate package or letting a "utils" package grow too big. Me probably more than many, but there's been a lot of clean-up in 5.1. If there's any documentation you read about 5.1, let it be the release notes.

I also found the function mentioned in an old email I marked for blogging about because of an OTN forum post I was listening to. Not because of the original topic, but another deprecated/renamed procedure mentioned within.

Authorization Evaluation Point

The default evaluation point for authorization schemes is once per session. This means the first time APEX comes across a component protected by an authorization scheme, it will evaluate it and remember the result.

Authorization Scheme Evaluation Point

This default option is best for performance, but if you want to afford your users the ability to pick up changes in authorization without needing to log out then back in, then you can use one of the other options.

Re-setting authorization schemes at runtime

A cool API exists called apex_authorization.reset_cache. The documentation states
"it resets the authorization caches for the session and forces a re-evaluation when an authorization is checked next".

This means you can provide a button to the user that would clear the slate for all authorization scheme outcomes in that session and force APEX to re-evaluate any authorisation schemes it encounters.

This will be handy for me because it offers a chance to do this on demand at runtime, instead of once or 'all the time'. It also does the job across multiple applications that share authentication.

This is one of quite a few library functions now available in 5.1, in fact, this particular one has been around in some form since 4.2, but buried in apex_util.reset_authorizations.

Under the hood

If you want to see the interactions in the underlying APEX table, this query will help.
select s.*, a.application_id, a.authorization_scheme_name
from apex_050000.wwv_flow_session_authz$ s
join apex_application_authorization a
  on a.authorization_scheme_id = s.authorization_id
where session_id = 16678957299354
See, it's not magic. Just clever.

References

apex_authorization.reset_cache
Providing Security through Authorization
APEX 5.1 Release Notes

4 comments:

Dietmar Aust said...

Hi Scott,

I use this feature a lot in my user management screens. This way I can assign new roles to my users and they are effective immediately. The user doesn't have to logout and login to see the difference.

Also nice when testing and demoing, makes things a lot easier. So you have the best of both worlds, caching on a session basis and current all the time, I like it :).

Cheers,
~Dietmar.

Scott Wesley said...

Out of curiosity, how/when do you trigger the API call for the user?

Dietmar Aust said...

Hi Scott,

sorry, didn't see your question.

I typically do it on the screen where I assign roles to the user. The privileges are driven by the respective user roles. Thus I have a process to call the api to reset the caches for the current user session.

Put in a different way ...I trigger the api whenever I change the privileges so that the cached authorization values would get stale. Typically you would have to log out and log in again, then the authorizations are run again.

Hope that clarifies it.

Cheers,
~Dietmar.

Dietmar Aust said...

Hi Scott,

perhaps you also want to update the caches not only for the currently logged in user but for all affected users when you change their privileges. So basically whenever I change the privileges for a user ... it will take immediate effect for the user in a different session without requiring him to logout and login again.

This would be the approach I would suggest:

*) Once any user logs in you save the date/time of the last update to the current users' roles in an application level variable, e.g. G_LAST_ROLE_UPDATE_ON.
*) Then you have an application level process which checks on each page run whether the current last update of the logged in users' roles still equals G_LAST_ROLE_UPDATE_ON. If not then run the api call and refresh the caches.

Does that clarify it?

Cheers,
~Dietmar.