-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update AuthToken rotation to support more auth types
This update extends the `AuthToken` rotation beyound supporting just the expiring (bearer) tokens to a more versatile solution that allows support of various auth types. An important part of the `AuthToken` rotation support is retryability, which is either managed automatically by the driver via the Managed Transaction API (Session.executeRead(TransactionCallback), etc.) or explicitly by the user. The rotation support relies on the existing retry approach used for the other retryable conditions. If a given unit of work fails due to credentials rejection by the server and the `AuthTokenManager` is able to supply valid credentials, the failure must be marked as retryable to indicate that the given unit of work is worth retrying. The driver provides the `RetryableException` marker interface for that. However, the credentials rejection server security error depends on auth type used. Therefore, it was decided that the `AuthTokenManager` implementations should have access to the security error details and should make a decision on whether such error should be considered as retryable or not. To achive this, the `AuthTokenManager.onExpired(AuthToken)` method is replaced with a new `AuthTokenManager.handleSecurityException(AuthToken authToken, SecurityException exception)` method that returns a `boolean` value to determine if the error is retryable. By default, the `SecurityException` and its subclasses are not retryable. If an error is determined to be retryable by the `AuthTokenManager`, then the driver wraps the current error into a new `SecurityRetryableException`. The latter is a subclass of the `SecurityException` and is also a `RetryableException`. It contains the original exception as a cause and transparently proxies calls of both the `SecurityRetryableException.code()` and `SecurityRetryableException.getMessage()` methods to the original exception. The `SecurityRetryableException` has been introduced to allow marking `SecurityException` and its subclasses as retryable and is not currently meant to fork a separate class hierarchy as a single class is sufficient for this purpose at this point. Following these updates, the `TokenExpiredRetryableException` has been deleted as no longer needed. The `AuthTokenManagers.expirationBased(Supplier<AuthTokenAndExpiration>)` and `AuthTokenManagers.expirationBasedAsync(Supplier<CompletionStage<AuthTokenAndExpiration>>)` methods have been replaced with `AuthTokenManagers.bearer(Supplier<AuthTokenAndExpiration>)` and `AuthTokenManagers.bearerAsync(Supplier<CompletionStage<AuthTokenAndExpiration>>)` methods respectively. The new medhods are tailored for the bearer token auth support specifically. In addition, 2 new methods have been introduced for the basic (type) `AuthToken` rotation support: `AuthTokenManagers.basic(Supplier<AuthToken>)` and `AuthTokenManagers.basicAsync(Supplier<CompletionStage<AuthToken>>)`. The code inspection profile has been updated to enable the `SerializableHasSerialVersionUIDField` warning.
- Loading branch information
1 parent
3958fce
commit 238a7b2
Showing
34 changed files
with
769 additions
and
216 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
driver/src/main/java/org/neo4j/driver/exceptions/SecurityRetryableException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright (c) "Neo4j" | ||
* Neo4j Sweden AB [http://neo4j.com] | ||
* | ||
* This file is part of Neo4j. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.neo4j.driver.exceptions; | ||
|
||
import java.io.Serial; | ||
import java.util.Objects; | ||
import org.neo4j.driver.AuthToken; | ||
import org.neo4j.driver.util.Experimental; | ||
import org.neo4j.driver.util.Preview; | ||
|
||
/** | ||
* Indicates that the contained {@link SecurityException} is a {@link RetryableException}, which is determined by the | ||
* {@link org.neo4j.driver.AuthTokenManager#handleSecurityException(AuthToken, SecurityException)} method. | ||
* <p> | ||
* The original {@link java.lang.SecurityException} is always available as a {@link Throwable#getCause()}. The | ||
* {@link SecurityRetryableException#code()} and {@link SecurityRetryableException#getMessage()} supply the values from | ||
* the original exception. | ||
* | ||
* @since 5.12 | ||
*/ | ||
@Preview(name = "AuthToken rotation and session auth support") | ||
public class SecurityRetryableException extends SecurityException implements RetryableException { | ||
@Serial | ||
private static final long serialVersionUID = 3914900631374208080L; | ||
|
||
/** | ||
* The original security exception. | ||
*/ | ||
private final SecurityException exception; | ||
|
||
/** | ||
* Creates a new instance. | ||
* | ||
* @param exception the original security exception, must not be {@code null} | ||
*/ | ||
public SecurityRetryableException(SecurityException exception) { | ||
super(exception.getMessage(), exception); | ||
this.exception = Objects.requireNonNull(exception); | ||
} | ||
|
||
@Override | ||
public String code() { | ||
return exception.code(); | ||
} | ||
|
||
@Override | ||
public String getMessage() { | ||
return exception.getMessage(); | ||
} | ||
|
||
/** | ||
* Returns the original security exception. | ||
* | ||
* @return the original security exception | ||
*/ | ||
@Experimental | ||
public SecurityException securityException() { | ||
return exception; | ||
} | ||
} |
50 changes: 0 additions & 50 deletions
50
driver/src/main/java/org/neo4j/driver/exceptions/TokenExpiredRetryableException.java
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.