3-legged OAuth with Oracle APEX

Navigating Callbacks in Oracle APEX: Simplifying 3-Legged OAuth Integration

·

3 min read

As digital ecosystems continue to expand, users often seek seamless and secure methods to access third-party services without compromising their credentials. This is where 3-legged OAuth, a robust authentication protocol, emerges as a crucial solution. 3-Legged OAuth facilitates the secure delegation of user credentials to third-party applications, allowing them to access resources on behalf of the user. The process involves three distinct entities: the user, the client application, and the server providing the requested resources. By introducing user consent into the authentication workflow, 3-legged OAuth ensures transparency and user-driven authorization.

This medium article discusses how to implement 3-legged OAuth with Fusion as the resource server.

This post is going to discuss how to implement this with Oracle APEX as the client application, some gotchas and how to get around them.

The main hurdle you’ll encounter with APEX as the client application is receiving the authorization code from the authorization server (IDCS aka IAM). APEX user sessions have their session ID embedded on the request URL every time. If the redirect URL for receiving the authorization code is an APEX application page, then when IDCS redirects to this page with the auth code, APEX will require the user to log in again since the request will be treated as a new session because there is no session ID passed to the URL. Even if you make the redirect page a public page, it will invalidate the existing user session.

So the solution is to have the redirect URL be a RESTful Service URL in APEX. But RESTful Services endpoints are stateless — how do you tie it to the user’s session?

The trick is to add a state parameter to the IDCS authorization redirect:

https://<IDCS HOST>/oauth2/v1/authorize?client_id=<CLIENT ID>&response_type=code&redirect_uri=<REDIRECT URL AS CONFIGURED IN CLIENT>&scope=<SCOPE AS CONFIGURED IN CLIENT ALLOWED SCOPE>&state=<STATE PARAMETER>

For the state parameter, you can pass the app ID, page ID and the user’s session ID. The session ID can be retrieved using the APEX_CUSTOM_AUTH.GET_SESSION_ID function. Use a delimiter such as a dot (.) to concatenate these 3 values into a single parameter value.

The state parameter is passed along to your redirect URL when authorization server sends back the auth code.

Implement the RESTful Service handler as follows:

  • Method: GET

  • Source Type: PL/SQL

  • Parameters: auth & state as URI IN parameters

  • Source:

DECLARE
    l_state_parts apex_t_varchar2;
    l_app_id      number;
    l_page_id     number;
    l_session_id  number;
BEGIN
    htp.htmlopen;
    htp.headopen;
    htp.title('Fusion Apps Authorization');
    htp.style('
body {
    font-family: Arial, sans-serif;
    text-align: center;
    margin: 50px;
}
.success {
    color: green;
}
.error {
    color: red;
}

');
    htp.headclose;
    htp.bodyopen;

    BEGIN
        l_state_parts := apex_string.split(:state, '.');
        l_app_id      := l_state_parts(1);
        l_page_id     := l_state_parts(2);
        l_session_id  := l_state_parts(3);

        apex_session.attach(p_app_id => l_app_id, p_page_id => l_page_id, p_session_id => l_session_id);

        /*** Update APEX application item to receive the auth code from :code bind variable ***/

        htp.print('<h1 class="success">Authorization Successful!</h1><p>You may close this page.</p>');
    EXCEPTION
        WHEN OTHERS THEN
            htp.print('<h1 class="error">Invalid Request</h1><p>An error occured.</p>');
    END;

    htp.bodyclose;
    htp.htmlclose;
END;

The APEX_SESSION.ATTACH allows the RESTful service handler to attach to the user’s session so it can manipulate application items or collections within that session.