Skip to content

Commit 3c43beb

Browse files
committed
feat(identity): support identity authentication for Zeebe
1 parent baf86fe commit 3c43beb

File tree

2 files changed

+90
-8
lines changed

2 files changed

+90
-8
lines changed

camunda-sdk-java/java-common/src/main/java/io/camunda/common/auth/SelfManagedAuthentication.java

+36-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.camunda.common.auth;
22

33
import io.camunda.common.auth.identity.IdentityConfig;
4+
import io.camunda.common.exception.SdkException;
45
import io.camunda.identity.sdk.Identity;
56
import io.camunda.identity.sdk.authentication.Tokens;
67
import io.camunda.identity.sdk.authentication.exception.TokenExpiredException;
@@ -14,10 +15,34 @@
1415

1516
public class SelfManagedAuthentication extends JwtAuthentication {
1617

18+
private static class Token {
19+
20+
public static final long EXPIRATION_BUFFER = 60 * 1000; // 1 minute
21+
private final String accessToken;
22+
private final long expiresAtMillis;
23+
24+
public Token(String accessToken, long expiresInSeconds) {
25+
this.accessToken = accessToken;
26+
expiresAtMillis = System.currentTimeMillis() + expiresInSeconds * 1000 - EXPIRATION_BUFFER;
27+
}
28+
29+
public String getAccessToken() {
30+
return accessToken;
31+
}
32+
33+
public long getExpiresAt() {
34+
return expiresAtMillis;
35+
}
36+
37+
public boolean isExpired() {
38+
return expiresAtMillis < System.currentTimeMillis();
39+
}
40+
}
41+
1742
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
1843
private JwtConfig jwtConfig;
1944
private IdentityConfig identityConfig;
20-
private Map<Product, String> tokens;
45+
private final Map<Product, Token> tokens;
2146

2247
public SelfManagedAuthentication() {
2348
tokens = new HashMap<>();
@@ -51,24 +76,27 @@ public void resetToken(Product product) {
5176

5277
@Override
5378
public Map.Entry<String, String> getTokenHeader(Product product) {
54-
String token;
55-
if (tokens.containsKey(product)) {
56-
token = tokens.get(product);
57-
} else {
79+
Token token = tokens.computeIfAbsent(product, k -> getIdentityToken(product));
80+
if (token.isExpired()) {
81+
LOG.debug("Token for product {} is expired. Requesting new token", product);
5882
token = getIdentityToken(product);
5983
saveToken(product, token);
6084
}
6185
return new AbstractMap.SimpleEntry<>("Authorization", "Bearer " + token);
6286
}
6387

64-
private String getIdentityToken(Product product) {
88+
private Token getIdentityToken(Product product) {
6589
Identity identity = identityConfig.get(product).getIdentity();
6690
String audience = jwtConfig.getProduct(product).getAudience();
6791
Tokens identityTokens = identity.authentication().requestToken(audience);
68-
return identityTokens.getAccessToken();
92+
if (identityTokens.getAccessToken() == null) {
93+
throw new SdkException("Unable to get access token from identity");
94+
}
95+
LOG.debug("Received new token for product {}", product);
96+
return new Token(identityTokens.getAccessToken(), identityTokens.getExpiresIn());
6997
}
7098

71-
private void saveToken(Product product, String token) {
99+
private void saveToken(Product product, Token token) {
72100
tokens.put(product, token);
73101
}
74102
}

spring-boot-starter-camunda/src/main/java/io/camunda/zeebe/spring/client/configuration/CommonClientConfiguration.java

+54
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.camunda.identity.sdk.IdentityConfiguration;
88
import io.camunda.identity.sdk.Identity;
99
import io.camunda.zeebe.spring.client.properties.*;
10+
import org.slf4j.Logger;
1011
import org.springframework.beans.factory.annotation.Autowired;
1112
import org.springframework.boot.context.properties.EnableConfigurationProperties;
1213
import org.springframework.context.annotation.Bean;
@@ -16,6 +17,8 @@
1617
@EnableConfigurationProperties({CommonConfigurationProperties.class, ZeebeSelfManagedProperties.class})
1718
public class CommonClientConfiguration {
1819

20+
private final static Logger LOG = org.slf4j.LoggerFactory.getLogger(CommonClientConfiguration.class);
21+
1922

2023
@Autowired(required = false)
2124
CommonConfigurationProperties commonConfigurationProperties;
@@ -120,26 +123,39 @@ private JwtConfig configureJwtConfig() {
120123
JwtConfig jwtConfig = new JwtConfig();
121124
// ZEEBE
122125
if (zeebeClientConfigurationProperties.getCloud().getClientId() != null && zeebeClientConfigurationProperties.getCloud().getClientSecret() != null) {
126+
LOG.info("Using Cloud properties to determine credentials for Zeebe");
123127
jwtConfig.addProduct(Product.ZEEBE, new JwtCredential(
124128
zeebeClientConfigurationProperties.getCloud().getClientId(),
125129
zeebeClientConfigurationProperties.getCloud().getClientSecret(),
126130
zeebeClientConfigurationProperties.getCloud().getAudience(),
127131
zeebeClientConfigurationProperties.getCloud().getAuthUrl())
128132
);
129133
} else if (zeebeSelfManagedProperties.getClientId() != null && zeebeSelfManagedProperties.getClientSecret() != null) {
134+
LOG.info("Using Self Managed properties to determine credentials for Zeebe");
130135
jwtConfig.addProduct(Product.ZEEBE, new JwtCredential(
131136
zeebeSelfManagedProperties.getClientId(),
132137
zeebeSelfManagedProperties.getClientSecret(),
133138
zeebeSelfManagedProperties.getAudience(),
134139
zeebeSelfManagedProperties.getAuthServer())
135140
);
136141
} else if (commonConfigurationProperties.getClientId() != null && commonConfigurationProperties.getClientSecret() != null) {
142+
LOG.info("Using Common properties to determine credentials for Zeebe");
137143
jwtConfig.addProduct(Product.ZEEBE, new JwtCredential(
138144
commonConfigurationProperties.getClientId(),
139145
commonConfigurationProperties.getClientSecret(),
140146
zeebeClientConfigurationProperties.getCloud().getAudience(),
141147
zeebeClientConfigurationProperties.getCloud().getAuthUrl())
142148
);
149+
} else if (identityConfigurationFromProperties != null
150+
&& hasText(identityConfigurationFromProperties.getClientId())
151+
&& hasText(identityConfigurationFromProperties.getClientSecret())) {
152+
LOG.info("Using Identity SDK credentials for Zeebe");
153+
jwtConfig.addProduct(Product.ZEEBE, new JwtCredential(
154+
identityConfigurationFromProperties.getClientId(),
155+
identityConfigurationFromProperties.getClientSecret(),
156+
identityConfigurationFromProperties.getAudience(),
157+
identityConfigurationFromProperties.getIssuerBackendUrl())
158+
);
143159
}
144160

145161
// OPERATE
@@ -160,20 +176,25 @@ private JwtConfig configureJwtConfig() {
160176
}
161177

162178
if (operateClientConfigurationProperties.getClientId() != null && operateClientConfigurationProperties.getClientSecret() != null) {
179+
LOG.info("Using Operate Client properties to determine credentials for Operate");
163180
jwtConfig.addProduct(Product.OPERATE, new JwtCredential(operateClientConfigurationProperties.getClientId(), operateClientConfigurationProperties.getClientSecret(), operateAudience, operateAuthUrl));
164181
} else if (identityConfigurationFromProperties != null && hasText(identityConfigurationFromProperties.getClientId()) && hasText(identityConfigurationFromProperties.getClientSecret())) {
182+
LOG.info("Using Identity SDK credentials for Operate");
165183
jwtConfig.addProduct(Product.OPERATE, new JwtCredential(identityConfigurationFromProperties.getClientId(), identityConfigurationFromProperties.getClientSecret(), identityConfigurationFromProperties.getAudience(), identityConfigurationFromProperties.getIssuerBackendUrl()));
166184
}
167185
else if (commonConfigurationProperties.getClientId() != null && commonConfigurationProperties.getClientSecret() != null) {
186+
LOG.info("Using Common properties to determine credentials for Operate");
168187
jwtConfig.addProduct(Product.OPERATE, new JwtCredential(
169188
commonConfigurationProperties.getClientId(),
170189
commonConfigurationProperties.getClientSecret(),
171190
operateAudience,
172191
operateAuthUrl)
173192
);
174193
} else if (zeebeClientConfigurationProperties.getCloud().getClientId() != null && zeebeClientConfigurationProperties.getCloud().getClientSecret() != null) {
194+
LOG.info("Using Zeebe Cloud properties to determine credentials for Operate");
175195
jwtConfig.addProduct(Product.OPERATE, new JwtCredential(zeebeClientConfigurationProperties.getCloud().getClientId(), zeebeClientConfigurationProperties.getCloud().getClientSecret(), operateAudience, operateAuthUrl));
176196
} else if (zeebeSelfManagedProperties.getClientId() != null && zeebeSelfManagedProperties.getClientSecret() != null) {
197+
LOG.info("Using Zeebe Self Managed properties to determine credentials for Operate");
177198
jwtConfig.addProduct(Product.OPERATE, new JwtCredential(zeebeSelfManagedProperties.getClientId(), zeebeSelfManagedProperties.getClientSecret(), operateAudience, operateAuthUrl));
178199
} else {
179200
throw new SdkException("Unable to determine OPERATE credentials");
@@ -191,6 +212,11 @@ private IdentityConfig configureIdentities(JwtConfig jwtConfig) {
191212
IdentityContainer operateIdentityContainer = configureOperateIdentityContainer(jwtConfig);
192213
identityConfig.addProduct(Product.OPERATE, operateIdentityContainer);
193214
}
215+
// ZEEBE
216+
if (zeebeClientConfigurationProperties != null) {
217+
IdentityContainer zeebeIdentityContainer = configureZeebeIdentityContainer(jwtConfig);
218+
identityConfig.addProduct(Product.ZEEBE, zeebeIdentityContainer);
219+
}
194220
return identityConfig;
195221
}
196222

@@ -227,4 +253,32 @@ private IdentityContainer configureOperateIdentityContainer(JwtConfig jwtConfig)
227253
Identity operateIdentity = new Identity(operateIdentityConfiguration);
228254
return new IdentityContainer(operateIdentity, operateIdentityConfiguration);
229255
}
256+
257+
private IdentityContainer configureZeebeIdentityContainer(JwtConfig jwtConfig) {
258+
String issuer;
259+
String issuerBackendUrl;
260+
if (hasText(identityConfigurationFromProperties.getIssuer())) {
261+
issuer = identityConfigurationFromProperties.getIssuer();
262+
} else {
263+
issuer = jwtConfig.getProduct(Product.ZEEBE).getAuthUrl();
264+
}
265+
266+
if (hasText(identityConfigurationFromProperties.getIssuerBackendUrl())) {
267+
issuerBackendUrl = identityConfigurationFromProperties.getIssuerBackendUrl();
268+
} else {
269+
issuerBackendUrl = jwtConfig.getProduct(Product.ZEEBE).getAuthUrl();
270+
}
271+
272+
IdentityConfiguration zeebeIdentityConfiguration = new IdentityConfiguration.Builder()
273+
.withBaseUrl(identityConfigurationFromProperties.getBaseUrl())
274+
.withIssuer(issuer)
275+
.withIssuerBackendUrl(issuerBackendUrl)
276+
.withClientId(jwtConfig.getProduct(Product.ZEEBE).getClientId())
277+
.withClientSecret(jwtConfig.getProduct(Product.ZEEBE).getClientSecret())
278+
.withAudience(jwtConfig.getProduct(Product.ZEEBE).getAudience())
279+
.withType(identityConfigurationFromProperties.getType().name())
280+
.build();
281+
Identity zeebeIdentity = new Identity(zeebeIdentityConfiguration);
282+
return new IdentityContainer(zeebeIdentity, zeebeIdentityConfiguration);
283+
}
230284
}

0 commit comments

Comments
 (0)