DBA Hub

📋Steps in this guide1/6

Oracle REST Data Services (ORDS) : Basic and Digest Authentication on Tomcat using DataSourceRealm

This article demonstrates the use of the Tomcat DataSourceRealm to control authentication to Oracle REST Data Services (ORDS) web services.

oracle miscconfigurationintermediate
by OracleDba
20 views
1

Web Service Setup

This article assumes you have completed the following setup, that is common to most ORDS authentication methods. - Create a Test Database User - Enable ORDS and Create a Web Service - ORDS Roles and Privileges At this point, if you attempt to access the test web service you get a HTTP 401 unauthorized status returned, as the test web service is protected by the "emp_role" role.

Code/Command (click line numbers to comment):

1
2
3
4
5
6
7
8
$ curl -i -k
https://localhost:8443/ords/hr/employees/7788
| grep HTTP/2
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   669  100   669    0     0   2230      0 --:--:-- --:--:-- --:--:--  2244
HTTP/2 401
$
2

Authentication Schema Setup

Create tables to hold the users and roles information, if you don't already have some tables containing this information in your application. You can read about the requirements for the tables here . We create a new user called "emp_user" with a plain text password and associate it with the "emp_role" role, which ties up with the ORDS role defined in the setup.

Code/Command (click line numbers to comment):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
conn sys/SysPassword1@//localhost:1521/freepdb1 as sysdba

-- drop user tomcat_auth cascade;

create user tomcat_auth identified by tomcat_auth_passwd
  quota unlimited on users;
grant create session, create table to tomcat_auth;


conn tomcat_auth/tomcat_auth_passwd@//localhost:1521/freepdb1

drop table tomcat_user_roles purge;
drop table tomcat_users purge;

create table tomcat_users (
  user_name  varchar2(15),
  user_pass  varchar2(150) not null,
  constraint tomcat_users_pk primary key (user_name)
);

create table tomcat_user_roles (
  user_name  varchar2(15) not null,
  role_name  varchar2(15) not null,
  constraint tomcat_user_roles_pk primary key (user_name, role_name),
  constraint tcur_tcus_fk foreign key (user_name) references tomcat_users(user_name)
);

insert into tomcat_users values ('emp_user', 'Password1');
insert into tomcat_user_roles values ('emp_user', 'emp_role');
commit;
3

JDBC Driver (ojdbc8.jar)

Download the "ojdbc8.jar" file from here and place it in the "CATALINA_BASE/lib" directory. In my case I just used the file from the database ORACLE_HOME. If you are using Java 11 or 17 you should use "ojdbc11.jar".

Code/Command (click line numbers to comment):

1
2
mkdir -p $CATALINA_BASE/lib/
cp $ORACLE_HOME/jdbc/lib/ojdbc8.jar $CATALINA_BASE/lib/
4

Basic Authentication

Edit the "$CATALINA_BASE/conf/server.xml" file, amending the resource and realm as shown below. The resource contains the database connection details, and the realm contains the details of the tables and columns used to identify authenticated users. Add the following to the "$CATALINA_BASE/conf/web.xml" file before the final "web-app" tag. With the config changes in place we need to restart Tomcat. Without authentication we still get the HTTP 401 Unauthorized response. If we provide the user credentials we authenticate as expected.

Code/Command (click line numbers to comment):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
(1)
From this:

  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
                  UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

To this:

   <GlobalNamingResources>
    <!-- Editable user database that can also be used by
                  UserDatabaseRealm to authenticate users
    -->
    <Resource name="jdbc/myoracle" auth="Container"
              type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
              url="jdbc:oracle:thin:@localhost:1521/freepdb1"
              username="tomcat_auth" password="tomcat_auth_passwd" maxTotal="20" maxIdle="10"
              maxWaitMillis="-1"/>
  </GlobalNamingResources>


(2)
From this:

      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
                          resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

To this:     
        
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
                          resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.DataSourceRealm"
          dataSourceName="jdbc/myoracle"
          userTable="TOMCAT_USERS" userNameCol="USER_NAME" userCredCol="USER_PASS"
          userRoleTable="TOMCAT_USER_ROLES" roleNameCol="ROLE_NAME"/>
      </Realm>

<security-constraint>
      <web-resource-collection>
        <web-resource-name>ords</web-resource-name>
        <url-pattern>/*</url-pattern>
      </web-resource-collection>
      <auth-constraint>
        <role-name>*</role-name>
      </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>
    <security-role>
       <role-name>*</role-name>
    </security-role>

$CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/startup.sh

tail -f $CATALINA_BASE/logs/catalina.out

$ curl -i -k https://localhost:8443/ords/hr/employees/7788 | grep HTTP/2
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   669  100   669    0     0   2230      0 --:--:-- --:--:-- --:--:--  2244
HTTP/2 401
$

$ curl -k
--user emp_user:Password1
https://localhost:8443/ords/hr/employees/7788
{"empno":7788,"ename":"SCOTT","job":"ANALYST","mgr":7566,"hiredate":"1987-04-19T00:00:00Z",
"sal":3000,"comm":null,"deptno":20,"links":[{"rel":"self","href":"https://localhost:8443/ords/hr/employees/7788"},
{"rel":"edit","href":"https://localhost:8443/ords/hr/employees/7788"},
{"rel":"describedby","href":"https://localhost:8443/ords/hr/metadata-catalog/employees/item"},
{"rel":"collection","href":"https://localhost:8443/ords/hr/employees/"}]}
$
5

Digest Authentication

In the example above we used a plain text password to keep it simple, but you shouldn't be storing plain text passwords in the database. If you want to use a Digest authentication you can digest it and store the digest, rather than the clear text password. In this example we digest our password of "Password1". We are using a realm name of "ORDS" as the salt. You can use any salt, but you have to be consistent in the Tomcat config, making sure it is specified as the realm name. We have to replace the user credentials we set above, storing the digest password instead of the plain text password. Edit the "$CATALINA_BASE/conf/server.xml" file, adding a credential handler to the realm. Edit the "$CATALINA_BASE/conf/web.xml" file, amending basic authentication setup from the previous section. Notice the has changed to . With the config changes in place we need to restart Tomcat. We can test digest authentication using curl, provided the include the flag, so it understands it need to do the call/response associated with digest authentication.

Code/Command (click line numbers to comment):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Digest a password.
$CATALINA_HOME/bin/digest.sh -a md5 -i 1 -s 0 -h org.apache.catalina.realm.MessageDigestCredentialHandler Password1 
Password1:2ac9cb7dc02b3c0083eb70898e549b63
$

conn tomcat_auth/tomcat_auth_passwd@//localhost:1521/freepdb1

delete from tomcat_user_roles;
delete from tomcat_users;

insert into tomcat_users values ('emp_user', '2ac9cb7dc02b3c0083eb70898e549b63');

insert into tomcat_user_roles values ('emp_user', 'emp_role');
commit;

<Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
                          resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.DataSourceRealm"
          dataSourceName="jdbc/myoracle"
          userTable="TOMCAT_USERS" userNameCol="USER_NAME" userCredCol="USER_PASS"
          userRoleTable="TOMCAT_USER_ROLES" roleNameCol="ROLE_NAME"
>
                 <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler"
                                       algorithm="md5"
                                       iterations="1"
                                       saltlenght="0"/>
        </Realm>
</Realm>

<security-constraint>
      <web-resource-collection>
        <web-resource-name>ords</web-resource-name>
        <url-pattern>/*</url-pattern>
      </web-resource-collection>
      <auth-constraint>
        <role-name>*</role-name>
      </auth-constraint>
    </security-constraint>
    <login-config>
<auth-method>DIGEST</auth-method>
</login-config>
    <security-role>
       <role-name>*</role-name>
    </security-role>

$CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/startup.sh

tail -f $CATALINA_BASE/logs/catalina.out

$ curl -k
--digest
--user emp_user:Password1 https://localhost:8443/ords/hr/employees/7788
{"empno":7788,"ename":"SCOTT","job":"ANALYST","mgr":7566,"hiredate":"1987-04-19T00:00:00Z",
"sal":3000,"comm":null,"deptno":20,"links":[{"rel":"self","href":"https://localhost:8443/ords/hr/employees/7788"},
{"rel":"edit","href":"https://localhost:8443/ords/hr/employees/7788"},
{"rel":"describedby","href":"https://localhost:8443/ords/hr/metadata-catalog/employees/item"},
{"rel":"collection","href":"https://localhost:8443/ords/hr/employees/"}]}

$
6

Thoughts

Just some thoughts about this approach. - Don't test authentication using a browser. They often cache authentication details, making it hard to know if a change has had an impact. - You are effectively configuring basic authentication, or digest authentication, in Tomcat in the normal way, so you are already protecting the resources, but the role name maps to the ORDS roles, which means you also get through the ORDS authentication. - Not surprisingly, you should avoid plain text passwords. Digest authentication allows you to do this, but the client needs to understand if is no longer basic authentication. - In this example I've just protected everything below "/*". As a result, every URL will need authentication. If you want some public resources, you will have to configure Tomcat appropriately. For more information see: - JDBCRealm - Oracle REST Data Services (ORDS) : Basic and Digest Authentication on Tomcat using JDBCRealm - Oracle REST Data Services (ORDS) : All Articles - Oracle REST Data Services (ORDS) : Installation on Tomcat - Oracle REST Data Services (ORDS) : Authentication - Oracle REST Data Services (ORDS) : Database Authentication - Oracle REST Data Services (ORDS) : Custom Authentication Schemes Hope this helps. Regards Tim...

Comments (0)

Please to add comments

No comments yet. Be the first to comment!