Forum Stats

  • 3,873,374 Users
  • 2,266,538 Discussions


APEX_UTIL.PREPARE_URL 0- cecksum parameter

Emu Member Posts: 270 Bronze Badge
edited Jul 25, 2009 5:12PM in APEX Discussions
Anyone what the different checksum options mean with APEX_UTIL.PREPARE_URL ? Al the doco I have seen just says it exists without explaining what it does.

(What I really want to do it to have a url emailed so that if they are already logged inot ythe application and using it when they get this email they do not have to log in again)


  • Roel Hartman
    Roel Hartman Member Posts: 2,711 Gold Trophy

    Look at [] - but you probably have done that.

    p_checksum_type can be SESSION (3), PRIVATE_BOOKMARK (2) or PUBLIC_BOOKMARK (1).
    A Public Bookmark can be used by anyone, anytime.
    A Private Bookmark can be used by you, anytime.
    A Session can be used by you, only now (that's probably the same as the default, but that is not quite clear).

    So I guess you need '1'.

    You can reward this reply by marking it as either Helpful or Correct ;-)
  • 60437
    60437 Member Posts: 16,564
    edited Jul 19, 2009 12:23PM

    If you are using the Session State Protection feature and the link is intended to be used only by a certain authenticated user, i.e., the particular combination of request, clear-cache, item names/item values in the URL is good only for that user, then use checksum type 2. The user will have to log in again, however.

    Roel - Type 3 (session level) is the default.

  • Simon Gadd
    Simon Gadd Member Posts: 598
    Hello Gentlemen

    I am trying to do just this.

    Generate an email which contains a link to an Issue/e-ticket in my APEX application.
    This email will go to several recipients
    The target is a page which utilises SSP

    I am using the following code in a page process to generate the URL which I add to the email
    v_issue_url := APEX_UTIL.PREPARE_URL('f?p=&APP_ID.:'||203||':'||:SESSION||'::NO::P203_USER_ISSUE_ID:'||:P203_USER_ISSUE_ID,'UTF-8',3);
    v_issue_url := 'Issue URL: ' || OWA_UTIL.get_cgi_env ('REQUEST_PROTOCOL') || '://'|| OWA_UTIL.get_cgi_env ('HTTP_HOST')|| OWA_UTIL.get_cgi_env ('SCRIPT_NAME') ||'/'|| v_issue_url;
    This generates a URL that I can click on when I receive the email as long as I am still logged in to the APEX application. It is no good for other users.

    What I need is a URL that can be sent to anyone. If they are already logged in to the application then it will take them directly to the issue. If they are not logged in then they will be presented with the login screen and then taken to the issue.

    Is this possible?

    Any suggestions/corrections much appreciated.

    Many thanks

    Kind regards

    Simon Gadd
  • 60437
    60437 Member Posts: 16,564
    edited Jul 24, 2009 11:22PM

    There are two separate problems here: 1) how to generate an SSP-aware URL that can be used by any user in a new session, and 2) how to generate links that will "join" an existing session if one exists.

    For the 1st problem, you need to pass '1' as the third argument (checksum type) to apex_util.prepare_url. This will cause a checksum (&cs=) to be appended to the f?p URL which will allow the link to be used in a new (future) session by any user of the application in the same workspace. The resulting URL will still be tamper-resistant so that the user can't mess with it.

    For the 2nd problem, try this:

    Create a page and set its security attribute to 'Page Is Public' and set its Page Access Protection attribute to Arguments Must Have Checksum.

    For deep link URLs that you send to users, always use the page ID of this public page.

    Put everything else in the URL as you normally would, leaving out the session ID, but set the request value to the page ID that you really want them to go to.

    So if the link you want them to use is f?p=100:1:::NO:RP:P1_X,P1_Y:abc,def and your new public page is 2, send them this link instead:f?p=100:2::1:NO:RP:P1_X,P1_Y:abc,def.

    Then use apex_util.prepare_url on that and use '1' as the third argument (checksum type). This is for public bookmarks. Then you have to be sure that each item whose name will be passed in the link (with a corresponding value) has its Session State Protection attribute set to Checksum Required - Application Level. If you were going to generate a private bookmark (type '2') then you would choose Checksum Required - User Level instead. And if you were generating the default session-level checksum (type '3') using prepare_url, then you would set each item's attribute to Checksum Required - Session Level. To flip this around, the checksum type that you request of apex_util.prepare_url, '1', '2', or '3', must be at least as high (numerically) as the highest value of the Session State Protection attribute ('1', '2', or '3') of all items passed in the link.

    On the public page put a before-header process with this PL/SQL anonymous block:


    l_app_id varchar2(20) := null;
    l_page_id varchar2(20) := null;
    l_sess_id varchar2(256) := null;
    l_remainder varchar2(2000) := null;
    l_new_url varchar2(2000) := null;
    l_this_url varchar2(2000) := wwv_flow_utilities.url_decode2(owa_util.get_cgi_env('QUERY_STRING'));
    l_join_session number;
    -- Treat current f?p URL to public page as having in its "request" position the actual desired page for the deep link
    -- and as having the rest of the URL intact (debug, clear-cache, arg names, arg values, and other arguments to f
    -- such as &c=WS1,&p_trace=YES or #anchors
    apex_application.g_unrecoverable_error := true;
    -- Get the session ID that we are now authenticated in
    l_join_session := wwv_flow_custom_auth_std.get_session_id_from_cookie;

    --parse components of f?p URL and return everything after session ID position as l_remainder

    -- Build new URL with authenticated session ID and correct page (from v('REQUEST'))
    if instr(l_this_url,':') > 0 then -- e.g., p=105:1:99999 or p=105:2::3:NO:RP:P3_X,P3_Y:VAL1,VAL2
    l_new_url := l_app_id||':'||nvl(v('REQUEST'),'1')||':'||to_char(l_join_session);
    if l_remainder is not null then
    -- Tack on everything from the original URL that followed the session ID position
    l_new_url := l_new_url||':'||l_remainder;
    end if;
    -- Improper format for this type of deep link so redirect to page 1 in current session
    l_new_url := l_app_id||':1:'||to_char(l_join_session); -- e.g., p=105
    end if;

    -- redirect to URL using page ID from request position. If we aren't authenticated (l_join_session is null),
    -- user will have to login but deep link will be preserved using the normal mechanism

    exception when others then
    -- Error, redirect to page indicated in v('REQUEST') in current application


    Edited by: sspadafo on Jul 24, 2009 8:14 AM

    Edited by: sspadafo on Jul 24, 2009 8:14 PM
  • Simon Gadd
    Simon Gadd Member Posts: 598
    Hi Scott.

    Thanks for picking this one back up. It looks like you're right on the money but I have a couple of anomalies from the expected bahaviour.

    If I issue the following command (No Session passed and still referring to my page with SSP) I get a URL with a Checksum
    If I issue the same command but this time set the target page to my new Public page I get a URL with no Checksum.
    My first question is, is this the expected behavious because the process on my new page 'should' create a new URL with a checksum anyway?

    My second question is, does the subsequent position of the page 203 appear in the right location?

    Many thanks

  • Simon Gadd
    Simon Gadd Member Posts: 598
    One more follow up Scott

    I currently generate the following URL which targets my public page (97)
    When I follow this URL my page only displays "OK" in the top left corner. If I generate a new email and then modify the URL in a text editor to enable DEBUG (and in my browser I am logged in as a developer) the page gives me the following error.
    Attempt to save item P203_USER_ISSUE_ID in session state during show processing. 
    Item protection level indicates "Item may be set when accompanied by a "session" checksum.". 
    No checksum was passed in or the checksum passed in would be suitable for an item with protection level "(No checksum was provided)".
    It's true, P203_USER_ISSUE_ID does have SSP enabled. Should the before header process on page 97 handle this for me?

    Many thanks

  • 60437
    60437 Member Posts: 16,564

    I forgot to tell you to set the new public page's Page Access Protection attribute to Arguments Must Have Checksum. I'll revise my post, above.

  • Simon Gadd
    Simon Gadd Member Posts: 598
    Hi Scott

    Set the new public page's Page Access Protection attribute to Arguments Must Have Checksum.

    Getting this (when I can get it give me a debug message)
    Session state protection violation: This may be caused by manual alteration of a URL containing a checksum or by using a link with an incorrect or missing checksum. If you are unsure what caused this error, please contact the application administrator for assistance.
    Any suggestions?

    Many thanks

  • 60437
    60437 Member Posts: 16,564

    I actually tested all this before I posted the solution. If you can set up your scenario on, I'll take a look. It's probably some little detail I overlooked.

  • Simon Gadd
    Simon Gadd Member Posts: 598
    Hello Scott

    I have uploaded this to APEX.ORACLE.COM

    Workspace :NEXTGEN
    User ID :[email protected]

    Can I email the password to you or can you access anyway? :-)

    The public page is 97 and the target page is 203.

    The process where I am generating the URL is toward the bottom of the page 203 process named "EMAIL_ISSUE_NOTE" Search for "APEX_UTIL.PREPARE_URL" and you'll find it.

    Naturally, these won't run because all the underlying database tables and data are not present but hopefully there would be enough for you to see any obvious errors.

    Please let me know if there is more I can do to assist.

    I really appreciate the help.

    Many thanks

This discussion has been closed.