'Authenticate with My Oracle Support Website

I realized my StackOverflow presence is basically nonexistent, so I figured I'd spruce the place up a bit with an official question.

I'm having trouble authenticating to the Oracle Support website to download patches, and a few other items. This will be used in an automated pipeline and needs to be non-interactive.

Background

I'm working in an enterprise environment and need a way to download objects out of Oracle's support website. Their solution is to give you a single-purpose shell script that uses wget to authenticate, and then pull down a file. It works, but it's interactive, single-purpose, and doesn't lend itself to being automated very easily.

The script given by Oracle's website uses the following snippet to get (what I assume are) authenticated session cookies:

wget --secure-protocol=auto --save-cookies='./cookiefile' --keep-session-cookies --http-user "$SSO_USERNAME" --ask-password "https://updates.oracle.com/Orion/Services/download" -O /dev/null 2>> "$LOGFILE"

And then reuses the cookies generated in the authenticating request to download the target file:

wget --load-cookies="./cookiefile" "https://updates.oracle.com/Orion/Services/download/p6880880_122010_Linux-x86-64.zip?aru=24233312&patch_file=p6880880_122010_Linux-x86-64.zip" -O "$OUTPUT_DIR/p6880880_122010_Linux-x86-64.zip" >> "$LOGFILE" 2>&1

-- Meta --

GNU bash, version 5.0.18(1)-release

python 3.9.5

requests 2.25.1

wget 1.21.1

Goal

For these types of tasks I prefer Python. I could just use bash, but at this point it's a challenge.

I want to be able to pass my script a list of objects to download from Oracle, have it authenticate with the My Oracle Support site (MOS) using credentials set in environment variables, and then download each of the objects in the list to the local directory.

Problem

My main problem is authentication. I've converted the wget parameters to the equivalent in the Python 3 requests library as best I can, but no matter what I try I get a 401 Authorization Required.

Things I've noted:

  • Changing the User-Agent header seems to be required. If the website things you're coming from a browser it just sends back the login page HTML.
  • Using a session object should help maintain cookies/headers across requests, but I'm not sure I understood the documentation properly.
  • I've tried using different authentication formats, including the default "BasicAuth" and "BasicAuthDigest"

My code so far

creds = get_credentials()

session = requests.Session()

session.headers.update({"User-Agent": "Wget/1.21.1"})

login = session.get(
    "https://updates.oracle.com/Orion/Services/download",
    auth=creds
)

I try to use the above snippet to authenticate with the website. You can assume for this question that get_credentials() will return an appropriate tuple.

The following are the debugging output (for the most part). Certain parts are truncated for privacy/brevity.

request url: https://login.oracle.com:443/oam/server/obrareq.cgi?encquery%3DALMCapFQLcY68rvFp... (truncated)
request status code: 401
request reason: Authorization Required
request content: b''
request headers: {'via': '<company> Proxy', 'Date': 'Tue, 08 Jun 2021 09:41:48 GMT', 'Pragma': 'no-cache', 'Server': 'Oracle-HTTP-Server', 'Expires': '0', 'Connection': 'Keep-Alive', 'Set-Cookie': 'OAM_BASIC_CTXT=VERSION_4~(truncated); path=/, login-ext-prod_iper=976787356.23313.0000; path=/; Httponly; Secure', 'Content-Type': 'text/html; charset=UTF-8', 'Cache-Control': 'no-cache, no-store', 'Content-Length': '0', 'Content-Language': 'en', 'WWW-Authenticate': 'Basic realm="OAM 11g"'}

This is as much information as I can currently provide. If I've missed anything of use please let me know in the comments!



Solution 1:[1]

Maybe getMosPatch.sh does what you want. We use it to automate patch downloading. You can read more about it here and and at the pythian site It could safe you some time to use this as a starting point. It would be nice to find your code back in GitHub when ready.

Solution 2:[2]

It looks like you need call session.get again on the final URL that is returned from the redirected request to https://updates.oracle.com/Orion/Services/download with your credentials, then make a call to whatever page you want.

This is working for me:

session = requests.Session()
basic_auth = HTTPBasicAuth(username, password)
session.auth = basic_auth

response = session.get("https://updates.oracle.com/Orion/Services/download")
response = session.get(response.url)
response = session.get("https://updates.oracle.com/Orion/SavedSearches/switch_to_simple")
print(f"Response Code: {response.status_code}")
print(f"Headers: {response.headers}")
print(f"Body: {response.text}")

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 CowboyNick