I'm trying to find a solution to create something similar to a server-side condition for pages. I want pages to be available depending on some global variables. I have created a function that returns a logical value in the database. How to implement it? I tried to use authorization schemes, but it doesn't work with parameters.
As far as I understood, value returned by that function decides whether someone is allowed to use certain page or not. You didn't explain what it exactly does, so I'll presume that it returns Boolean: TRUE (yes, allow page access) or FALSE (don't allow it), based on certain parameters such as :APP_USER.
If that's so, my suggestion would be to do what you already tried but failed for some reason.
navigate to Shared Components
go to Security - Authorization Schemes
create a new scheme, let's call it AS_ALLOW
set
scheme type = PL/SQL function returning Boolean
PL/SQL function body
return your_function(:APP_USER);
message displayed when scheme violated: "You aren't authorized to visit this page"
Now, back to page. Open its Security properties and put
AS_ALLOW into the "Authorization scheme"
That should do it; once the user runs the application, the function will return either TRUE or FALSE which will - in turn - allow (or not) that user's access to page that has the authorization scheme set.
Related
Edit: I might have been unclear with my question. The authorization scheme is supposed to go off a page after the login page.
I am creating an Apex application with custom authentication, I successfully made the login page and am now able to set session item values. I made an apex application item called 'SESSION_USER_ROLE' and in my login authentication procedure I set the user role in the session state by using:
Apex_Util.Set_Session_State('SESSION_USER_ROLE', v_role);
After logging in with one of my user accounts and checking the session application items I can confirm that the item value and item name are properly set in the application items and session state.
However, when I try to access the value of the 'SESSION_USER_ROLE' item for an authorization scheme by using a PL/SQL function returning boolean I always seem to get 'false' even when I should be getting 'true'. This is the PL/SQL code I've been trying to use for authorization purpose:
DECLARE
v_role VARCHAR2(200);
v_auth boolean;
BEGIN
v_role := APEX_UTIL.FETCH_APP_ITEM('SESSION_USER_ROLE');
--This is the value of the SESSION_USER_ROLE for this specific user
if v_role = 'CEO' then
v_auth := true;
else
v_auth := false;
end if;
return v_auth;
END;
I don't understand what I'm doing wrong here. Is this not the correct way to retrieve the item value of SESSION_USER_ROLE?
Ensure the process that sets your application item where you refer to 'login authentication procedure' is referred to in the 'post-authentication procedure name' attribute of the current Authentication Scheme.
Alternatively, use the After Authentication computation point for application processes.
On new instance would be too early, before the person logs in.
Add some instrumentation using apex_debug.message, and run the process in debug mode.
For instance, you might like to log the value of v_role in the authentication process, and again after you fetch it in the Authorisation Scheme.
You may well be fetching it correctly, but does it have the value you expect? An alternative reference method is with bind variable syntax, :SESSION_USER_ROLE
On a side note, I've had more scalable success by defining authorisation schemes by privilege, not by business role.
I am trying to define a condition to my button in the home page that is of type pl/sql expression in order to hide this button, if the specific text is not submitted from other users. The expression that im trying to return is a text field from another page(login).Here is my expression
:P101_PASSWORD='xxxxxx'
Here xxxxxx is the condition to show the button but the button doesnt appear whenever i log in as xxxxxx.
I don't remember exactly, it could be one of two reasons: item P101_PASSWORD receives NULL value just after login process or value of item with type "Password" couldn't be used in SQL and PL/SQL(I'm not sure that this was described in documentation).
You can try to make experiment (I can't do until morning). I don't know, what you want to do, but if you ask user to enter password once again, use verification function to check.
If all you want to do is making the appearance of page items conditional on the name or group of the current user, querying the password field of your login page is most likely not the way you want to go (depending on your page processes, the session state of your page might get cleared after login. Also, if the user changes their password, you would need to update the display condition etc.).
The easiest way to handle this situation is probably to create a new group of users who should have access to the restricted information and functionality (call it PRIV_GROUP, for example). Next, define an authorization scheme of type 'PL/SQL Function Returning Boolean' with the following body:
BEGIN
RETURN APEX_UTIL.CURRENT_USER_IN_GROUP(p_group_name => 'PRIV_GROUP');
END;
Finally, set your authorization scheme as the button's display condition.
Edit:
In your case, since you are using custom authentication, I would suggest you create an application level item to store the name of the currently logged user. Go to Shared Components -> Application Items -> Create and create an item called LOGGED_USER.
Next, you need to create a post-authentication procedure:
In your DB, issue the following command:
CREATE OR REPLACE PROCEDURE post_authentication IS
BEGIN
apex_util.set_session_state('LOGGED_USER', upper(:P101_USER_NAME)); --Adapt to the name of your page item
END post_authentication;
To associate this procedure with your authentication scheme, go to Shared Components -> Authentication Schemes and edit your custom scheme. Under 'Post-Authentication Procedure Name', type "post_authentication" (without quotation marks).
If only user MANAGER should have access to the button, redefine your authorization (NOT authentication) scheme as follows:
BEGIN
IF :LOGGED_USER = 'MANAGER' THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END;
I am trying to create a suitable authentication check for a CakePHP service. Currently it appears that the user session is created initially during login, but never checked beyond this during a single session.
eg. Renamed the username, changing the password or ID in the user's database entry has no effect on the session.
Is there a preferred method for this type of, constantly checked, authentication? Essentially the user should be confirmed access at every request.
My current solution would involve extending the AuthComponent and storing a hash of the user data (including the encrypted password) and checking this at every request. I also considered storing the session ID in this same token, but noticed that CakePHP does not even use the session_start() function.
This functionality appears necessary for me, and I would have thought others would also require such a solution. I have yet to find Cake documentation or community solutions similar to what I need.
Well, you can use isAuthorized() function from AuthComponent. It's being called with every request.
public function isAuthorized($user){
return true; //allow the user to see the page
}
You can debug($user) to see the actual data and if you want "new" information from your database, you can always get them like this:
public function isAuthorized($user){
$current_user_from_database = $this->User->findById($user['id']);
if($current_user_from_database['User']['username'] != $user['username']){
$this->Session->setFlash('You\'ve changed the username. Please, login again.');
$this->redirect($this->Auth->logout);
return false;
}
return true;
}
Look at the API for more info and from the PDF book. You can look at this video about AuthComponent too. It's great.
If you need any more information or help, feel free to ask.
Btw. you have to configure AuthComponent in your Controller if you want isAuthorized() function to get called with every request.
If Session.timeout will work correctly with a setting of zero minutes, you're set. http://book.cakephp.org/2.0/en/development/sessions.html
Is it possible to set the absoluteURI in the controller after clicking on an action link? So for example:
User clicks on a link called "GoHere". The current URL is domain.com/section/place. When the link hits the method in the controller, it recognizes that the user is currently in a section called "section", even though in the file structure section doesn't exist. The link itself actually points to domain.com/place2. Instead of returning a URL of domain.com/place2, it returns domain.com/section/place2.
The reason I ask is because for what I'm doing, the section is completely arbitrary and doesn't exist. It's just there to give the impression that the user is in another section. I know I could create extra sets of controllers, but I'm trying to get around this since for management purposes it's better if I just have one set of controllers. Is this possible? Thanks.
In your gobal.asax, try setting your route to require section for the control. Maybe "{control}/section/{action}/" and whatever else you need.
I'm using Azure ACS in my ASP.net MVC 3 website (hosted in Azure too), the scenario is this:
A user first enters my website and fills a one field form, then they need to chose a provider and login, but first I want to store the field value so when they come back from login I'm able to create a profile with this value for the loged in user.
So I believe when they first enter the site and then leaves to login and enters the site again those are two different sessions am I right? and that's the reason the stored data using session state (through SQL Server) is not present when they come back after login am I right? if this is true what would be the best approach then? if not then I'm doing something wrong storing temp data right?
Thanks
UPDATE:
I have discovered that HttpContext.Application state works keeping the data, still I'm not sure if it's a good idea to use it in a controller considering it's in Azure, will it work on production properly??
You can pass state around in the WS-Federation redirect sequence using the wctx URL parameter. In the action that handles the initial POST request, you should get hold of the form parameter you want to keep, then redirect to you identity provider selection page (this will have to be a custom page) with the form parameter appended to the URL. When the user selects an IP on your page, you can pass the parameter on again using the wctx parameter. The WS-Federation passive requestor profile says that this should be returned to you eventually when the IP redirects the user back to your site.
This has some details
http://msdn.microsoft.com/en-us/library/bb608217.aspx
Edit: To get the wctx parameter out of the request when the user finally comes back to your app. Put something like this in the action code:
var fam = FederatedAuthentication.WSFederationAuthenticationModule;
if (fam.CanReadSignInResponse(System.Web.HttpContext.Current.Request, true))
{
string wctxValue = this.HttpContext.Request.Form["wctx"];
}
My preference is to have the wcxt parameter represent a redirect URL (URL encoded) with your parameter as a query parameter in that so it be a URL encoded version of this:
wctx=https://yourserver/yourapp/yourpage?yourparameter=foo
Then the action that was receiving the redirect from the ACS would simply pull out the value of wctx and do a redirect to it without any more processing. This keeps things simple.
Another approach would be to save whatever data you need to pass around in the Database, and just pass around some ID that refers back to the database record. You'll pass this ID to IP and back through wctx (as Mike mentioned above).
This will solve the issue of limited length of URLs (in case your data is very large). Of course you would need to manage deletion of this data, but this shouldn't be hard.