Skip to content

Commit fd51f84

Browse files
committed
- add withCert to entraID provider
- add EntraIDTokenAuthConfig - add test context and endpoint config
1 parent ab8d6e0 commit fd51f84

File tree

14 files changed

+643
-92
lines changed

14 files changed

+643
-92
lines changed

core/src/main/java/redis/clients/authentication/core/TokenAuthConfig.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static class Builder {
2727
private IdentityProviderConfig identityProviderConfig;
2828
private int lowerRefreshBoundMillis;
2929
private float expirationRefreshRatio;
30-
private int tokenRequestExecutionTimeoutInMs;
30+
private int tokenRequestExecTimeoutInMs;
3131
private int maxAttemptsToRetry;
3232
private int delayInMsToRetry;
3333

@@ -41,8 +41,8 @@ public Builder lowerRefreshBoundMillis(int lowerRefreshBoundMillis) {
4141
return this;
4242
}
4343

44-
public Builder tokenRequestExecutionTimeoutInMs(int tokenRequestExecutionTimeoutInMs) {
45-
this.tokenRequestExecutionTimeoutInMs = tokenRequestExecutionTimeoutInMs;
44+
public Builder tokenRequestExecTimeoutInMs(int tokenRequestExecTimeoutInMs) {
45+
this.tokenRequestExecTimeoutInMs = tokenRequestExecTimeoutInMs;
4646
return this;
4747
}
4848

@@ -63,7 +63,7 @@ public Builder identityProviderConfig(IdentityProviderConfig identityProviderCon
6363

6464
public TokenAuthConfig build() {
6565
return new TokenAuthConfig(new TokenManagerConfig(expirationRefreshRatio,
66-
lowerRefreshBoundMillis, tokenRequestExecutionTimeoutInMs,
66+
lowerRefreshBoundMillis, tokenRequestExecTimeoutInMs,
6767
new TokenManagerConfig.RetryPolicy(maxAttemptsToRetry, delayInMsToRetry)),
6868
identityProviderConfig);
6969
}

core/src/main/java/redis/clients/authentication/core/TokenManager.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import java.util.concurrent.TimeUnit;
1010
import java.util.concurrent.TimeoutException;
1111

12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
1215
public class TokenManager {
1316

1417
private TokenManagerConfig tokenManagerConfig;
@@ -19,6 +22,8 @@ public class TokenManager {
1922
private boolean stopped = false;
2023
private ScheduledFuture<?> scheduledTask;
2124
private int numberOfRetries = 0;
25+
private Exception lastException;
26+
private Logger logger = LoggerFactory.getLogger(getClass());
2227

2328
public TokenManager(IdentityProvider identityProvider, TokenManagerConfig tokenManagerConfig) {
2429
this.identityProvider = identityProvider;
@@ -59,9 +64,9 @@ protected Token renewToken() {
5964
}
6065
Token newToken = null;
6166
try {
62-
Future<Token> requestResult = executor.submit(() -> identityProvider.requestToken());
63-
newToken = requestResult.get(tokenManagerConfig.getTokenRequestExecutionTimeoutInMs(),
64-
TimeUnit.MILLISECONDS);
67+
Future<Token> requestResult = executor.submit(() -> requestToken());
68+
newToken = requestResult.get(tokenManagerConfig.getTokenRequestExecTimeoutInMs(),
69+
TimeUnit.MILLISECONDS);
6570
long delay = calculateRenewalDelay(newToken.getExpiresAt(), newToken.getReceivedAt());
6671
scheduledTask = scheduleNext(delay);
6772
listener.onTokenRenewed(newToken);
@@ -71,13 +76,25 @@ protected Token renewToken() {
7176
numberOfRetries++;
7277
scheduledTask = scheduleNext(tokenManagerConfig.getRetryPolicy().getdelayInMs());
7378
} else {
74-
listener.onError(e);
75-
throw new AuthXException("Token request/renewal failed!", e);
79+
TokenRequestException tre = new TokenRequestException(e, lastException);
80+
listener.onError(tre);
81+
throw tre;
7682
}
7783
}
7884
return null;
7985
}
8086

87+
protected Token requestToken() {
88+
lastException = null;
89+
try {
90+
return identityProvider.requestToken();
91+
} catch (Exception e) {
92+
lastException = e;
93+
logger.error("Request to identity provider failed with message: " + e.getMessage(), e);
94+
throw e;
95+
}
96+
}
97+
8198
public long calculateRenewalDelay(long expireDate, long issueDate) {
8299
long ttlLowerRefresh = ttlForLowerRefresh(expireDate);
83100
long ttlRatioRefresh = ttlForRatioRefresh(expireDate, issueDate);

core/src/main/java/redis/clients/authentication/core/TokenManagerConfig.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public class TokenManagerConfig {
77

88
private final float expirationRefreshRatio;
99
private final int lowerRefreshBoundMillis;
10-
private final int tokenRequestExecutionTimeoutInMs;
10+
private final int tokenRequestExecTimeoutInMs;
1111
private final RetryPolicy retryPolicy;
1212

1313
public static class RetryPolicy {
@@ -30,10 +30,10 @@ public int getdelayInMs() {
3030
}
3131

3232
public TokenManagerConfig(float expirationRefreshRatio, int lowerRefreshBoundMillis,
33-
int tokenRequestExecutionTimeoutInMs, RetryPolicy retryPolicy) {
33+
int tokenRequestExecTimeoutInMs, RetryPolicy retryPolicy) {
3434
this.expirationRefreshRatio = expirationRefreshRatio;
3535
this.lowerRefreshBoundMillis = lowerRefreshBoundMillis;
36-
this.tokenRequestExecutionTimeoutInMs = tokenRequestExecutionTimeoutInMs;
36+
this.tokenRequestExecTimeoutInMs = tokenRequestExecTimeoutInMs;
3737
this.retryPolicy = retryPolicy;
3838
}
3939

@@ -59,8 +59,8 @@ public int getLowerRefreshBoundMillis() {
5959
/**
6060
* Represents the maximum time in milliseconds to wait for a token request to complete.
6161
*/
62-
public int getTokenRequestExecutionTimeoutInMs() {
63-
return tokenRequestExecutionTimeoutInMs;
62+
public int getTokenRequestExecTimeoutInMs() {
63+
return tokenRequestExecTimeoutInMs;
6464
}
6565

6666
/**
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package redis.clients.authentication.core;
2+
3+
public class TokenRequestException extends AuthXException {
4+
5+
private static final String msg = "Token request/renewal failed!";
6+
private final Exception identityProviderFailedWith;
7+
8+
public TokenRequestException(Throwable cause, Exception identityProviderFailedWith) {
9+
super(getMessage(identityProviderFailedWith), cause);
10+
this.identityProviderFailedWith = identityProviderFailedWith;
11+
}
12+
13+
public Exception getIdentityProviderFailedWith() {
14+
return identityProviderFailedWith;
15+
}
16+
17+
private static String getMessage(Exception identityProviderFailedWith) {
18+
if (identityProviderFailedWith == null) {
19+
return msg;
20+
}
21+
return msg + " Identity provider failed with: " + identityProviderFailedWith.getMessage();
22+
}
23+
24+
}

entraid/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
</properties>
5252

5353
<dependencies>
54+
5455
<dependency>
5556
<groupId>com.auth0</groupId>
5657
<artifactId>java-jwt</artifactId>
@@ -66,6 +67,12 @@
6667
<artifactId>msal4j</artifactId>
6768
<version>1.17.2</version>
6869
</dependency>
70+
<dependency>
71+
<groupId>redis.clients</groupId>
72+
<artifactId>jedis</artifactId>
73+
<version>5.3.0-SNAPSHOT</version>
74+
<scope>test</scope>
75+
</dependency>
6976
<dependency>
7077
<groupId>junit</groupId>
7178
<artifactId>junit</artifactId>

entraid/src/main/java/redis/clients/authentication/entraid/EntraIDIdentityProvider.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package redis.clients.authentication.entraid;
22

33
import java.net.MalformedURLException;
4+
import java.security.PrivateKey;
5+
import java.security.cert.X509Certificate;
46
import java.util.Set;
57
import java.util.concurrent.ExecutionException;
68
import java.util.concurrent.Future;
@@ -21,14 +23,19 @@ public final class EntraIDIdentityProvider implements IdentityProvider {
2123

2224
public EntraIDIdentityProvider(String clientId, String authority, String secret,
2325
Set<String> scopes) {
24-
init(clientId, authority, secret, scopes);
26+
IClientCredential credential = ClientCredentialFactory.createFromSecret(secret);
27+
init(clientId, authority, credential, scopes);
2528
}
2629

27-
protected void init(String clientId, String authority, String secret, Set<String> scopes) {
28-
IClientCredential credential = ClientCredentialFactory.createFromSecret(secret);
30+
public EntraIDIdentityProvider(String clientId, String authority, PrivateKey key, X509Certificate cert,
31+
Set<String> scopes) {
32+
IClientCredential credential = ClientCredentialFactory.createFromCertificate(key, cert);
33+
init(clientId, authority, credential, scopes);
34+
}
35+
36+
protected void init(String clientId, String authority, IClientCredential credential, Set<String> scopes) {
2937
try {
30-
app = ConfidentialClientApplication.builder(clientId, credential).authority(authority)
31-
.build();
38+
app = ConfidentialClientApplication.builder(clientId, credential).authority(authority).build();
3239
} catch (MalformedURLException e) {
3340
throw new RedisEntraIDException("Failed to init EntraID client!", e);
3441
}

entraid/src/main/java/redis/clients/authentication/entraid/EntraIDIdentityProviderConfig.java

Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,60 @@
11
package redis.clients.authentication.entraid;
22

3+
import java.security.PrivateKey;
4+
import java.security.cert.X509Certificate;
35
import java.util.Set;
6+
47
import redis.clients.authentication.core.IdentityProvider;
58
import redis.clients.authentication.core.IdentityProviderConfig;
69

710
public final class EntraIDIdentityProviderConfig implements IdentityProviderConfig, AutoCloseable {
811

12+
public enum EntraIDAccess {
13+
WithSecret,
14+
WithCert,
15+
}
16+
917
private String clientId;
10-
private String credential;
18+
private EntraIDAccess accessWith;
19+
private String secret;
20+
private PrivateKey key;
21+
private X509Certificate cert;
1122
private String authority;
1223
private Set<String> scopes;
1324

14-
public EntraIDIdentityProviderConfig() {
25+
public EntraIDIdentityProviderConfig(String clientId,
26+
EntraIDAccess accessWith,
27+
String secret,
28+
PrivateKey key,
29+
X509Certificate cert,
30+
String authority, Set<String> scopes) {
31+
this.clientId = clientId;
32+
this.accessWith = accessWith;
33+
this.secret = secret;
34+
this.key = key;
35+
this.cert = cert;
36+
this.authority = authority;
37+
this.scopes = scopes;
1538
}
1639

1740
@Override
1841
public IdentityProvider getProvider() {
19-
IdentityProvider identityProvider = new EntraIDIdentityProvider(clientId, authority,
20-
credential, scopes);
21-
clear();
22-
return identityProvider;
23-
}
24-
25-
public static class Builder {
26-
27-
private String clientId;
28-
private String credential;
29-
private String authority;
30-
private Set<String> scopes;
31-
32-
public Builder clientId(String clientId) {
33-
this.clientId = clientId;
34-
return this;
35-
}
36-
37-
public Builder credential(String credential) {
38-
this.credential = credential;
39-
return this;
42+
IdentityProvider identityProvider = null;
43+
switch (accessWith) {
44+
case WithSecret:
45+
identityProvider = new EntraIDIdentityProvider(clientId, authority,
46+
secret, scopes);
47+
break;
48+
case WithCert:
49+
identityProvider = new EntraIDIdentityProvider(clientId, authority,
50+
key, cert, scopes);
51+
break;
52+
default:
53+
throw new RedisEntraIDException("Access type and credentials must be set!");
4054
}
4155

42-
public Builder authority(String authority) {
43-
this.authority = authority;
44-
return this;
45-
}
46-
47-
public Builder scopes(Set<String> scopes) {
48-
this.scopes = scopes;
49-
return this;
50-
}
51-
52-
public EntraIDIdentityProviderConfig build() {
53-
EntraIDIdentityProviderConfig config = new EntraIDIdentityProviderConfig();
54-
config.clientId = this.clientId;
55-
config.credential = this.credential;
56-
config.authority = this.authority;
57-
config.scopes = this.scopes;
58-
this.clientId = null;
59-
this.credential = null;
60-
this.authority = null;
61-
this.scopes = null;
62-
return config;
63-
}
64-
65-
}
66-
67-
public static Builder builder() {
68-
return new Builder();
56+
clear();
57+
return identityProvider;
6958
}
7059

7160
@Override
@@ -75,7 +64,9 @@ public void close() throws Exception {
7564

7665
private void clear() {
7766
clientId = null;
78-
credential = null;
67+
secret = null;
68+
key = null;
69+
cert = null;
7970
authority = null;
8071
scopes = null;
8172
}

0 commit comments

Comments
 (0)