r-dbi / odbc

Connect to ODBC databases (using the DBI interface)
https://odbc.r-dbi.org/
Other
388 stars 107 forks source link

Allow `uid` to be specified when using `authenticator="externalbrowser"` #817

Closed ray-pacheco closed 2 months ago

ray-pacheco commented 3 months ago

For our Snowflake instance we have external auth set up, but the connection string requires we pass our user name. Currently odbc::snowflake() does not allow you to pass uid without also providing pwd. Not sure if our setup is common, but I would like to be able to pass the uid when authenticator is specified without requiring pwd be specified as well.

# specifying authenticator as externalbrowser as is in the documentation example gives error requiring uid specified
con <- DBI::dbConnect(odbc::snowflake(),
                      account = "testorg-test_account",
                      authenticator = "externalbrowser")
#> Error in `DBI::dbConnect()`:
#> ! ODBC failed with error 28000 from [Snowflake][DSI].
#> ✖  (20032) Required setting 'UID' is not present in the connection settings.
#> ℹ From 'nanodbc/nanodbc.cpp:1150'.
#> Backtrace:
#>      ▆
#>   1. ├─DBI::dbConnect(...)
#>   2. ├─DBI::dbConnect(...)
#>   3. │ └─odbc (local) .local(drv, ...)
#>   4. │   ├─rlang::inject(dbConnect(odbc(), !!!args))
#>   5. │   ├─DBI::dbConnect(...)
#>   6. │   └─odbc::dbConnect(...)
#>   7. │     └─odbc (local) .local(drv, ...)
#>   8. │       └─odbc:::OdbcConnection(...)
#>   9. │         ├─base::withCallingHandlers(...)
#>  10. │         └─odbc:::odbc_connect(...)
#>  11. └─odbc (local) `<fn>`("nanodbc/nanodbc.cpp:1150: 28000\n[Snowflake][DSI] (20032) Required setting 'UID' is not present in the connection settings. ")
#>  12.   └─cli::cli_abort(...)
#>  13.     └─rlang::abort(...)

# specifying uid and authenticator as externalbrowser  gives error requiring pwd specified
con <- DBI::dbConnect(odbc::snowflake(),
                      account = "testorg-test_account",
                      uid = "me@user.org",
                      authenticator = "externalbrowser")
#> Error in `DBI::dbConnect()`:
#> ! Both `uid` and `pwd` must be specified to authenticate.
#> ℹ Or leave both unset to use ambient Snowflake credentials.
#> Backtrace:
#>     ▆
#>  1. ├─DBI::dbConnect(...)
#>  2. └─DBI::dbConnect(...)
#>  3.   └─odbc (local) .local(drv, ...)
#>  4.     └─odbc:::snowflake_args(...)
#>  5.       └─odbc:::snowflake_auth_args(account, ...)
#>  6.         └─rlang::abort(...)
#>  

# I am able to get around this today by sending a blank password, but this probably is not ideal
con <- DBI::dbConnect(odbc::snowflake(),
                      account = "testorg-test_account",
                      uid = "me@user.org",
                      pwd = "",
                      authenticator = "externalbrowser")
hadley commented 3 months ago

cc @atheriel

atheriel commented 3 months ago

Yeah this makes perfect sense, we should update the check to allow externalbrowser as well.

simonpcouch commented 2 months ago

Had a slightly different experience with this today--when connecting, I saw:

con <- dbConnect(snowflake(), authenticator = "externalbrowser")
#> Error in `dbConnect()`:
#> ! ODBC failed with error 00000 from [Snowflake][DSI].
#> ✖  (20032) Required setting 'UID' is not present in the connection settings.

So I set:

con <- dbConnect(snowflake(), authenticator = "externalbrowser", UID = "my@email.com")

...and the connection worked fine. I didn't look at the snowflake() docs, but if I had, I would have seen that the case is uid in dbConnect(snowflake()) and passed the argument with that case:

con <- dbConnect(snowflake(), authenticator = "externalbrowser", uid = "my@email.com")
#> Error in `DBI::dbConnect()`:
#> ! Both `uid` and `pwd` must be specified to authenticate.
#> ℹ Or leave both unset to use ambient Snowflake credentials.

So, for now, another workaround is to change the case of uid, but this is another place of being bit by the case-insensitivity of argument keys in ODBC.

All that said, this is worth fixing. :)