go-oci8: External/kerberos authentication not working

We’re attempting to use kerberos authentication to connect to an Oracle 12.x database, using go-oci8 commit id 96a3284b269c. We can connect to the database using go-oci8 with username+password, and we can connect using sqlplus+kerberos, but when we try to use go-oci8+kerberos, it fails with:

Failed to connect to DB: ORA-01017: invalid username/password; logon denied

This problem persists whether we use a connect string directly or a host defined in our tnsnames.ora.

After some digging, we were able to successfully connect by messing around with dsn.externalauthentication. By reversing the test at https://github.com/mattn/go-oci8/blob/master/oci8.go#L323 such that it does not execute that block when dsn.externalauthentication is set to false, the connection works and we’re able to proceed normally.

Now to the meat of our question: what is the purpose of dsn.externalauthentication? Based on the name, we presume it’s when the library itself isn’t handling authentication via username and password. However, it appears to be somewhat overloaded, as setting it to true requires not just the username and password fields to be empty, but also the dsn.Connect field (https://github.com/mattn/go-oci8/blob/master/oci8.go#L125). And to reinforce that having an empty hostname is required for external auth, down at line https://github.com/mattn/go-oci8/blob/master/oci8.go#L279 there is another test for dsn.externalauthentication where, if it’s true, the database server to use is set to nil.

If dsn.externalauthentication is to be used for our use-case (kerberos authentication), how do we pass in the name of the server to connect to? And if it’s not for our use case, then how to we configure our connection string to work?

Finally, we’re happy to provide a pull request that converts “external authentication” to only requiring username and password to be empty, without also requiring the hostname to be empty, if that sounds reasonable. We’re also happy to hear what we’re doing wrong as we’re not actually well versed in kerberos authentication (this being our first attempt at using it), and if we’re missing something obvious, that doesn’t require patching go-oci8, that’s even better.

Thanks for your time and I’ll be glad to answer any follow-up questions you have.

David

Example code that we’re using to test our connection:

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/mattn/go-oci8"
)

func main() {
	// WORKS
	db, err := sql.Open("oci8", "username/password@TEST")
	// DOESN'T WORK
	// db, err := sql.Open("oci8", "/@TEST")
        // NOR DOES
	// db, err := sql.Open("oci8", "@TEST")

	if err != nil {
		fmt.Println(err)
		return
	}
	defer db.Close()
	if err = db.Ping(); err != nil {
		fmt.Printf("Error connecting to the database: %s\n", err)
		return
	} else {
		fmt.Printf("Connected successfully\n")
	}
}

where TEST is defined as a server in our tnsnames.ora:

TEST =
 (DESCRIPTION =
   (ADDRESS = (PROTOCOL = TCP)(HOST = test.foo.us-west-1.rds.amazonaws.com)(PORT = 1521))
 (CONNECT_DATA =
   (SID = ORCL)
 )
)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (8 by maintainers)

Most upvoted comments

It works in our test environment, but we want to test it against the real thing, which we hopefully should be able to do tomorrow. I will absolutely update/close this at that point. Thank you!