# Avatar image in Oracle APEX

# Why you should read this

Displaying custom avatar images in Oracle APEX’s top navigation bar isn't as straightforward as you might think. By default, APEX lets you use **Font APEX icons**, but replacing those with **actual image -** especially ones stored as **BLOBs in database - it** takes some extra work.

In this post, I've put down the steps to do that using a **REST Media Resource** as the image source for your avatar, which is one of the simplest and most flexible approaches.

There are a few other possible methods that you can use:

* T**hird-party services** that host avatar images and provides image URLs via API (such as Gravatar, used by the [APEX Ideas App](https://apexapps.oracle.com/pls/apex/r/apex_pm/ideas/home))
    
* Hosting your avatars in the APEX **Static Application Files**
    
* Converting your avatar images to **Base64-encoded image URLs**
    

Each of these alternatives has its pros and cons and will try to cover them in more detail in future blog post. For now, let’s see how the **REST Media Resource** approach can help us in achieving our goal.

# Step by step guide

1. ### REST Module with a GET method, Source type - Media Resource
    

```sql
DECLARE
  l_roles     OWA.VC_ARR;
  l_modules   OWA.VC_ARR;
  l_patterns  OWA.VC_ARR;

BEGIN
  ORDS.ENABLE_SCHEMA(
      p_enabled             => TRUE,
      p_url_mapping_type    => 'BASE_PATH',
      p_url_mapping_pattern => 'gamma_dev',
      p_auto_rest_auth      => FALSE);

  ORDS.DEFINE_MODULE(
      p_module_name    => 'profile',
      p_base_path      => '/profile/',
      p_items_per_page => 25,
      p_status         => 'PUBLISHED',
      p_comments       => NULL);

  ORDS.DEFINE_TEMPLATE(
      p_module_name    => 'profile',
      p_pattern        => 'profile_picture/:user_id',
      p_priority       => 0,
      p_etag_type      => 'HASH',
      p_etag_query     => NULL,
      p_comments       => NULL);

  ORDS.DEFINE_HANDLER(
      p_module_name    => 'profile',
      p_pattern        => 'profile_picture/:user_id',
      p_method         => 'GET',
      p_source_type    => 'resource/lob',
      p_mimes_allowed  => NULL,
      p_comments       => NULL,
      p_source         => 
'select mime_type as content_type, blob_content from MY_USERS_TABLE where id = :user_id');

  ORDS.DEFINE_PARAMETER(
      p_module_name        => 'profile',
      p_pattern            => 'profile_picture/:user_id',
      p_method             => 'GET',
      p_name               => 'user_id',
      p_bind_variable_name => 'user_id',
      p_source_type        => 'URI',
      p_param_type         => 'STRING',
      p_access_method      => 'IN',
      p_comments           => NULL);


COMMIT;

END;
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757761657550/a32a98e4-df99-44b5-bb33-27288bbd3a95.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757761724282/0208d75e-f7de-4dcc-a892-3e86e8d763ca.png align="center")

2. ### Desktop Navigation Bar entry
    

```xml
<img id="user_avatar_img" class="ea-topnav-avatar" src="https://oracleapex.com/ords/gamma_dev/profile/profile_picture/&G_USER_ID."></img>
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757762216787/93c8a943-8d34-4b6c-89f1-7d326ceefd33.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757762238668/3f95ca60-a528-4dcf-989d-68d82d3d7139.png align="center")

3. ### Application Item with the User\_ID, used in the REST module
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757762425007/cd5f7e24-369b-4012-9c05-736a7c6628f2.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757762491158/7c6de076-9f7a-4796-91cc-89e56645fe95.png align="center")

4. ### Add CSS to style the navigation
    

```css
/* Navigation Bar avatar fixes */
.t-NavigationBar {
    align-items: center;
}

.ea-topnav-avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px #6b3010 solid;
}

@media (max-width:768px) {
    .ea-topnav-avatar {
        width: 32px;
        height: 32px; 
    }
}

@media (max-width:479px) {
    .ea-topnav-avatar {
        margin-right: 20px;
    }

    .t-NavigationBar {
        column-gap: 25px;
    }
}

.t-Button--navBar .t-Button-badge {
    display: flex;
    border-radius: 50%;
    padding: 0;
    background: none;
}
```

5. ### See your avatar in action
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757939693338/2d90bc81-6c2a-49c0-8839-5226626bf12f.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757939746365/6404eda6-b7ea-4e90-9b05-35c823b3f6b6.png align="center")

# Security

1. ### Instead of just USER\_ID, use a hashed version on the User\_id + User\_Email or any other columns in your user table
    

* Create new Application Item, called `G_USER_HASH`
    
* Compute `G_USER_HASH` after Authentication (using Application Process or Application Computation). Here is a sample code for a hashing that you could use:
    
    ```sql
    select mime_type content_type, profile_image blob_content 
    from my_users_table 
    where apex_util.get_hash(apex_t_varchar2 (id, user_email)) = :user_hash
    ```
    

2. ### Modify the REST module to use the `G_USER_HASH`, instead of just user\_id
    

* Change the Resource Template, replacing :user\_id with :user\_hash parameter (similar to the below):
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757941105998/37d90e3c-806a-4165-a4dc-d178961e943b.png align="center")

* Change the `GET` method **Source** and **Parameter** name:
    
    ```sql
    select mime_type content_type, profile_image blob_content 
    from my_users_table 
    where apex_util.get_hash(apex_t_varchar2 (id, user_email)) = :user_hash
    ```
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1757940787089/83ccb9e4-d09b-44d2-b328-4352ec3f7337.png align="center")
