Skip to content

Commit 2a46b38

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

File tree

2 files changed

+92
-8
lines changed

2 files changed

+92
-8
lines changed

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

+38-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,36 @@
1415

1516
public class SelfManagedAuthentication extends JwtAuthentication {
1617

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

2249
public SelfManagedAuthentication() {
2350
tokens = new HashMap<>();
@@ -51,24 +78,27 @@ public void resetToken(Product product) {
5178

5279
@Override
5380
public Map.Entry<String, String> getTokenHeader(Product product) {
54-
String token;
55-
if (tokens.containsKey(product)) {
56-
token = tokens.get(product);
57-
} else {
81+
Token token = tokens.computeIfAbsent(product, k -> getIdentityToken(product));
82+
if (token.isExpired()) {
83+
LOG.debug("Token for product {} is expired. Requesting new token", product);
5884
token = getIdentityToken(product);
5985
saveToken(product, token);
6086
}
6187
return new AbstractMap.SimpleEntry<>("Authorization", "Bearer " + token);
6288
}
6389

64-
private String getIdentityToken(Product product) {
90+
private Token getIdentityToken(Product product) {
6591
Identity identity = identityConfig.get(product).getIdentity();
6692
String audience = jwtConfig.getProduct(product).getAudience();
6793
Tokens identityTokens = identity.authentication().requestToken(audience);
68-
return identityTokens.getAccessToken();
94+
if (identityTokens.getAccessToken() == null) {
95+
throw new SdkException("Unable to get access token from identity");
96+
}
97+
LOG.debug("Received new token for product {}", product);
98+
return new Token(identityTokens.getAccessToken(), identityTokens.getExpiresIn());
6999
}
70100

71-
private void saveToken(Product product, String token) {
101+
private void saveToken(Product product, Token token) {
72102
tokens.put(product, token);
73103
}
74104
}

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)