Skip to content
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

SNOW-1825482: PAT + OAuth Authorization Code + OAuth Client Credentials support #1978

Open
wants to merge 33 commits into
base: master
Choose a base branch
from

Conversation

sfc-gh-dheyman
Copy link
Contributor

@sfc-gh-dheyman sfc-gh-dheyman commented Nov 30, 2024

Overview

SNOW-1825482: PAT + OAuth Authorization Code + OAuth Client Credentials support

Pre-review self checklist

  • PR branch is updated with all the changes from master branch
  • The code is correctly formatted (run mvn -P check-style validate)
  • New public API is not unnecessary exposed (run mvn verify and inspect target/japicmp/japicmp.html)
  • The pull request name is prefixed with SNOW-XXXX:
  • Code is in compliance with internal logging requirements

External contributors - please answer these questions before submitting a pull request. Thanks!

  1. What GitHub issue is this PR addressing? Make sure that there is an accompanying issue to your PR.

    Issue: #NNNN

  2. Fill out the following pre-review checklist:

    • I am adding a new automated test(s) to verify correctness of my new code
    • I am adding new logging messages
    • I am modifying authorization mechanisms
    • I am adding new credentials
    • I am modifying OCSP code
    • I am adding a new dependency or upgrading an existing one
    • I am adding new public/protected component not marked with @SnowflakeJdbcInternalApi (note that public/protected methods/fields in classes marked with this annotation are already internal)
  3. Please describe how your code solves the related issue.

    Please write a short description of how your code change solves the related issue.

@sfc-gh-dheyman sfc-gh-dheyman marked this pull request as ready for review December 4, 2024 15:12
@sfc-gh-dheyman sfc-gh-dheyman requested a review from a team as a code owner December 4, 2024 15:12
@sfc-gh-dheyman sfc-gh-dheyman changed the title OAuth Authorization Code flow using Nimbus OAuth 2.0 SDK SNOW-1825482: OAuth Authorization Code flow (Snowflake + Okta) Dec 4, 2024
@snowflakedb snowflakedb deleted a comment from gitguardian bot Dec 4, 2024
Copy link

gitguardian bot commented Dec 4, 2024

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

ci/scripts/check_content.sh Outdated Show resolved Hide resolved
@@ -218,6 +219,11 @@
<artifactId>nimbus-jose-jwt</artifactId>
<version>${nimbusds.version}</version>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>oauth2-oidc-sdk</artifactId>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have security review finished for this library?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet

src/main/java/net/snowflake/client/core/SFLoginInput.java Outdated Show resolved Hide resolved
TokenRequest request = buildTokenRequest(loginInput, authorizationCode, pkceVerifier);
URI requestUri = request.getEndpointURI();
logger.debug(
"Requesting access token from: " + requestUri.getAuthority() + requestUri.getPath());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use logger parameters instead of string concatenation, also in other logs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@sfc-gh-jszczerbinski sfc-gh-jszczerbinski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me in general, I will need a second look once I get some more knowledge about OAuth

@@ -29,6 +29,12 @@ public enum SFSessionProperty {
AUTHENTICATOR("authenticator", false, String.class),
OKTA_USERNAME("oktausername", false, String.class),
PRIVATE_KEY("privateKey", false, PrivateKey.class),
OAUTH_REDIRECT_URI("redirectUri", false, String.class),
CLIENT_ID("clientID", false, String.class),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oauthClientId, oauthClientSecret etc.?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer not to introduce new parameters, after all user can use only one authentication type at a time

},
"bodyPatterns": [
{
"contains": "grant_type=authorization_code&code=123&redirect_uri=http%3A%2F%2Flocalhost%3A8001%2Fsnowflake%2Foauth-redirect&code_verifier="
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please verify if we indeed use PKCE

Copy link
Contributor Author

@sfc-gh-dheyman sfc-gh-dheyman Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we need to.

}

@Test
public void browserTimeoutFlowScenario() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These error tests seem very similar, maybe we could make them parameterized? For keeping descriptive names, see Arguments.argumentSet (in case of @ArgumentProvider).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd do it after client credentials flow is added, because I'm not yet sure if these will remain as they are.

/*
* Authorization code flow with browser popup
*/
OAUTH_AUTHORIZATION_CODE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe CLIENT_OAUTH would be a good name from this OAuth flows to make it different than OAuth and indicate it's on client side, WDYT? @sfc-gh-dprzybysz @sfc-gh-dheyman @sfc-gh-pfus

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like it. CLIENT_OAUTH is too generic. Dawid's name seems better to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather change the original OAUTH authenticator to OAUTH_ACCESS_TOKEN or something like that, but I understand it would be a BCR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sfc-gh-eworoshow WDYT? did you go through any naming discussion already

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a couple options:

  1. AUTHENTICATOR=OAUTH plus OAUTH_FLOW={TOKEN | AUTHORIZATION_CODE | CLIENT_CREDENTIALS }, where TOKEN is our existing default.
  2. AUTHENTICATOR={OAUTH | OAUTH_ACCESS_TOKEN, alias of OAUTH | OAUTH_AUTHORIZATION_CODE | ... }.

In both cases I think we should use the "standard" name for the OAuth flow we're implementing.

@@ -14,11 +14,6 @@
<Source><Package name="com.nimbusds.jose"/></Source>
<Reason>Optional</Reason>
</LinkageError>
<LinkageError>
<Target><Package name="org.brotli.dec"/></Target>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want to delete these lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored.

/*
* Authorization code flow with browser popup
*/
OAUTH_AUTHORIZATION_CODE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like it. CLIENT_OAUTH is too generic. Dawid's name seems better to me.

String code = codeFuture.get(this.browserAuthorizationTimeoutSeconds, TimeUnit.SECONDS);
return new AuthorizationCode(code);
} catch (Exception e) {
if (e instanceof TimeoutException) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not catch (TimeoutException)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, fixed.

private final long expiresIn;
private final long refreshTokenExpiresIn;

@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if some of these properties are missing? Will nulls be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@@ -0,0 +1,51 @@
package net.snowflake.client.core;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add license header like in other files

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

try {
TokenRequest request = buildTokenRequest(loginInput, authorizationCode, pkceVerifier);
URI requestUri = request.getEndpointURI();
logger.debug(
"Requesting access token from: " + requestUri.getAuthority() + requestUri.getPath());
"Requesting access token from: {}", requestUri.getAuthority() + requestUri.getPath());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can concatenate in formatted string:

"Requesting access token from: {}{}", requestUri.getAuthority(), requestUri.getPath()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


@SnowflakeJdbcInternalApi
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package scope class does not need internal annotation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@sfc-gh-dheyman sfc-gh-dheyman changed the title SNOW-1825482: OAuth Authorization Code flow (Snowflake + Okta) SNOW-1825482: PAT + OAuth Authorization Code + OAuth Client Credentials support Dec 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants