-
Notifications
You must be signed in to change notification settings - Fork 114
feat(go/adbc/driver/flightsql): Add OAuth Support to Flight Client #2651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I would suggest to update |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, Helder, for this PR!
The only concerns I have are around thread safety.
}, nil | ||
} | ||
|
||
func (f *tokenExchange) GetToken(ctx context.Context) (*oauth2.Token, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please add RWLock here to make this method thread safe?
}, nil | ||
} | ||
|
||
func (c *clientCredentials) GetToken(ctx context.Context) (*oauth2.Token, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same question is here - should it be thread safe? If so, could you please add rwlock here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can use https://pkg.go.dev/golang.org/x/[email protected]/clientcredentials#Config instead and just call https://pkg.go.dev/golang.org/x/[email protected]/clientcredentials#Config.TokenSource
If we do that, then most of this code can be entirely removed in favor of just using https://pkg.go.dev/google.golang.org/grpc/credentials/oauth#TokenSource and https://pkg.go.dev/google.golang.org/grpc#WithPerRPCCredentials which would manage the oauth flow for us entirely as long as we can construct the token source which performs refreshes as necessary (as per the clientcredentials config above)
Essentially, SetOptions can create the TokenSource and then getFlightClient
just adds the token source as a dialoption via WithPerRPCCredentials
. That would be much more convenient and less work/code for us to maintain
@zeroshade I was not aware of that, thank you for bringing this up. While I was testing this proposal I realized that TokenSource requires transport security. I think this conflicts with development and how to run tests making it mandatory to use tls. What alternatives do I have here? The options I see:
Do you have any suggestion? |
We have a TLS suite set up already for tests here:
|
Also TokenSource on it's own shouldn't require transport security, it just has a method that returns a bool letting the caller know whether or not it requires it |
Replaced extra structs for OAuth in favor of grpc's TokenSource and grpc.DialOption WithPerRPCCredentials
* Changed OAuth tests to use TLS since it is a requirement from grpc's TokenSource and WithPerRPCCredentials * Split DoSetupSuit to setupFlightServer and setupDatabase so they can be used independently
* Removed adbc.flight.sql.token in favour of adbc.flight.sql.authorization_header when the client wants to pass a token or adbc.flight.sql.oauth.exchange.subject_token when client wants to do token exchange * Simplified options to set oauth flow. Now client can set client_credentials or token_exchange instead of integers
docs/source/driver/flight_sql.rst
Outdated
@@ -159,6 +159,12 @@ few optional authentication schemes: | |||
header will then be sent back as the ``authorization`` header on all | |||
future requests. | |||
|
|||
- (Go only) OAuth 2.0 authentication flows. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't it not Go only? Anything that uses the flightsql driver should be able to use the options that are being added. (We should add constants to the python adbc_driver_flightsql
package)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to create a separate PR for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sense to make a separate PR to add the option constants, but I would still say that the "Go only" should be removed as nothing would prevent any other binding from using these options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.#2714
Just to add to this (and this could be a follow-on PR) - what happens if https://github.com/apache/arrow-adbc/blob/a187ead78afebe85c75b466a06ad6e01ae4ac8c6/go/adbc/driver/flightsql/flightsql_statement.go#L194C21-L194C25 is part of a long running operation and the token expires? How does the token get refreshed and then continue the poll operation? By the way, this is a concern for all ADBC drivers in general, as we don't seem to have a standard way of failing "mid stream" and then "resume" the long running operation without starting it over. |
Or if
|
And for context, #2655 is making an attempt to demonstrate this capability for BigQuery in the .NET driver when using Entra authentication. The Databricks driver also needs to do this. Essentially, any OAuth protected data source could support this type of retry behavior. |
@davidhcoe I think you can refer to this comment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a couple nits, but otherwise this looks good to me! Thanks for this!
Description
This pull request introduces OAuth support to the Flight client in the GO driver. The changes include the addition of OAuth access token support, implementation of token exchange and client credentials OAuth flows.
Related Issues
Changes Made
token
as a database optiontoken
gets exchanged and the result is added to theAuthorization
header as aBearer
tokenclient_id
andclient_secret
are used to obtain a access token that is added to theAuthorization
header as aBearer
tokenHere's the markdown code for the OAuth 2.0 configuration options table:
markdown# OAuth 2.0 Configuration Options
adbc.flight.sql.oauth.flow
client_credentials
,token_exchange
adbc.flight.sql.oauth.client_id
adbc.flight.sql.oauth.client_secret
adbc.flight.sql.oauth.token_uri
adbc.flight.sql.oauth.scope
"read.all offline_access"
)adbc.flight.sql.oauth.exchange.subject_token
adbc.flight.sql.oauth.exchange.subject_token_type
adbc.flight.sql.oauth.exchange.actor_token
adbc.flight.sql.oauth.exchange.actor_token_type
adbc.flight.sql.oauth.exchange.aud
adbc.flight.sql.oauth.exchange.resource
adbc.flight.sql.oauth.exchange.scope
adbc.flight.sql.oauth.exchange.requested_token_type
Supported token types:
urn:ietf:params:oauth:token-type:access_token
urn:ietf:params:oauth:token-type:refresh_token
urn:ietf:params:oauth:token-type:id_token
urn:ietf:params:oauth:token-type:saml1
urn:ietf:params:oauth:token-type:saml2
urn:ietf:params:oauth:token-type:jwt