Skip to Main Content

APEX

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

SSO authentication do not log out users correctly

MohammasMay 27 2019 — edited May 27 2019

Hi,

We are currently on Oracle 12.1.0.2.0 and Apex 5.1.4.

Set-up:

There are three applications.

1. SSO Application - This has homescreen with hyperlink to actual applications(Applications A & B).

2. Application A

3. Application B

Issue:

After the user logs out from any of the pages of above 3 applications, clicking on back button of browser, user is taken back to the exact same screen before logout.

Expected Behavior:

Once logged out, irrespective of what the user does, he should be directed to SSO login page, unless valid login credentials are provided.

Following is the code in our system,

Authentication Scheme:

SSO Application:

Name: SSO Login Authentication Scheme

Sentry Function_Name: sentry

Authentication Function Name: check_credentials

Session Not Valid:

URL: f?p=&APP_ID.:101:&SESSION.

Post Logout URL:

logout?p_app_alias=&APP_ALIAS.

Classic Navigation Bar Entry: Logout

Target -> URL -> logout?p_app_alias=&APP_ALIAS.

Application A & B:

Name: Auxiliary Authentication Scheme

Scheme Type: Custom

Sentry Function_Name: sentry

Session Not Valid:

login_page

Post Logout URL:

login_page

Classic Navigation Bar Entry: Logout

Target -> URL -> logout?p_app_alias=&APP_ALIAS.

CODE

Our code is very close to below article.

https://blogs.oracle.com/oraclemagazine/creating-custom-authentication

Sentry:

   FUNCTION sentry

      RETURN BOOLEAN

   AS

      l_current_sid   NUMBER;

      l_username      VARCHAR2 (240) := NULL;

      l_cookie        OWA_COOKIE.cookie := OWA_COOKIE.get (c_cookie_name);

   BEGIN

      BEGIN

         -- See if there is a leftover user cookie

         l_username :=

            UPPER (

               wwv_flow_utilities.string_to_table2 (l_cookie.vals (1),

                                                    sep   => '^') (1));

      EXCEPTION

         WHEN OTHERS

         THEN

            RETURN FALSE;

      END;

      l_current_sid := APEX_CUSTOM_AUTH.get_session_id_from_cookie;

      -- If the apex session from the cookie is valid, re-instantiate the session

      IF APEX_CUSTOM_AUTH.is_session_valid

      THEN

         wwv_flow.g_instance := l_current_sid;

         IF l_username = APEX_CUSTOM_AUTH.get_username

         THEN

            APEX_CUSTOM_AUTH.define_user_session (

               p_user         => l_username,

               p_session_id   => l_current_sid);

            RETURN TRUE;

         ELSE

            -- Username mismatch. Unset the session cookie and redirect back here to take other branch

            APEX_CUSTOM_AUTH.LOGOUT (

               p_this_app             => v ('APP_ID'),

               p_next_app_page_sess   =>    v ('APP_ID')

                                         || ':'

                                         || NVL (v ('APP_PAGE_ID'), 0)

                                         || ':'

                                         || l_current_sid);

            -- tell apex engine to stop processing and return false

            wwv_flow.g_unrecoverable_error := TRUE;

            RETURN FALSE;

         END IF;

      ELSE

         -- application session cookie not valid; we need a new apex session

         APEX_CUSTOM_AUTH.define_user_session (

            p_user         => l_username,

            p_session_id   => wwv_flow_custom_auth.get_next_session_id);

         wwv_flow.g_unrecoverable_error := TRUE;  -- tell flows engine to quit

         IF OWA_UTIL.get_cgi_env ('REQUEST_METHOD') = 'GET'

         THEN

            wwv_flow_custom_auth.remember_deep_link (

               p_url   =>    'f?'

                          || wwv_flow_utilities.get_cgi_query_string_decoded);

         ELSE

            wwv_flow_custom_auth.remember_deep_link (

               p_url   =>    'f?p='

                          || TO_CHAR (wwv_flow.g_flow_id)

                          || ':'

                          || TO_CHAR (NVL (wwv_flow.g_flow_step_id, 0))

                          || ':'

                          || TO_CHAR (wwv_flow.g_instance));

         END IF;

         -- register session in sessions$,set cookie,redirect back

         APEX_CUSTOM_AUTH.post_login (

            p_uname      => l_username,

            p_app_page   =>    wwv_flow.g_flow_id

                            || ':'

                            || NVL (wwv_flow.g_flow_step_id, 0));

         RETURN FALSE;

      END IF;

     

   EXCEPTION

      WHEN OTHERS

      THEN

         logger.error (DBMS_UTILITY.format_error_backtrace);

         logger.error (DBMS_UTILITY.format_call_stack);

         RAISE;

   END sentry;

Check Credentails:

C_Cookie_name value is "VALID_SESSION";

   FUNCTION check_credentials (p_username   IN VARCHAR2,

                               p_password   IN VARCHAR2)

      RETURN BOOLEAN

   AS

      l_result                BOOLEAN;

   BEGIN

      HTP.init;

      OWA_UTIL.mime_header ('text/html', FALSE);

      set_sso_cookie;

   EXCEPTION

      WHEN OTHERS

      THEN

         logger.error (DBMS_UTILITY.format_error_backtrace);

         logger.error (DBMS_UTILITY.format_call_stack);

         RAISE;

   END check_credentials;

  

   PROCEDURE set_sso_cookie

   IS

      --sets suite cookie, called from check_credentials only

      l_t_id   NUMBER := NULL;

   BEGIN

      OWA_COOKIE.send (

         name      => c_cookie_name,

         VALUE     => UPPER (v ('P101_USERNAME')) || '^' || v ('APP_SESSION'),

         expires   => NULL,

         PATH      => '/');

   EXCEPTION

      WHEN OTHERS

      THEN

         logger.error (DBMS_UTILITY.format_error_backtrace);

         logger.error (DBMS_UTILITY.format_call_stack);

         RAISE;

   END set_sso_cookie;

Login Page

   PROCEDURE login_page

   AS

   BEGIN

      OWA_UTIL.redirect_url (logout_url);

   EXCEPTION

      WHEN OTHERS

      THEN

         logger.error (DBMS_UTILITY.format_error_backtrace);

         logger.error (DBMS_UTILITY.format_call_stack);

         RAISE;

   END;

  

   FUNCTION logout_url

      RETURN VARCHAR2

   AS

      l_return                   VARCHAR2 (225);

      l_host_port                VARCHAR2 (25);

      l_service_name             VARCHAR2 (15);

      c_sso_app_alias   CONSTANT VARCHAR2 (10) := 'SSO';

   BEGIN

      l_host_port := OWA_UTIL.get_cgi_env ('HTTP_HOST');

      SELECT ords_serv_name

        INTO l_service_name

        FROM apex_usr.apex_applications

       WHERE application_id = c_sso_app_alias;

      l_return :=

            'http://'

         || l_host_port

         || '/'

         || l_service_name

         || '/f?p='

         || c_sso_app_alias

         || ':LOGIN';

      RETURN l_return;

   EXCEPTION

      WHEN OTHERS

      THEN

         logger.error (DBMS_UTILITY.format_error_backtrace);

         logger.error (DBMS_UTILITY.format_call_stack);

         RAISE;

   END logout_url;

Logout

   PROCEDURE LOGOUT (p_app_alias IN VARCHAR2 DEFAULT NULL)

   IS

      l_sqlerrm                 VARCHAR2 (4000) DEFAULT NULL;

      l_target_dad              VARCHAR2 (400) DEFAULT NULL;

      l_target_instance         VARCHAR2 (400) DEFAULT NULL;

      l_target_url              VARCHAR2 (4000) DEFAULT NULL;

      l_target_app_alias        VARCHAR2 (4000) DEFAULT NULL;

      l_target_app_id           NUMBER DEFAULT NULL;

      l_target_logout_page_id   NUMBER DEFAULT NULL;

      l_last_instance           VARCHAR2 (400) DEFAULT NULL;

      l_last_url                VARCHAR2 (4000) DEFAULT NULL;

      l_last_app_id             NUMBER DEFAULT NULL;

      l_calling_app_id          NUMBER DEFAULT v ('APP_ID');

      l_calling_app_alias       VARCHAR2 (400)

                                   DEFAULT NVL (p_app_alias, v ('APP_ALIAS'));

      l_calling_instance        VARCHAR2 (400) DEFAULT NULL;

      l_script                  VARCHAR2 (400) DEFAULT '/apex';

      l_host                    VARCHAR2 (400)

                                   DEFAULT OWA_UTIL.get_cgi_env ('HTTP_HOST');

      l_app_cnt                 NUMBER DEFAULT NULL;

      l_logout_cnt              NUMBER := 0;

      l_app_found               BOOLEAN := FALSE;

      l_is_sso2                 NUMBER :=  0;

      l_service_name            VARCHAR2 (15);

   BEGIN

      -- get instance info from apps table based on this iteration's invoking application alias

      FOR appinfo IN (SELECT instance, id AS app_id

                        FROM apex_usr.apex_applications

                       WHERE application_id = l_calling_app_alias)

      LOOP

         l_calling_instance := appinfo.instance;

         l_calling_app_id := appinfo.app_id;

      END LOOP;

      -- set through cursor of active apps to find the next one needing deauthentication

      FOR i IN (  SELECT id           AS app_id,

                         instance,

                         host_port,

                         logout_page_id,

                         application_id AS app_alias

                    FROM apex_usr.apex_applications

                   WHERE active_flag = c_yes_value

                ORDER BY instance, id)

      LOOP

         --deauthenticating all the apps

         APEX_CUSTOM_AUTH.LOGOUT (p_this_app => i.app_id);

         IF NOT l_app_found

         THEN

            l_last_instance := l_target_instance;

            l_last_app_id := l_target_app_id;

            l_target_instance := i.instance;

            l_target_app_alias := i.app_alias;

            l_target_app_id := i.app_id;

            IF    (    l_last_instance = l_calling_instance

                   AND NVL (l_last_app_id, -1) = NVL (l_calling_app_id, -1))

               OR p_app_alias IS NULL

            THEN

               l_app_found := TRUE;

            END IF;

         END IF;

      END LOOP;

      -- expire the suite cookie if all apps have been deauthenticated

      IF p_app_alias IS NULL

      THEN

         LOGOUT (p_app_alias => l_target_app_alias);

         RETURN;

      ELSE

         expire_cookie;

            APEX_CUSTOM_AUTH.logout_then_go_to_url (

               p_args   => l_target_app_id || ':' || fhlb_logout_url);

      END IF;

      wwv_flow.g_unrecoverable_error := TRUE;

   EXCEPTION

      WHEN OTHERS

      THEN

         l_sqlerrm := SQLERRM;

         logger.error (DBMS_UTILITY.format_error_backtrace);

         logger.error (DBMS_UTILITY.format_call_stack);

         RAISE;

   END LOGOUT;

  

   PROCEDURE expire_cookie

   IS

      l_t_id   NUMBER := NULL;

   BEGIN

      HTP.init;

      OWA_UTIL.mime_header ('text/html', FALSE);

      OWA_COOKIE.send (name      => c_cookie_name,

                       VALUE     => 'user_logged_out',

                       expires   => SYSDATE - 100,

                       PATH      => '/');

   EXCEPTION

      WHEN OTHERS

      THEN

         logger.error (DBMS_UTILITY.format_error_backtrace);

         logger.error (DBMS_UTILITY.format_call_stack);

         RAISE;

   END expire_cookie;

Let us know what we are missing, because of which the session is not expiring. Any inputs are highly appreciated.

Thanks,

Shoaib

Comments
Post Details
Added on May 27 2019
3 comments
665 views