-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Token based authentication integration with core extension #3063
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
Merged
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
91871b6
Support for StreamingCredentials
ggivo e9d4d63
Tests & publish ReauthEvent
ggivo 820ffff
Clean up & Format & Add ReauthenticateEvent test
ggivo 5858286
Conditionally enable connection reauthentication based on client setting
ggivo 779edca
Client setting for enabling reauthentication
ggivo 21bf696
formating
ggivo c8ca829
Merge branch 'main' into streaming-auth
ggivo f3aef04
resolve conflict with main
ggivo 631d420
format
ggivo 6f46022
dispath using connection handler
ggivo b32f84c
Support multi with re-auth
ggivo 7eaaf6b
Fix EndpointId missing in events
ggivo 086ccf3
format
ggivo 61158f2
Add unit tests for setCredenatials
ggivo 9a0e513
Skip preProcessing of auth command to avoid replacing the credential …
ggivo 6ec2846
clean up - remove dead code
ggivo 110eb1a
Moved almost all code inside the new handler
tishun 8e9ab48
fix inTransaction lock with dispatch command batch
ggivo 746dd82
Remove StreamingCredentialsProvider interface.
ggivo 31341f1
Add authentication handler to ClusterPubSub connections
ggivo 6891281
Merge branch 'main' into streaming-auth
ggivo 77c5058
Token based auth integration with core extension
ggivo 3c6dbc9
rebase to address "oid" core-autx lib change
ggivo 00de1ce
Add EntraId integration tests
ggivo 0e0f502
StreamingCredentialsProvider replaced with RedisCredentialsProvider.s…
ggivo 2acdb6d
pub/sub test basic functionality with entraid auth
ggivo 8c760f1
Update src/main/java/io/lettuce/authx/TokenBasedRedisCredentialsProvi…
ggivo a2a8e10
Addressing review comments from @tishun
ggivo 668b850
Bump redis-authx-core & redis-authx-entraid from 0.1.0-SNAPSHOT to 0.…
ggivo 369341c
add java doc for
ggivo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
137 changes: 137 additions & 0 deletions
137
src/main/java/io/lettuce/authx/TokenBasedRedisCredentialsProvider.java
This file contains hidden or 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,137 @@ | ||
| /* | ||
| * Copyright 2024, Redis Ltd. and Contributors | ||
| * All rights reserved. | ||
| * | ||
| * Licensed under the MIT License. | ||
| */ | ||
| package io.lettuce.authx; | ||
|
|
||
| import io.lettuce.core.RedisCredentials; | ||
| import io.lettuce.core.RedisCredentialsProvider; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
| import reactor.core.publisher.Flux; | ||
| import reactor.core.publisher.Mono; | ||
| import reactor.core.publisher.Sinks; | ||
| import redis.clients.authentication.core.Token; | ||
| import redis.clients.authentication.core.TokenAuthConfig; | ||
| import redis.clients.authentication.core.TokenListener; | ||
| import redis.clients.authentication.core.TokenManager; | ||
|
|
||
| /** | ||
| * A {@link RedisCredentialsProvider} implementation that supports token-based authentication for Redis. | ||
| * <p> | ||
| * This provider uses a {@link TokenManager} to manage and renew tokens, ensuring that the Redis client can authenticate with | ||
| * Redis using a dynamically updated token. This is particularly useful in scenarios where Redis access is controlled via | ||
| * token-based authentication, such as when Redis is integrated with an identity provider like EntraID. | ||
| * </p> | ||
| * <p> | ||
| * The provider supports streaming of credentials and automatically emits new credentials whenever a token is renewed. It must | ||
| * be used with {@link io.lettuce.core.ClientOptions.ReauthenticateBehavior#ON_NEW_CREDENTIALS} to automatically re-authenticate | ||
| * connections whenever new tokens are emitted by the provider. | ||
| * </p> | ||
| * <p> | ||
| * The lifecycle of this provider is externally managed. It should be closed when there are no longer any connections using it, | ||
| * to stop the token management process and release resources. | ||
| * </p> | ||
| * | ||
| * @since 6.6 | ||
| */ | ||
| public class TokenBasedRedisCredentialsProvider implements RedisCredentialsProvider, AutoCloseable { | ||
|
|
||
| private static final Logger log = LoggerFactory.getLogger(TokenBasedRedisCredentialsProvider.class); | ||
|
|
||
| private final TokenManager tokenManager; | ||
|
|
||
| private final Sinks.Many<RedisCredentials> credentialsSink = Sinks.many().replay().latest(); | ||
|
|
||
| private TokenBasedRedisCredentialsProvider(TokenManager tokenManager) { | ||
| this.tokenManager = tokenManager; | ||
| } | ||
|
|
||
| private void init() { | ||
|
|
||
| TokenListener listener = new TokenListener() { | ||
|
|
||
| @Override | ||
| public void onTokenRenewed(Token token) { | ||
| String username = token.getUser(); | ||
| char[] pass = token.getValue().toCharArray(); | ||
| RedisCredentials credentials = RedisCredentials.just(username, pass); | ||
| credentialsSink.tryEmitNext(credentials); | ||
| } | ||
|
|
||
| @Override | ||
| public void onError(Exception exception) { | ||
| log.error("Token renew failed!", exception); | ||
| } | ||
|
|
||
| }; | ||
|
|
||
| try { | ||
| tokenManager.start(listener, false); | ||
| } catch (Exception e) { | ||
| credentialsSink.tryEmitError(e); | ||
| tokenManager.stop(); | ||
| throw new RuntimeException("Failed to start TokenManager", e); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Resolve the latest available credentials as a Mono. | ||
| * <p> | ||
| * This method returns a Mono that emits the most recent set of Redis credentials. The Mono will complete once the | ||
| * credentials are emitted. If no credentials are available at the time of subscription, the Mono will wait until | ||
| * credentials are available. | ||
| * | ||
| * @return a Mono that emits the latest Redis credentials | ||
| */ | ||
| @Override | ||
| public Mono<RedisCredentials> resolveCredentials() { | ||
|
|
||
| return credentialsSink.asFlux().next(); | ||
| } | ||
|
|
||
| /** | ||
| * Expose the Flux for all credential updates. | ||
| * <p> | ||
| * This method returns a Flux that emits all updates to the Redis credentials. Subscribers will receive the latest | ||
| * credentials whenever they are updated. The Flux will continue to emit updates until the provider is shut down. | ||
| * | ||
| * @return a Flux that emits all updates to the Redis credentials | ||
| */ | ||
| @Override | ||
| public Flux<RedisCredentials> credentials() { | ||
ggivo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return credentialsSink.asFlux().onBackpressureLatest(); // Provide a continuous stream of credentials | ||
| } | ||
|
|
||
| @Override | ||
| public boolean supportsStreaming() { | ||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Stop the credentials provider and clean up resources. | ||
| * <p> | ||
| * This method stops the TokenManager and completes the credentials sink, ensuring that all resources are properly released. | ||
| * It should be called when the credentials provider is no longer needed. | ||
| */ | ||
| @Override | ||
| public void close() { | ||
| credentialsSink.tryEmitComplete(); | ||
| tokenManager.stop(); | ||
| } | ||
|
|
||
| public static TokenBasedRedisCredentialsProvider create(TokenAuthConfig tokenAuthConfig) { | ||
| return create(new TokenManager(tokenAuthConfig.getIdentityProviderConfig().getProvider(), | ||
| tokenAuthConfig.getTokenManagerConfig())); | ||
| } | ||
|
|
||
| public static TokenBasedRedisCredentialsProvider create(TokenManager tokenManager) { | ||
| TokenBasedRedisCredentialsProvider credentialManager = new TokenBasedRedisCredentialsProvider(tokenManager); | ||
| credentialManager.init(); | ||
| return credentialManager; | ||
| } | ||
|
|
||
| } | ||
This file contains hidden or 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
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.