MySQL REST Service - Core REST APIs

This book provides examples of using the MySQL REST Service queries and other operations against tables and views after you have REST-enabled them.

Chapter Overview


Please also see


1 MRS Core REST APIs

This section provides examples of using the MySQL REST Service queries and other operations against tables and views after you have REST-enabled them.

The examples in this section provide an insight into the direct, low-level REST API calls that can be made against the MySQL REST Service. They can be used to gain a deep understanding of how MRS works.

When developing an application with MRS, it is recommended to use a higher-level MRS Software Development Kit (SDK) instead. Please check if a SDK has already been made available for your programming language and platform.

1.1 About MRS RESTful Web Services

MRS supports the creation of an unlimited amount of distinct RESTful Web Services. You can also refer to them as MRS services. Each of those MRS services usually maps to one (or more) web applications.

After you create a RESTful Web Service, you can access it by navigating to the following URL.

Pattern:

https://<HOSTNAME:PORT>/<MRS_SERVICE_PATH>/<MRS_DATABASE_SCHEMA_PATH>/<MRS_DATABASE_OBJECT_PATH>/
  • HOSTNAME:PORT/MRS_SERVICE_PATH: Specifies the address at which the given MRS service is running. You can also refer to it as the MRS service URI.
  • MRS_DATABASE_SCHEMA_PATH: Specifies the path that you provided while REST-enabling your database schema. By default, it is the name of the schema.
  • MRS_DATABASE_OBJECT_PATH: Specifies the path that you provided while REST-enabling your database object (TABLE, VIEW or PROCEDURE).

Together, these values comprise the MRS endpoint URL.

Example:

https://localhost:8000/mrs/sakila/actor

1.2 About Request Path Syntax Requirements

To prevent path-based attacks, MRS requires the syntax of the path element of each request URL to conform to the following rules:

  • Is not empty or whitespace-only
  • Does not contain any of the following characters: ?, #, ;, %
  • Does not contain the null character (000)
  • Does not contain characters in the range: 001-031
  • Does not end with white space or a period (.)
  • Does not contain double forward slash (//) or double back slash(\)
  • Does not contain two or more periods in sequence (.., …, and so on)
  • Total length is {@value #MAX_PATH_LENGTH} characters or less
  • Does not match any of the following names (case insensitive), with or without file extensions: CON, PRN, AUX, CLOCK$, NUL, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9

If you intend to enable REST endpoints for database objects, then avoid object names that do not comply with these requirements. For example, do not create a table named #EMPS. If you do want to auto-REST enable objects that have non-compliant names, then you must use an alias that complies with the requirements.

These requirements are applied to the URL decoded form of the URL, to prevent attempted circumvention of percent encodings.

1.3 About cURL and Testing RESTful Services

Usually you can navigate to a URL of a RESTful service using a web browser. However, another way to test it is by using a command line tool like cURL.

cURL enables you to see and control what data is being sent to and received from a RESTful service.

curl -i https://localhost:8000/mrs/sakila/actor/2

This example produces a response like the following:

{
    "links": [
        {
            "rel": "self",
            "href": "http://localhost:8000/mrs/sakila/actor/2"
        }
    ],
    "actor_id": 2,
    "last_name": "WAHLBERG",
    "first_name": "NICK",
    "last_update": "2006-02-15 03:34:33.000000"
}

The -i option tells cURL to display the HTTP headers returned by the server.

2 MRS REST Queries

A MRS REST service provides access to one or more schemas (and their metadata) as well as their comprising database objects such as tables, views and procedures (and their metadata).

2.1 Get Schema Metadata

This example retrieves a list of resources available through the specified schema alias. It shows RESTful services that are created by enabling a table, view or procedure.

Pattern:

GET http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/metadata-catalog/

Example:

GET http://localhost:8000/mrs/sakila/metadata-catalog/

Result:

{
    "items": [
        {
            "name": "/actor",
            "links": [
                {
                    "rel": "describes",
                    "href": "/mrs/sakila/actor"
                },
                {
                    "rel": "canonical",
                    "href": "/mrs/sakila/metadata-catalog/actor"
                }
            ]
        },
        {
            "name": "/address",
            "links": [
                {
                    "rel": "describes",
                    "href": "/mrs/sakila/address"
                },
                {
                    "rel": "canonical",
                    "href": "/mrs/sakila/metadata-catalog/address"
                }
            ]
        }
    ],
    "limit": 25,
    "offset": 0,
    "hasMore": false,
    "count": 2,
    "links": [
        {
            "rel": "self",
            "href": "/mrs/sakila/metadata-catalog/"
        }
    ]
}

Each available resource has two hyperlinks:

  • The link with a “describes” relation points to the actual resource
  • The link with a “canonical” relation points to the resource metadata

2.2 Get Object Metadata

This example retrieves the metadata (which describes the object) of an individual object. The location of the metadata is specified by the canonical link relation.

Pattern:

GET http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/metadata-catalog/<ObjectAlias>/

Example:

GET http://localhost:8000/mrs/sakila/metadata-catalog/actor/

Result:

{
    "name": "/actor",
    "primaryKey": [
        "actor_id"
    ],
    "members": [
        {
            "name": "actor_id",
            "type": "null"
        },
        {
            "name": "first_name",
            "type": "null"
        },
        {
            "name": "last_name",
            "type": "null"
        },
        {
            "name": "last_update",
            "type": "string"
        }
    ],
    "links": [
        {
            "rel": "collection",
            "href": "/mrs/sakila/metadata-catalog",
            "mediaType": "application/json"
        },
        {
            "rel": "canonical",
            "href": "/mrs/sakila/metadata-catalog/actor"
        },
        {
            "rel": "describes",
            "href": "/mrs/sakila/actor"
        }
    ]
}

2.3 Get Object Data

This example retrieves the data in the object. Each row in the object corresponds to a JSON object embedded within the JSON array

Pattern:

GET http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/<ObjectAlias>/

Example:

GET http://localhost:8000/mrs/sakila/actor/

Result:

{
    "items": [
        {
            "links": [
                {
                    "rel": "self",
                    "href": "/mrs/sakila/actor/1"
                }
            ],
            "actor_id": 1,
            "last_name": "GUINESSS",
            "first_name": "PENELOPE",
            "last_update": "2021-09-28 20:18:53.000000"
        },
        {
            "links": [
                {
                    "rel": "self",
                    "href": "/mrs/sakila/actor/2"
                }
            ],
            "actor_id": 2,
            "last_name": "WAHLBERG",
            "first_name": "NICK",
            "last_update": "2006-02-15 03:34:33.000000"
        },
        {
            "links": [
                {
                    "rel": "self",
                    "href": "/mrs/sakila/actor/3"
                }
            ],
            "actor_id": 3,
            "last_name": "CHASE",
            "first_name": "ED",
            "last_update": "2006-02-15 03:34:33.000000"
        },
        ...
    ]
}

2.3.1 Get Table Data Using Pagination

We can specify offset and limit parameters which are used for result data pagination.

Pattern:

GET http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/<ObjectAlias>/?offset=<Offset>&limit=<Limit>

Example:

GET http://localhost:8080/mrs/sakila/actor/?offset=10&limit=2

Result:

{
    "items": [
        {
            "links": [
                {
                    "rel": "self",
                    "href": "/mrs/sakila/actor/11"
                }
            ],
            "actor_id": 11,
            "last_name": "CAGE",
            "first_name": "ZERO",
            "last_update": "2006-02-15 03:34:33.000000"
        },
        {
            "links": [
                {
                    "rel": "self",
                    "href": "/mrs/sakila/actor/12"
                }
            ],
            "actor_id": 12,
            "last_name": "BERRY",
            "first_name": "KARL",
            "last_update": "2006-02-15 03:34:33.000000"
        }
    ],
    "limit": 2,
    "offset": 10,
    "hasMore": true,
    "count": 2,
    "links": [
        {
            "rel": "self",
            "href": "/mrs/sakila/actor/"
        },
        {
            "rel": "next",
            "href": "/mrs/sakila/actor/?offset=12&limit=2"
        },
        {
            "rel": "prev",
            "href": "/mrs/sakila/actor/?offset=8&limit=2"
        },
        {
            "rel": "first",
            "href": "/mrs/sakila/actor/?limit=2"
        }
    ]
}

2.3.2 Get Table Data Using Query

We can use a filter clause to restrict the set of objects that are returned.

Pattern:

GET http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/<ObjectAlias>/?q=<FilterClause>

Example:

GET http://localhost:8080/mrs/sakila/actor/?q={"last_name":{"$like":"WAW%"}}

Result:

{
    "items": [
        {
            "links": [
                {
                    "rel": "self",
                    "href": "/mrs/sakila/actor/97"
                }
            ],
            "actor_id": 97,
            "last_name": "HAWKE",
            "first_name": "MEG",
            "last_update": "2006-02-15 03:34:33.000000"
        }
    ],
    "limit": 25,
    "offset": 0,
    "hasMore": false,
    "count": 1,
    "links": [
        {
            "rel": "self",
            "href": "/mrs/sakila/actor/"
        }
    ]
}

2.3.3 Get Table Row Using Primary Key

This example retrieves an object by specifying its identifying key values.

Note: A table requires a primary key to be part of a REST service.

Pattern:

GET http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/<ObjectAlias>/<KeyValues>

Where <KeyValues> is a comma-separated list of key values (in key order).

Example:

GET http://localhost:8000/mrs/sakila/actor/53

Result:

{
    "links": [
        {
            "rel": "self",
            "href": "/mrs/sakila/actor/53"
        }
    ],
    "actor_id": 53,
    "last_name": "TEMPLE",
    "first_name": "MENA",
    "last_update": "2006-02-15 03:34:33.000000"
}

2.4 Insert Table Row

To insert data into a table, the request body should be a JSON object that contains the data to be inserted.

If the object has a primary key, then the POST request can include the primary key value in the body. If the table has an AUTO_INCREMENT column then the primary key column may be omitted.

Pattern:

POST http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/<ObjectAlias>/

Example:

curl -i -H "Content-Type: application/json" -X POST -d "{ \"last_name\" : \"FOLEY\", \"first_name\": \"MIKE\" }" "http://localhost:8000/mrs/sakila/actor/" Content-Type: application/json

Result:

{
    "links": [
        {
            "rel": "self",
            "href": "/mrs/sakila/actor/201"
        }
    ],
    "actor_id": 201,
    "last_name": "FOLEY",
    "first_name": "MIKE",
    "last_update": "2022-11-29 15:35:17.000000"
}

2.5 Update/Insert Table Row

To insert, update or “upsert” (update if exists, insert if not) data into a table, we can send a request where the body contains a JSON object with the data to insert or update.

Pattern:

PUT http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/<ObjectAlias>/<KeyValues>

Example:

curl -i -H "Content-Type: application/json" -X PUT -d "{ \"last_name\" : \"FOLEY\", \"first_name\": \"JACK\" }" "https://localhost:8000/mrs/sakila/actor/201" Content-Type: application/json

Result:

{
    "links": [
        {
            "rel": "self",
            "href": "/mrs/sakila/actor/201"
        }
    ],
    "actor_id": 201,
    "last_name": "FOLEY",
    "first_name": "JACK",
    "last_update": "2022-11-29 15:45:10.000000"
}

2.6 Delete Using Filter

Deleting a object or other database object can be done by specifying a filter clause that identifies the object to delete.

Pattern:

DELETE http://<HOST>:<PORT>/<ServiceAlias>/<SchemaAlias>/<ObjectAlias>/?q=<FilterClause>

Example:

curl -i -X DELETE "https://localhost:8000/mrs/sakila/actor/?q=\{\"actor_id\":201\}"

Result:

{
    "itemsDeleted": 1
}

3 Filtering in REST Queries

This section details the process of filtering in queries against REST-enabled tables and views. The next section offers practical examples to illustrate the concepts.

Filtering involves the process of limiting a collection resource by using a per-request dynamic filter definition across multiple page resources. Each page contains a subset of items found in the complete collection. Filtering enables efficient traversal of large collections.

To implement filtering in a query, incorporate the parameter q=FilterObject, where FilterObject is a JSON object specifying the custom selection and sorting to be applied to the resource. To illustrate, consider the following example:

https://example.com/myService/sakila/actor/

The following query contains a filter that restricts the first_name column to “BRUCE”. Note that the REST object was created using the default JSON field mapping, which translates the database column first_name (snake_case) to the JSON field firstName (camelCase).

https://example.com/myService/sakila/actor/?q={"firstName":"BRUCE"}

3.1 FilterObject Grammar

The FilterObject must be a JSON object that complies with the following syntax:

    FilterObject { orderby , asof, wmembers }

The orderby, asof, and wmembers attributes are optional, and their definitions are as follows:

orderby
    "$orderby": {orderByMembers}

orderByMembers
    orderByProperty
    orderByProperty , orderByMembers

orderByProperty
    columnName : sortingValue

sortingValue
    "ASC"
    "DESC"
    "-1"
    "1"
    -1
    1

asof
    "$asof": gtid

wmembers
    wpair
    wpair , wmembers

wpair
    columnProperty
    complexOperatorProperty

columnProperty
    columnName : string
    columnName : number
    columnName : date
    columnName : geo
    columnName : vector
    columnName : boolean
    columnName : simpleOperatorObject
    columnName : complexOperatorObject
    columnName : [complexValues]

columnName
"\p{Alpha}[[\p{Alpha}]]([[\p{Alnum}]#$_])*$"

complexOperatorProperty
    complexKey : [complexValues]
    complexKey : simpleOperatorObject

complexKey
    "$and"
    "$or"

complexValues
    complexValue , complexValues

complexValue
    simpleOperatorObject
    complexOperatorObject
    columnObject

columnObject
    {columnProperty}

simpleOperatorObject
    {simpleOperatorProperty}

complexOperatorObject
    {complexOperatorProperty}

simpleOperatorProperty
    "$eq" : string | number | date | geo | vector | boolean
    "$ne" : string | number | date | geo | vector | boolean
    "$lt" :  number | date
    "$lte" : number | date
    "$gt" : number | date
    "$gte" : number | date
    "$instr" : string
    "$ninstr" : string
    "$like" : string
    "$null" : null
    "$notnull" : null
    "$between" : betweenValue
    "$match": fullTextSearch

betweenValue
    [null , betweenNotNull]
    [betweenNotNull , null]
    [betweenRegular , betweenRegular]

betweenNotNull
    number
    date

betweenRegular
    string
    number
    date

fullTextSearch
    {"$params":[fieldList], "$against":{"$expr":fullTextExpr}}
    {"$params":[fieldList], "$against":{"$expr":fullTextExpr, "$modifier":fullTextMod}}

Data type definitions include the following:

string
    JSONString

number
    JSONNumber

date
      {"$date":"datechars"}

gtid
    JSONString

geo
    https://en.wikipedia.org/wiki/GeoJSON

vector
    [numberList]

numberList
    number, numberList

fieldList
    fieldName, fieldList

fieldName: JSONString

fullTextExpr: JSONString

fullTextMod:
    "IN NATURAL LANGUAGE MODE"
    "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION"
    "IN BOOLEAN MODE"
    "WITH QUERY EXPANSION"

Where:

datechars is an RFC3339 date format in UTC (Z)


JSONString
        ""
        " chars "
chars
        char
        char chars
char
        any-Unicode-character except-"-or-\-or-control-character
        \"
        \\
        \/
        \b
        \f
        \n
        \r
        \t
        \u four-hex-digits


JSONNumber
    int
    int frac
    int exp
    int frac exp
int
    digit
    digit1-9 digits
    - digit
    - digit1-9 digits
frac
    . digits
exp
    e digits
digits
    digit
    digit digits
e
    e
    e+
    e-
    E
    E+
    E-

The FilterObject must be encoded according to Section 2.1 of RFC3986.

4 FilterObject Grammar Examples

4.1 ORDER BY property ($orderby)

Order by with literals

{
  "$orderby": {"SALARY":  "ASC","ENAME":"DESC"}
}

Order by with numbers

{
  "$orderby": {"SALARY":  -1,"ENAME":  1}
}

4.2 ASOF property ($asof)

With SCN (Implicit)

{
  "$asof": 1273919
}

With SCN (Explicit)

{
  "$asof": {"$scn": "1273919"}
}

With Date (Implicit)

{
  "$asof": "2014-06-30T00:00:00Z"
}

With Date (Explicit)

{
  "$asof": {"$date": "2014-06-30T00:00:00Z"}
}

4.3 EQUALS operator ($eq)

Implicit (Support String and Dates too)

{
  "SALARY": 1000
}

Explicit

{
  "SALARY": {"$eq": 1000}
}

Strings

{
  "ENAME": {"$eq":"SMITH"}
}

Dates

{
  "HIREDATE": {"$date": "1981-11-17T08:00:00Z"}
}

4.4 NOT EQUALS operator ($ne)

Number

{
  "SALARY": {"$ne": 1000}
}

String

{
  "ENAME": {"$ne":"SMITH"}
}

Dates

{
  "HIREDATE": {"$ne": {"$date":"1981-11-17T08:00:00Z"}}
}

4.5 LESS THAN operator ($lt)

(Supports dates and numbers only)

Numbers

{
  "SALARY": {"$lt": 10000}
}

Dates

{
  "SALARY": {"$lt": {"$date":"1999-12-17T08:00:00Z"}}
}

4.6 LESS THAN OR EQUALS operator ($lte)

(Supports dates and numbers only)

Numbers

{
  "SALARY": {"$lte": 10000}
}

Dates

{
  "HIREDATE": {"$lte": {"$date":"1999-12-17T08:00:00Z"}}
}

4.7 GREATER THAN operator ($gt)

(Supports dates and numbers only)

Numbers

{
  "SALARY": {"$gt": 10000}
}

Dates

{
  "SALARY": {"$gt": {"$date":"1999-12-17T08:00:00Z"}}
}

4.8 GREATER THAN OR EQUALS operator ($gte)

(Supports dates and numbers only)

Numbers

{
  "SALARY": {"$gte": 10000}
}

Dates

{
  "HIREDATE": {"$gte": {"$date":"1999-12-17T08:00:00Z"}}
}

4.9 In string operator ($instr)

(Supports strings only)

{
  "ENAME": {"$instr":"MC"}
}

4.10 Not in string operator ($ninstr)

(Supports strings only)

{
  "ENAME": {"$ninstr":"MC"}
}

4.11 LIKE operator ($like)

(Supports strings. Eescape character not supported to try to match expressions with _ or % characters.)

{
  "ENAME": {"$like":"AX%"}
}

4.12 BETWEEN operator ($between)

(Supports string, dates, and numbers)

Numbers

{
  "SALARY": {"$between": [1000,2000]}
}

Dates

{
  "SALARY": {"$between": [{"$date":"1989-12-17T08:00:00Z"},{"$date":"1999-12-17T08:00:00Z"}]}
}

Strings

{
  "ENAME": {"$between": ["A","C"]}
}

Null Ranges ($lte equivalent)
(Supported by numbers and dates only)

{
  "SALARY": {"$between": [null,2000]}
}

Null Ranges ($gte equivalent)
(Supported by numbers and dates only)

{
  "SALARY": {"$between": [1000,null]}
}

4.13 NULL operator ($null)

{
  "ENAME": {"$null": null}
}

4.14 NOT NULL operator ($notnull)

{
  "ENAME": {"$notnull": null}
}

4.15 AND operator ($and)

(Supports all operators, including $and and $or)

(Example: Salary greater than 1000 and name starts with S or T)

{
  "SALARY": {"$gt": 1000},
  "ENAME": {"$or": [{"$like":"S%"}, {"$like":"T%"}]}
}

Invalid expression (operators $lt and $gt lack column context)

{
  "$and": [{"$lt": 5000},{"$gt": 1000}]
}

Valid alternative for the previous invalid expression

{
  "$and": [{"SALARY": {"$lt": 5000}}, {"SALARY": {"$gt": 1000}}]
}

4.16 OR operator ($or)

(Supports all operators including $and and $or. Similar to High order AND)

(Example: name starts with S or salary greater than 1000)

{
  "$or": [{"SALARY":{"$gt": 1000}},{"ENAME": {"$like":"S%"}}]
}

5 Authenticate a REST User

When executing CRUD operations on a REST object that requires authentication, one must first authenticate a REST user via the corresponding linked authentication app.

5.1 MySQL Internal Authentication

In the case of a MySQL Internal auth app, the workflow is as follows. First the client must send the credentials to the /login path at the corresponding authentication endpoint, by omission /${service}/authentication/login. The client specifies the auth mechanism to use (cookie or bearer token). By default, the authentication mechanism used is based on a cookie.

Pattern:

POST http://<HOST>:<PORT>/<ServiceAlias>/<AuthPath>/login
{
    "username": "...",
    "password": "...",
    "authApp": "...",
    "sessionType": "cookie | bearer"
}

If the client requests a cookie and the authentication succeeds, the MRS backend server immediately sends back a response containing the corresponding Set-Cookie header:

Example:

curl -i -X POST -d \{\"username\":\"...\",\"password\":\"...\",\"authApp\":\"MySQL\",\"sessionType\":\"cookie\"} https://localhost:8000/mrs/authentication/login
HTTP/1.1 200 Ok
...
Set-Cookie: session_31000000000000000000000000000000=XXXXXXXXXXXXXXXXXXX; Path=/; SameSite=None; Secure; HttpOnly

If the client requests a bearer token, instead of the Set-Cookie header the response includes a JSON object in the body with an accessToken property whose value matches the generated JWT.

Example:

curl -i POST -d \{\"username\":\"...\",\"password\":\"...\",\"authApp\":\"MySQL\",\"sessionType\":\"bearer\"\} "https://localhost:8443/mrs/authentication/login"
HTTP/1.1 200 Ok
...
Content-Type: application/json
...

{"accessToken":"..."}

5.2 MRS Authentication

In the case of an MRS auth app, the workflow follows a SCRAM-style negotiation. First the client must send the credentials to the authentication endpoint. In this case, instead of the original password, the client generates and sends the initial nonce (a random hex string). Similarly, the client also specifies the auth mechanism to use (cookie or bearer token). Then the MRS backend server sends back a response containing a JSON object in the body which includes the value of all variables required to calculate the SCRAM client proof.

Pattern:

POST http://<HOST>:<PORT>/<ServiceAlias>/<AuthPath>/login
{
    "username": "...",
    "nonce": "...",
    "authApp": "...",
    "sessionType": "cookie | bearer"
}

POST http://<HOST>:<PORT>/<ServiceAlias>/<AuthPath>/login
{
    "clientProof": [...],
    "nonce": "...",
    "state": "response"
}

Example:

curl -i -X POST -d \{\"username\":\"...\",\"nonce\":\"...\",\"authApp\":\"MRS\",\"sessionType\":\"cookie\"} https://localhost:8000/mrs/authentication/login
...
{"session":"...","iterations":5000,"nonce":"...","salt":[...]}

To finish the SCRAM negotiation, the client needs to calculate the corresponding client proof send another request to the same endpoint containing that value, alongside the server-generated nonce and an additional state flag set to response. If the authentication succeeds, the MRS backend server sends back a response containing the Set-Cookie header.

Example:

curl -i -X POST -d \{\"clientProof\":[...],\"nonce\":\"...\",\"state\":\"response\"\} https://localhost:8000/mrs/authentication/login
HTTP/1.1 200 Ok
...
Set-Cookie: session_30000000000000000000000000000000=XXXXXXXXXXXXXXXXXXX; Path=/; SameSite=None; Secure; HttpOnly

If the client requests a bearer token instead, the process is exactly the same apart from the last step where, the backend server sends back a response containing JSON object in the body with an accessToken property whose value matches the generated JWT.

5.3 OAuth

In the case of an OAuth auth app, an hypermedia client like a web-browser is required, because in the initial step, the client is redirected by the MRS backend server to the authentication web page of the actual auth provider (OCI, Google or Facebook). Currently, only cookie-based authentication is supported.

Example:

curl -iG https://localhost:8443/mrs/authentication/login --data-urlencode 'authApp=Facebook'
HTTP/1.1 307 Temporary Redirect
...
Location: https://www.facebook.com/v12.0/dialog/oauth?response_type=code&state=first&client_id=XXXXXXXXXXXXX&redirect_uri=https://localhost:8443/mrs/authentication/login?authApp=Facebook

If the authentication succeeds, the auth provider redirects the client to the corresponding callback url sending the authorization code to the MRS backend server. The MRS backend server redirects the client to a different URL under its control and then sends back a response containing the Set-Cookie header.

Example:

curl -i https://localhost:8443/mrs/authentication/login --data-urlencode 'access_token=YYYYYYYYYYYY' --data-urlencode 'redirect_url=https://localhost:8443/mrs/success'
HTTP/1.1 307 Temporary Redirect
...
Location: https://www.facebook.com/v12.0/dialog/oauth?response_type=code&state=first&client_id=XXXXXXXXXXXXX&redirect_uri=https://localhost:8443/mrs/authentication/login?authApp=Facebook


curl -i https://localhost:8443/mrs/success
HTTP/1.1 200 Ok
...
Set-Cookie: session_32000000000000000000000000000000=XXXXXXXXXXXXXXXXXXX; Path=/; SameSite=None; Secure; HttpOnly

The examples are for illustrative purposes only, the workflow is entirely handled by the hypermedia client (web browser).

5.4 Executing CRUD Operations on a REST Object

Once the authentication succeeds, one can execute the CRUD operations enabled for a specific REST object that requires authentication, by including an additional header in the corresponding HTTP request. In the case of cookie-based authentication, the value of the Set-Cookie response header should be used in the Cookie request header.

Pattern:

Cookie: <Set-Cookie>

Example:

curl -H "Cookie: session_31000000000000000000000000000000=XXXXXXXXXXXXXXXXXXX; Path=/; SameSite=None; Secure; HttpOnly" https://localhost:8443/mrs/sakila/actor

In the case of token-based authentication, the JWT should be encoded in the Authorization request header as follows:

Pattern:

Authorization: Bearer XXXXXXXXXXXXXXXXX

Example:

curl -H "Authorization: Bearer XXXXXXXXXXXXXXXXX" https://localhost:8443/mrs/sakila/actor

5.4.1 Full Workflow Example

In the worst-case scenario, when the user is not yet authenticated, executing a CRUD operation on a protected REST object requires two steps which should share some kind of state, i.e. either the cookie or the bearer token need to be saved somewhere in between.

When requesting a cookie, the value of the Set-Cookie header can be extracted using curl:

$ cookie=$(curl -X POST -s -o /dev/null -w '%header{set-cookie}' -d \{\"username\":\"...\",\"password\":\"...\",\"authApp\":\"MySQL\",\"sessionType\":\"cookie\"\} "https://localhost:8443/mrs/authentication/login")
$ curl -H "Cookie: $cookie" https://localhost:8443/mrs/sakila/actor

When requesting a bearer token, since the JWT is sent in a JSON object in the response body, it can be extracted using a tool like jq:

$ jwt=$(curl -X POST -s -d \{\"username\":\"...\",\"password\":\"...\",\"authApp\":\"MySQL\",\"sessionType\":\"bearer\"\} "https://localhost:8443/mrs/authentication/login" | jq -r .accessToken)
$ curl -H "Authorization: Bearer $jwt" https://localhost:8443/mrs/sakila/actor

Copyright (c) 2022, 2025, Oracle and/or its affiliates.