ORA-01017: Invalid Username/Password – Complete Guide

Last Updated: December 2025 | Oracle 19c/21c | By Ahaaryo

Oracle Version Scope: This guide covers Oracle 19c (fully supported) and Oracle 21c (Innovation Release, already desupported but widely deployed).


ORA-01017 invalid username password error showing Oracle authentication architecture, password hashing versions, and troubleshooting workflow for Oracle 19c/21c databases

Introduction

“The password is definitely correct!” – Every DBA has said this at least once while troubleshooting ORA-01017 invalid username password.

I remember a production incident at 2 AM. The monitoring application couldn’t connect to the database. The password hadn’t changed, the connection string was correct, but login kept failing. After investigating, I discovered the account had automatically expired due to a password policy the application team didn’t know existed.

ORA-01017 seems straightforward – wrong username or password, right? But there are actually 7 different root causes, and several involve Oracle’s authentication mechanisms that many DBAs don’t fully understand. In this comprehensive guide, I’ll explain not just HOW to fix ORA-01017, but WHY each solution works at the technical level.


What is ORA-01017?

Error Message:

ORA-01017: invalid username/password; logon denied

What it means: Oracle’s authentication process failed. This could be due to incorrect credentials, account status issues, authentication configuration problems, or connection misrouting.

When it occurs:

  • SQL*Plus login fails
  • Application database connections fail
  • Database links stop working
  • Scheduled jobs fail to authenticate
  • SQL Developer/Toad cannot connect
  • Service accounts suddenly lose access

Critical Oracle Authentication Concepts

Before diving into troubleshooting, understanding these Oracle authentication fundamentals will save you hours of frustration.

1. Password Case Sensitivity & Hashing Versions

Oracle’s password case sensitivity depends on which password hashing algorithm is active:

sql

-- Check user's password versions
SELECT username, password_versions
FROM dba_users
WHERE username = 'SCOTT';

-- Possible values:
-- 10G  : Legacy DES hash (case-INSENSITIVE if this exists)
-- 11G  : SHA-1 hash (case-sensitive)
-- 12C  : SHA-2 hash (case-sensitive, strongest)

Critical Rule:

  • If 10G version exists → Password is case-INSENSITIVE
  • If only 11G or 12C exists → Password is case-SENSITIVE
  • Best practice: Remove 10G hash for security

Example:

sql

-- User with only 12C hash
SELECT password_versions FROM dba_users WHERE username = 'APPUSER';
-- Result: 12C

-- These will have different behaviors:
CONNECT appuser/MyPassword    -- Works
CONNECT appuser/mypassword    -- ORA-01017 (case matters!)
CONNECT appuser/MYPASSWORD    -- ORA-01017

2. Password Special Characters (The Double Quote Rule)

CRITICAL: Passwords containing special characters MUST be enclosed in double quotes during password setting. The quotes are NOT part of the password.

sql

-- CORRECT - Special characters require quotes during ALTER
ALTER USER app_user IDENTIFIED BY "P@ssw0rd!2024";

-- WRONG - Without quotes, Oracle interprets @ as SQL*Plus variable
ALTER USER app_user IDENTIFIED BY P@ssw0rd!2024;
-- Results in: SP2-0042: unknown command

-- When connecting, quotes are needed:
CONNECT app_user/"P@ssw0rd!2024"

Common special characters requiring quotes:

  • @ # $ % ^ & * ( ) ! + = { } [ ] | : ; ' " < > , . ? /

3. Username Case Sensitivity (Quoted Identifiers)

Default behavior: Unquoted usernames are stored in UPPERCASE.

sql

-- These are IDENTICAL - both create user "SCOTT"
CREATE USER scott IDENTIFIED BY tiger;
CREATE USER SCOTT IDENTIFIED BY tiger;

-- Both stored as: SCOTT (uppercase)

-- This creates a DIFFERENT user: "Scott" (case-preserved)
CREATE USER "Scott" IDENTIFIED BY tiger;

Connection implications:

sql

-- For normal user (created without quotes)
CONNECT scott/tiger           -- Works
CONNECT SCOTT/tiger           -- Works  
CONNECT "scott"/tiger         -- ORA-01017 (no such user)

-- For quoted user (created with quotes)
CREATE USER "Scott" IDENTIFIED BY tiger;
CONNECT "Scott"/tiger         -- Works
CONNECT scott/tiger           -- ORA-01017
CONNECT SCOTT/tiger           -- ORA-01017

Best Practice: Avoid quoted usernames unless absolutely necessary. They create confusion and break automation scripts.

4. The sec_case_sensitive_logon Parameter

sql

-- Check current setting
SHOW PARAMETER sec_case_sensitive_logon;

-- Disable case sensitivity (NOT RECOMMENDED)
ALTER SYSTEM SET sec_case_sensitive_logon = FALSE;

Important Notes:

  • Setting to FALSE is a security downgrade
  • Do NOT use this as a fix – properly set passwords instead

Version Status:

VersionStatus
12c✅ Supported
18c✅ Supported
19c⚠️ Deprecated (documented)
21c❌ Desupported
23ai❌ Removed

The 7 Root Causes of ORA-01017

Cause 1: Wrong Password (Most Common – 60% of cases)

Problem: The password provided doesn’t match Oracle’s stored hash.

Diagnosis:

sql

-- You cannot retrieve passwords - only reset them
-- Connect as SYSDBA
sqlplus / as sysdba

-- Check if user exists
SELECT username, account_status 
FROM dba_users 
WHERE username = 'APPUSER';

Solution:

sql

-- Reset password
ALTER USER appuser IDENTIFIED BY "NewSecure123!";

-- Test connection
CONNECT appuser/"NewSecure123!"

Why it works: Oracle hashes the new password using the configured algorithm (11G/12C) and stores it. During login, Oracle hashes the provided password and compares hashes.


Cause 2: Password Case Mismatch

Problem: Password has correct characters but wrong case, and user only has 11G/12C hash (no 10G hash for case-insensitive fallback).

Diagnosis:

sql

-- Check password versions
SELECT username, password_versions
FROM dba_users
WHERE username = 'APPUSER';

-- If result shows: 11G 12C (no 10G)
-- Then password IS case-sensitive

Solution:

sql

-- Try different cases manually
CONNECT appuser/MyPassword
CONNECT appuser/mypassword  
CONNECT appuser/MYPASSWORD

-- Or reset with known case
ALTER USER appuser IDENTIFIED BY "MyPassword";

Technical Detail: The 10G hash algorithm (DES) uppercases passwords before hashing. 11G (SHA-1) and 12C (SHA-2) hash the password exactly as provided, making them case-sensitive.


Cause 3: Account is Locked

Problem: Account locked due to failed login attempts or manual lock.

Diagnosis:

sql

SELECT username, account_status, lock_date
FROM dba_users
WHERE username = 'APPUSER';

-- Status shows: LOCKED or LOCKED(TIMED)

Solution:

sql

-- Unlock the account
ALTER USER appuser ACCOUNT UNLOCK;

-- Test
CONNECT appuser/correct_password

To prevent auto-locking for service accounts:

sql

-- Create service profile with unlimited failed attempts
CREATE PROFILE svc_profile LIMIT
  FAILED_LOGIN_ATTEMPTS UNLIMITED
  PASSWORD_LIFE_TIME UNLIMITED;

-- Assign to service account
ALTER USER appuser PROFILE svc_profile;

Cause 4: Password Expired

Problem: Password lifetime exceeded based on profile settings.

Diagnosis:

sql

SELECT username, account_status, expiry_date
FROM dba_users  
WHERE username = 'APPUSER';

-- Status shows: EXPIRED or EXPIRED(GRACE)

Solution:

sql

-- Reset password (also removes expiry)
ALTER USER appuser IDENTIFIED BY "NewPassword123!";

-- For service accounts, use unlimited lifetime
ALTER USER appuser IDENTIFIED BY "NewPassword123!"
  PROFILE svc_profile;

Cause 5: Quoted Username Mismatch

Problem: User was created with quotes, but connecting without quotes (or vice versa).

Diagnosis:

sql

-- Check exact username as stored
SELECT username, created 
FROM dba_users 
WHERE UPPER(username) = 'SCOTT';

-- If username shows as "Scott" (mixed case)
-- → User was created with quotes

Solution:

sql

-- For quoted user, use quotes when connecting
CONNECT "Scott"/tiger

-- To avoid confusion, recreate without quotes
DROP USER "Scott";
CREATE USER scott IDENTIFIED BY tiger;
-- Now stored as: SCOTT (uppercase)

Real-world scenario:

sql

-- Developer accidentally creates:
CREATE USER "AppUser" IDENTIFIED BY pass123;

-- Later, connection fails:
CONNECT appuser/pass123     -- ORA-01017

-- Must use:
CONNECT "AppUser"/pass123   -- Works

Cause 6: Wrong Service Name or Connection String

Problem: Connecting to wrong database service entirely.

Diagnosis:

sql

-- On the database server, check service names
SELECT value FROM v$parameter WHERE name = 'service_names';

-- List all available services
SELECT name, con_id FROM v$services ORDER BY con_id;

-- From client, test connection
tnsping YOUR_SERVICE_NAME

Solution:

bash

# Correct connection format
sqlplus username/password@hostname:port/service_name

# Example
sqlplus appuser/"Pass123"@dbserver:1521/PROD

# Or update tnsnames.ora correctly
PROD =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = dbserver)(PORT = 1521))
    (CONNECT_DATA = (SERVICE_NAME = PROD))
  )

Common mistake:

bash

# Using database name instead of service name
sqlplus user/pass@host:1521/ORCL    # Wrong if service is PROD

# Check database name vs service name - they CAN be different!

Cause 7: Wrong PDB in Multitenant (12c+)

Problem: In multitenant architecture, user exists in a specific PDB but you’re connecting to CDB$ROOT or a different PDB.

Diagnosis:

sql

-- Connect to CDB as SYSDBA
sqlplus / as sysdba

-- Check which container(s) user exists in
SELECT con_id, username, account_status
FROM cdb_users
WHERE username = 'APPUSER'
ORDER BY con_id;

-- Result example:
-- CON_ID  USERNAME   ACCOUNT_STATUS
-- ------  ---------  --------------
--      1  APPUSER    OPEN           <- CDB$ROOT
--      3  APPUSER    OPEN           <- PDB1

Solution:

bash

# Connect directly to the correct PDB
sqlplus appuser/password@hostname:1521/PDB1

# Or connect to CDB first, then switch container
sqlplus / as sysdba
ALTER SESSION SET CONTAINER = PDB1;
CONNECT appuser/password;

Verify PDB services:

sql

-- List PDB service names
SELECT name AS service_name, con_id
FROM v$services
WHERE con_id > 1;

Real-world example:

sql

-- User exists only in PDB1, but connection string points to CDB
-- Wrong:
sqlplus appuser/pass@host:1521/CDB1    -- ORA-01017

-- Correct:
sqlplus appuser/pass@host:1521/PDB1    -- Success

Complete Troubleshooting Workflow

Follow this systematic approach to diagnose ORA-01017:

Step 1: Verify Username Existence and Container

sql

sqlplus / as sysdba

-- Non-CDB environment
SELECT username, account_status, lock_date, expiry_date,
       password_versions, profile
FROM dba_users
WHERE username = 'YOUR_USERNAME';

-- CDB/PDB environment  
SELECT con_id, username, account_status, password_versions
FROM cdb_users
WHERE username = 'YOUR_USERNAME'
ORDER BY con_id;

Interpretation:

  • No rows: Username doesn’t exist → CREATE USER
  • Multiple CON_IDs: Exists in multiple containers → Connect to correct PDB
  • Account_status: Determines next troubleshooting step

Step 2: Check Account Status

StatusMeaningAction Required
OPENActive, password is wrongReset password
LOCKEDToo many failed attemptsACCOUNT UNLOCK
EXPIREDPassword lifetime exceededReset password
EXPIRED & LOCKEDBoth problemsReset password AND unlock
EXPIRED(GRACE)In grace periodReset password soon

Fix commands:

sql

-- For LOCKED
ALTER USER username ACCOUNT UNLOCK;

-- For EXPIRED or EXPIRED & LOCKED  
ALTER USER username IDENTIFIED BY "NewPass123!";

-- Combined fix
ALTER USER username IDENTIFIED BY "NewPass123!" ACCOUNT UNLOCK;

Step 3: Verify Password Case Sensitivity

sql

-- Check hashing versions
SELECT password_versions FROM dba_users WHERE username = 'APPUSER';

-- If 11G or 12C only (no 10G), password is case-sensitive
-- Try exact case from documentation or reset
ALTER USER appuser IDENTIFIED BY "KnownPassword";

Step 4: Check for Quoted Username

sql

-- This query finds case-sensitive usernames
SELECT username 
FROM dba_users 
WHERE username != UPPER(username);

-- If your username appears, it was created with quotes
-- Connect using: CONNECT "ExactCase"/password

Step 5: Verify Service Name and PDB

sql

-- Check available service names
SELECT value FROM v$parameter WHERE name = 'service_names';

-- For CDB, list PDB services
SELECT pdb_name, service_name FROM cdb_services;

-- Test from client
tnsping YOUR_SERVICE_NAME

Step 6: Test Connection

bash

# Try connecting with explicit service
sqlplus username/"password"@host:port/service_name

# For PDB
sqlplus username/"password"@host:port/pdb_service_name

Preventing ORA-01017 Issues

1. Service Account Password Management

sql

-- Create service account profile
CREATE PROFILE svc_unlimited LIMIT
  PASSWORD_LIFE_TIME UNLIMITED
  PASSWORD_REUSE_TIME UNLIMITED
  PASSWORD_LOCK_TIME UNLIMITED
  FAILED_LOGIN_ATTEMPTS UNLIMITED;

-- Create service account
CREATE USER batch_svc IDENTIFIED BY "Secure!Pass2024"
  DEFAULT TABLESPACE users
  TEMPORARY TABLESPACE temp
  PROFILE svc_unlimited;

-- Grant required privileges
GRANT CONNECT, RESOURCE TO batch_svc;

2. Password Complexity Standards

Implement password verification function:

sql

-- Example verification function
CREATE OR REPLACE FUNCTION verify_password
(username varchar2,
 password varchar2,
 old_password varchar2)
RETURN boolean IS
BEGIN
   -- Check length (minimum 12 characters)
   IF LENGTH(password) < 12 THEN
      RAISE_APPLICATION_ERROR(-20001, 'Password too short');
   END IF;
   
   -- Check complexity (must have upper, lower, digit, special)
   IF NOT REGEXP_LIKE(password, '([A-Z])') OR
      NOT REGEXP_LIKE(password, '([a-z])') OR  
      NOT REGEXP_LIKE(password, '([0-9])') OR
      NOT REGEXP_LIKE(password, '([!@#$%^&*])') THEN
      RAISE_APPLICATION_ERROR(-20002, 'Password lacks complexity');
   END IF;
   
   RETURN(TRUE);
END;
/

-- Assign to profile
ALTER PROFILE default LIMIT
  PASSWORD_VERIFY_FUNCTION verify_password;

3. Monitor Account Status

sql

-- Daily monitoring script
SELECT username, account_status, 
       expiry_date,
       ROUND(expiry_date - SYSDATE) days_until_expiry
FROM dba_users
WHERE (account_status != 'OPEN'
       OR expiry_date < SYSDATE + 7)
  AND username NOT IN ('SYS','SYSTEM','DBSNMP','XS$NULL')
ORDER BY expiry_date;

4. Document Connection Strings

Maintain connection documentation:

Environment | Host        | Port | Service Name | PDB
----------- | ----------- | ---- | ------------ | ------
Production  | dbprod1     | 1521 | PRODDB       | PDB1
UAT         | dbuat1      | 1521 | UATDB        | PDB2  
Dev         | dbdev1      | 1521 | DEVDB        | PDB3

5. Connection Testing Script

bash

#!/bin/bash
# test_connections.sh

USERS="appuser1 appuser2 batch_svc reporting"
SERVICE="dbprod:1521/PRODDB"

for user in $USERS; do
  echo -n "Testing $user@$SERVICE... "
  echo "exit" | sqlplus -S $user/password@$SERVICE >/dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo "OK"
  else
    echo "FAILED - ORA-01017"
  fi
done

Advanced Troubleshooting Scenarios

Scenario 1: Database Link Fails After Password Change

sql

-- Check existing database links
SELECT db_link, username, host
FROM dba_db_links;

-- Test link
SELECT * FROM dual@REMOTE_DB;
-- ORA-01017 via database link

-- Fix: Update database link with new password
DROP DATABASE LINK remote_db;

CREATE DATABASE LINK remote_db
  CONNECT TO remote_user IDENTIFIED BY "NewPassword123"
  USING 'remote_tns';

Scenario 2: SQLPLUS Works but Application Fails

Diagnosis:

sql

-- Check application user from application server
sqlplus appuser/password@connection_string

-- If this works but app fails, check:
-- 1. Application's connection string
-- 2. Special characters in password (app may not escape properly)
-- 3. Application using wrong service/PDB

Solution:

  • Review application configuration file
  • Check application logs for actual connection string used
  • Consider simpler password without special characters for app accounts

Scenario 3: Intermittent ORA-01017

Possible causes:

  1. Multiple passwords in use (some cached connections still use old)
  2. RAC node configuration differences
  3. Password about to expire (EXPIRED(GRACE) status)

Diagnosis:

sql

-- Check grace period
SELECT username, account_status, expiry_date,
       ROUND(expiry_date - SYSDATE) days_until_expiry
FROM dba_users
WHERE username = 'APPUSER';

-- Check RAC password file consistency
SELECT * FROM v$pwfile_users WHERE username = 'APPUSER';

Key Takeaways

The ORA-01017 Quick Reference:

  1. Passwords with special characters → Always use double quotes
  2. Password case matters → Unless user has 10G hash (not recommended)
  3. Username case matters → Only if created with quotes (avoid this)
  4. Check account status first → LOCKED, EXPIRED most common after wrong password
  5. Verify service name → Often overlooked in multitenant environments
  6. Check correct PDB → User might exist in different PDB than expected
  7. Never use sec_case_sensitive_logon=FALSE → Deprecated, insecure

Best Practices:

  • ✅ Service accounts: UNLIMITED password lifetime
  • ✅ Document all passwords in secure vault
  • ✅ Avoid quoted usernames
  • ✅ Use strong passwords with complexity requirements
  • ✅ Monitor account status proactively
  • ✅ Test connections after any password changes
  • ✅ Keep only 11G/12C hashes (remove 10G for security)

Conclusion

ORA-01017 is deceptively simple on the surface but reveals Oracle’s sophisticated authentication architecture when you dig deeper. Understanding password hash versions, case sensitivity rules, and multitenant container awareness transforms you from someone who just resets passwords to someone who can architect secure, maintainable authentication strategies.

The next time you encounter ORA-01017, you’ll know exactly where to look and why each solution works at the technical level. That’s the difference between fixing a symptom and understanding the system.

Have you encountered ORA-01017 in an unusual scenario not covered here? Share your experience in the comments!

Additional Resources


Related Posts:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.