Tracking Failed OBIEE Logins: Client IP and User ID in WebLogic Logs

Tracking failed OBIEE logins cover: locked door and two logs linked by time

When a security audit asks for “the account, time, and IP address of every failed login,” OBIEE’s default configuration can’t answer it: the log that has the user ID has no IP address, and the log that has the IP address has no user ID. In March 2019 I reproduced failed logins on OBIEE 11g (11.1.1.7.x, WebLogic 10.3.6) and 12c (12.2.1.4) test environments to see what each log records. This post summarizes the results.

I first wrote this up in Notion in September 2024 and re-checked it against Oracle’s documentation in October 2026. Some of the log samples in that note didn’t match my screenshots from the time, so every log in this post is taken from what the screenshots actually show (only user IDs and IP addresses are changed). Oracle Analytics Server (OAS), OBIEE’s successor, also runs on WebLogic 12.2.1.4, so the WebLogic settings apply the same way, but I have not reproduced this on OAS.

The short answer: what each log records

LogClient IPUser IDFailure visibleTime
access.log (Extended format)YesNo12c: yes (redirect to login-failed.jsp)
11g: hard to tell
Yes
DefaultAuditRecorder.log (Auditing provider)NoYesYes (Severity =FAILURE)Yes
bi_server1-diagnostic.logNoNoYesYes

No single log has both the IP address and the user ID, so the practical approach is to match the IP in access.log with the user ID in DefaultAuditRecorder.log by time. In my tests the two logs matched to the second. The limit is that if several people log in during the same second, you can’t be sure which pair belongs together.

1. Record the client IP in access.log

WebLogic’s default HTTP access log format (common) doesn’t let you choose fields. Switch to the Extended format and list the fields, on the Managed Server that serves OBIEE pages (bi_server1).

  1. In the Administration Console, click Lock & Edit.
  2. Go to Environment > Servers > bi_server1 > Logging > HTTP.
  3. Make sure HTTP access log file enabled is checked.
  4. Under Advanced, set Format to Extended and enter the fields below in Extended Logging Format Fields.
  5. Save, Activate Changes, and restart bi_server1.
date time c-ip s-ip cs-method ctx-ecid ctx-rid cs-uri sc-status bytes
  • Restart: Changing the log format (LogFileFormat) requires a restart (restartNeeded: true in the WebLogic 12.2.1.4 MBean metadata).
  • Time: With the default setting (Log time in GMT off), entries use the server’s local time, so you can compare them with the audit log directly.
  • User ID fields don’t work: I also tried cs-authuser and cs-username, but they only ever logged null and -. Neither is in the field list of WebLogic’s Extended Log Format documentation, and Oracle Support Doc ID 2384515.1 (“Missing Username After Setting Up HTTP Extended Log Format”) covers the missing user name with the Extended format. I left them out of the field list above.

2. Record the failed user ID: the Auditing provider

The user ID is recorded in DefaultAuditRecorder.log by the WebLogic Auditing provider (DefaultAuditor). How to add it is covered in WebLogic Auditing: Track Changes with an Auditing Provider and Configuration Auditing; here are the points that matter for failed logins.

  • Add it under Security Realms > myrealm > Providers > Auditing > New with the type DefaultAuditor.
  • A failed login is a FAILURE event. Severity records the chosen level and every level ranked above it, so the default ERROR already records FAILURE events, along with SUCCESS events.
  • To record failures only, set Severity to CUSTOM and enable only Failure Audit Severity Enabled. In my test I enabled every level, and routine authorization checks (Authorization Audit Event V2, SUCCESS) made up most of the log.
  • Adding a provider is not a dynamic change, so restart the server unless the realm’s automatic restart is enabled.

3. Comparing the logs: 12c

These are the records when I entered a wrong password from the same PC (10.10.1.64) as user01 at 11:44:17 and as weblogic at 11:44:30.

access.log: Each login POST is followed by a redirect to login-failed.jsp, which gives you the time and IP of the failure. The user ID columns (cs-authuser, cs-username) are empty.

#Fields: date time cs-authuser cs-username c-ip s-ip cs-method ctx-ecid ctx-rid cs-uri sc-status bytes
2019-03-10 11:44:17 null - 10.10.1.64 10.10.1.102:7780 POST 8c10abaf-6a1e-4a9c-9d7b-11532b3c6639-00000579 0 /bi-security-login/login 302 681
2019-03-10 11:44:17 null - 10.10.1.64 10.10.1.102:7780 GET 8c10abaf-6a1e-4a9c-9d7b-11532b3c6639-0000057a 0 /bi-security-login/login-failed.jsp?msi=false&redirect=... 200 1167
2019-03-10 11:44:30 null - 10.10.1.64 10.10.1.102:7780 POST 8c10abaf-6a1e-4a9c-9d7b-11532b3c6639-00000580 0 /bi-security-login/login 302 681
2019-03-10 11:44:30 null - 10.10.1.64 10.10.1.102:7780 GET 8c10abaf-6a1e-4a9c-9d7b-11532b3c6639-00000581 0 /bi-security-login/login-failed.jsp?msi=false&redirect=... 200 1167

DefaultAuditRecorder.log: The failed user IDs appear at the same times. There is no IP address.

#### Audit Record Begin <Mar 10, 2019 11:44:17 AM> <Severity =FAILURE> <<<Event Type = Authentication Audit Event><user01><AUTHENTICATE>>> <FailureException =javax.security.auth.login.FailedLoginException: [Security:090938]Authentication failure: The specified user failed to log in. javax.security.auth.login.FailedLoginException: [Security:090302]Authentication Failed: User specified user denied> Audit Record End ####
#### Audit Record Begin <Mar 10, 2019 11:44:30 AM> <Severity =FAILURE> <<<Event Type = Authentication Audit Event><weblogic><AUTHENTICATE>>> <FailureException =javax.security.auth.login.FailedLoginException: [Security:090938]Authentication failure: The specified user failed to log in. javax.security.auth.login.FailedLoginException: [Security:090302]Authentication Failed: User specified user denied> Audit Record End ####

bi_server1-diagnostic.log: The authentication failure (OBI-SEC-00020) is recorded, but without the user ID or IP address (userId: <anonymous>).

[2019-03-10T11:44:30.627-05:00] [bi_server1] [NOTIFICATION] [OBI-SEC-00020] [oracle.bi.security.authentication] [tid: [ACTIVE].ExecuteThread: '38' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId: <anonymous>] [ecid: 8c10abaf-6a1e-4a9c-9d7b-11532b3c6639-...] ... The specified user credentials could not be authenticated.
javax.security.auth.login.LoginException: [Security:090938]Authentication failure: The specified user failed to log in. javax.security.auth.login.FailedLoginException: [Security:090302]Authentication Failed: User specified user denied

4. Comparing the logs: 11g

In 11g a failed login still ends with a /analytics/saw.dll?bieehome POST returning 200, so access.log alone doesn’t show the failure. In the same second the server itself (10.10.1.103) called /bisecurity/service and got a 500, and in 11g ctx-ecid and ctx-rid were logged as -.

2019-03-10 13:28:33 - - 10.10.1.64  10.10.1.103:7780 POST - - /analytics/saw.dll?bieehome 200 3228
2019-03-10 13:28:34 - - 10.10.1.103 10.10.1.103:7780 POST - - /bisecurity/service 500 512
2019-03-10 13:28:34 - - 10.10.1.64  10.10.1.103:7780 POST - - /analytics/saw.dll?bieehome 200 10852

DefaultAuditRecorder.log records the failed user ID at the same 13:28:34.

#### Audit Record Begin <Mar 10, 2019 1:28:34 PM> <Severity =FAILURE> <<<Event Type = Authentication Audit Event><user01><AUTHENTICATE>>> <FailureException =javax.security.auth.login.FailedLoginException: [Security:090304]Authentication Failed: User user01 javax.security.auth.login.FailedLoginException: [Security:090302]Authentication Failed: User user01 denied> Audit Record End ####

bi_server1-diagnostic.log records the BI Security Service rejecting the credentials, without the user ID or IP address.

[2019-03-10T13:28:34.102-04:00] [bi_server1] [ERROR] [OWS-04086] [oracle.webservices.service] ... [APP: bisecurity#11.1.1] oracle.webservices.provider.ProviderException: javax.xml.ws.WebServiceException: BI Security Service Access Denied - credentials supplied in SOAP Message header failed authentication

5. Behind a load balancer: the original client IP

Behind a load balancer or proxy, c-ip records the load balancer’s address. If the load balancer passes the original address in the X-Forwarded-For header, a WebLogic custom field can log that header. This adapts the custom field example (CustomELFLogger) from the WebLogic documentation to X-Forwarded-For.

// GWXFF.java
import weblogic.servlet.logging.CustomELFLogger;
import weblogic.servlet.logging.FormatStringBuffer;
import weblogic.servlet.logging.HttpAccountingInfo;

public class GWXFF implements CustomELFLogger {
    public void logField(HttpAccountingInfo metrics, FormatStringBuffer buff) {
        buff.appendValueOrDash(metrics.getHeader("X-Forwarded-For"));
    }
}
# Compiling needs weblogic.jar (my original note left out -cp)
javac -cp $ORACLE_HOME/wlserver/server/lib/weblogic.jar GWXFF.java
jar cvf GWXFF.jar GWXFF.class
  1. Add the JAR to the CLASSPATH used to start the server. Oracle’s documentation says not to put this class inside a web or enterprise application. Rather than editing generated scripts, append it to POST_CLASSPATH in <DOMAIN_HOME>/bin/setUserOverridesLate.sh (see the setUserOverrides notes in the boot.properties post). The setUserOverrides scripts exist from WebLogic 12.1.2, so on OBIEE 11g (WebLogic 10.3.6) set the CLASSPATH in the domain’s startup environment script instead.
  2. Add x-GWXFF to Extended Logging Format Fields. A custom field name is x- followed by the class’s fully qualified name.
  3. Restart the server.
# setUserOverridesLate.sh
POST_CLASSPATH="${POST_CLASSPATH}${CLASSPATHSEP}/u01/custom/GWXFF.jar"
export POST_CLASSPATH

# Extended Logging Format Fields
date time c-ip x-GWXFF s-ip cs-method ctx-ecid ctx-rid cs-uri sc-status bytes

A client can send X-Forwarded-For itself, so trust the value only if the load balancer is configured to overwrite it. My original note cited a cs(X-Forwarded-For) field; that comes from third-party blogs and isn’t in the field list of the WebLogic 12.2.1.4 documentation, so this post uses the documented custom field instead. My screenshots from the time don’t show this custom field’s output, so check that values actually appear in access.log after you apply it.

Things to watch

  • Oracle notes that an Auditing provider affects performance even if only a few events are logged, and that a custom log field class must not do slow work such as database or network calls, because it runs for every HTTP request.
  • Log volume grows, so plan retention and disk space with it.
  • Before production, reproduce a failed login in a test environment and compare the three logs yourself.

Summary

OBIEE has no setting that puts the IP address and user ID of a failed login on one line. Switch access.log to the Extended format to record IP addresses, use the Auditing provider to record failed user IDs, and match the two logs by time. In 12c the redirect to login-failed.jsp makes the failed request easy to find, so matching is easier than in 11g.

For WebLogic auditing in general, see WebLogic Auditing: Track Changes with an Auditing Provider and Configuration Auditing. For diagnosing slow OAS sign-ins, see OAS Sign-In Delays: When AD Users Are Fast but weblogic Is Slow.

Scroll to Top