Skip to content

Commit 4adcfea

Browse files
committed
wip
Signed-off-by: Richard Salac <richard.salac@broadcom.com>
1 parent a4c96b7 commit 4adcfea

28 files changed

Lines changed: 168 additions & 89 deletions

File tree

api-catalog-services/src/main/java/org/zowe/apiml/apicatalog/config/SecurityConfiguration.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ WebFilter tokenAuthenticationFilter(
317317
}
318318
})
319319
.map(pair -> ReactiveSecurityContextHolder.withAuthentication(
320+
//TODO: WTF?! token used as username?
320321
createAuthenticated(pair.getValue().getUserId(), pair.getKey(), TokenAuthentication.Type.JWT)
321322
))
322323
.orElse(context)
@@ -343,15 +344,15 @@ WebFilter oidcAuthenticationFilter(
343344
Optional.ofNullable(exchange.getRequest().getHeaders().getFirst(HEADER_OIDC_TOKEN))
344345
.map(token -> {
345346
try {
346-
return Map.entry(token, gatewaySecurity.verifyOidc(token));
347+
var tokenAuthentication = gatewaySecurity.verifyOidc(token);
348+
tokenAuthentication.setAuthenticated(true);
349+
return tokenAuthentication;
347350
} catch (Exception e) {
348351
log.debug("Cannot verify OIDC token: {}", token, e);
349352
return null;
350353
}
351354
})
352-
.map(pair -> ReactiveSecurityContextHolder.withAuthentication(
353-
createAuthenticated(pair.getValue().getUserId(), pair.getKey(), TokenAuthentication.Type.OIDC)
354-
))
355+
.map(ReactiveSecurityContextHolder::withAuthentication)
355356
.orElse(context)
356357
);
357358
}

apiml-security-common/src/main/java/org/zowe/apiml/security/common/token/TokenAuthentication.java

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
import lombok.EqualsAndHashCode;
1515
import lombok.Getter;
1616
import lombok.extern.slf4j.Slf4j;
17+
import org.apache.el.parser.Token;
1718
import org.springframework.security.authentication.AbstractAuthenticationToken;
1819
import org.springframework.security.core.parameters.P;
20+
import org.zowe.apiml.security.common.util.JwtUtils;
1921

2022
import java.io.Serial;
2123
import java.text.ParseException;
22-
import java.util.Collections;
23-
import java.util.Date;
24-
import java.util.List;
24+
import java.util.*;
2525

2626
/**
2727
* This object is added to security context after successful authentication.
@@ -45,13 +45,13 @@ public class TokenAuthentication extends AbstractAuthenticationToken {
4545
@Getter
4646
private Type type;
4747

48-
public TokenAuthentication(String tokenString) throws ParseException {
49-
super(Collections.emptyList());
48+
public TokenAuthentication(String tokenString) {
49+
this(tokenString, (Type) null);
50+
}
5051

51-
this.jwt = JWTParser.parse(tokenString);
52-
this.claims = jwt.getJWTClaimsSet();
53-
this.queryResponse = parseQueryResponse(claims);
54-
this.type = null;
52+
public TokenAuthentication(String userId, String tokenString) {
53+
this(tokenString);
54+
checkUserId(userId);
5555
}
5656

5757
public TokenAuthentication(String tokenString, Type type) {
@@ -63,10 +63,32 @@ public TokenAuthentication(String tokenString, Type type) {
6363
this.queryResponse = parseQueryResponse(claims);
6464
this.type = type;
6565
} catch (ParseException ex) {
66-
throw new TokenNotValidException("Token is not valid.", ex);
66+
throw JwtUtils.handleJwtParserException(ex);
6767
}
6868
}
6969

70+
public TokenAuthentication(String userId, String tokenString, Type type) {
71+
this(tokenString, type);
72+
checkUserId(userId);
73+
}
74+
75+
76+
public static TokenAuthentication createAuthenticated(String tokenString, Type type) {
77+
var tokenAuthentication = new TokenAuthentication(tokenString, type);
78+
tokenAuthentication.setAuthenticated(true);
79+
return tokenAuthentication;
80+
}
81+
82+
public static TokenAuthentication createAuthenticated(String tokenString, String type) {
83+
return createAuthenticated(tokenString, Type.valueOf(type));
84+
}
85+
86+
public static TokenAuthentication createAuthenticated(String userId, String token, Type type) {
87+
var tokenAuthentication = new TokenAuthentication(userId, token, type);
88+
tokenAuthentication.setAuthenticated(true);
89+
return tokenAuthentication;
90+
}
91+
7092
public JWT getJwt() {
7193
return jwt;
7294
}
@@ -164,4 +186,12 @@ private QueryResponse parseQueryResponse(JWTClaimsSet claims) {
164186
throw new TokenNotValidException(e.getMessage(), e);
165187
}
166188
}
189+
190+
private void checkUserId(String userId) {
191+
var principal = getPrincipal();
192+
if (userId == null || !userId.equalsIgnoreCase(principal)) {
193+
log.debug("Username '{}' does not match the one in token '{}'", userId, principal);
194+
throw new TokenNotValidException("Token is not valid for provided username");
195+
}
196+
}
167197
}

apiml-security-common/src/testFixtures/java/org/zowe/apiml/security/common/util/JWTTestUtils.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,26 @@ public static String createToken(String username, String domain, String ltpaToke
5555
.compact();
5656
}
5757

58+
public static String createDummyJwtToken(String username, String issuer) {
59+
long now = System.currentTimeMillis();
60+
long expiration = now + 100_000L;
61+
return Jwts.builder()
62+
.subject(username)
63+
.issuedAt(new Date(now))
64+
.expiration(new Date(expiration))
65+
.issuer(issuer)
66+
.id(UUID.randomUUID().toString())
67+
.compact();
68+
}
69+
70+
public static String createDummyAPIMLToken(String username) {
71+
return createDummyJwtToken(username, "APIML");
72+
}
73+
74+
public static String createDummyZOSMFToken(String username) {
75+
return createDummyJwtToken(username, "ZOSMF");
76+
}
77+
5878
@SneakyThrows
5979
public static String createTokenWithUserFields() {
6080
var now = Instant.now();

apiml/src/main/java/org/zowe/apiml/GatewaySecurityApi.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@
2222
import org.springframework.stereotype.Service;
2323
import org.zowe.apiml.security.client.service.GatewaySecurity;
2424
import org.zowe.apiml.security.common.login.LoginRequest;
25-
import org.zowe.apiml.security.common.token.OIDCProvider;
26-
import org.zowe.apiml.security.common.token.QueryResponse;
27-
import org.zowe.apiml.security.common.token.TokenNotValidException;
25+
import org.zowe.apiml.security.common.token.*;
2826
import org.zowe.apiml.zaas.security.config.CompoundAuthProvider;
2927
import org.zowe.apiml.zaas.security.service.AuthenticationService;
3028
import lombok.extern.slf4j.Slf4j;
@@ -65,15 +63,15 @@ public QueryResponse query(String token) {
6563
var authentication = authenticationService.validateJwtToken(token);
6664
if (authentication.isAuthenticated()) {
6765
log.debug("JWT is valid. Parsing JWT.");
68-
return authenticationService.parseJwtToken(token);
66+
return authenticationService.parseJwtToken(token).getQueryResponse();
6967
}
7068
throw new TokenNotValidException(TOKEN_NOT_VALID.getDefaultMessage());
7169
}
7270

7371
@Override
74-
public QueryResponse verifyOidc(String token) {
72+
public TokenAuthentication verifyOidc(String token) {
7573
if (oidcProvider != null && oidcProvider.isValid(token)) {
76-
return new QueryResponse();
74+
return new TokenAuthentication(token, TokenAuthentication.Type.OIDC);
7775
}
7876
throw new TokenNotValidException(TOKEN_NOT_VALID.getDefaultMessage());
7977
}

apiml/src/test/java/org/zowe/apiml/GatewaySecurityApiTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,10 @@ void thenReturnQueryResponse() {
109109

110110
String validToken = "valid-jwt";
111111
QueryResponse expectedResponse = new QueryResponse(); // Assuming a default or populated response
112+
var tokenAuthenticationMock = mock(TokenAuthentication.class);
113+
when(tokenAuthenticationMock.getQueryResponse()).thenReturn(expectedResponse);
112114
when(authenticationService.validateJwtToken(validToken)).thenReturn(tokenAuthenticated);
113-
when(authenticationService.parseJwtToken(validToken)).thenReturn(expectedResponse);
115+
when(authenticationService.parseJwtToken(validToken)).thenReturn(tokenAuthenticationMock);
114116

115117
QueryResponse actualResponse = gatewaySecurityApi.query(validToken);
116118

@@ -153,7 +155,7 @@ void whenVerifyOidc_andTokenIsValid_thenReturnResponse() {
153155
String validOidcToken = "valid-oidc-token";
154156
when(oidcProvider.isValid(validOidcToken)).thenReturn(true);
155157

156-
QueryResponse response = gatewaySecurityApi.verifyOidc(validOidcToken);
158+
QueryResponse response = gatewaySecurityApi.verifyOidc(validOidcToken).getQueryResponse();
157159

158160
assertNotNull(response, "QueryResponse should not be null for a valid OIDC token");
159161
}

security-service-client-spring/src/main/java/org/zowe/apiml/security/client/service/GatewaySecurity.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
package org.zowe.apiml.security.client.service;
1212

13+
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
1314
import org.zowe.apiml.security.common.token.QueryResponse;
15+
import org.zowe.apiml.security.common.token.TokenAuthentication;
1416

1517
import java.util.Optional;
1618

security-service-client-spring/src/main/java/org/zowe/apiml/security/client/service/GatewaySecurityService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.zowe.apiml.security.common.error.ErrorType;
3434
import org.zowe.apiml.security.common.login.LoginRequest;
3535
import org.zowe.apiml.security.common.token.QueryResponse;
36+
import org.zowe.apiml.security.common.token.TokenAuthentication;
3637

3738
import java.io.IOException;
3839
import java.nio.charset.StandardCharsets;

security-service-client-spring/src/main/java/org/zowe/apiml/security/client/token/GatewayTokenProvider.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
package org.zowe.apiml.security.client.token;
1212

13+
import ch.qos.logback.core.subst.Token;
1314
import lombok.RequiredArgsConstructor;
1415
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
1516
import org.springframework.security.authentication.AuthenticationProvider;

zaas-service/src/main/java/org/zowe/apiml/zaas/security/login/dummy/DummyAuthenticationProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public Authentication authenticate(Authentication authentication) {
9494
String username = usernamePasswordAuthentication.getName();
9595
String token = authenticationService.createJwtToken(username, DUMMY_PROVIDER, null);
9696

97-
TokenAuthentication tokenAuthentication = new TokenAuthentication(username, token, TokenAuthentication.Type.JWT);
97+
TokenAuthentication tokenAuthentication = new TokenAuthentication(token, TokenAuthentication.Type.JWT);
9898
tokenAuthentication.setAuthenticated(true);
9999
return tokenAuthentication;
100100
}

zaas-service/src/main/java/org/zowe/apiml/zaas/security/login/saf/ZosAuthenticationProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public Authentication authenticate(Authentication authentication) {
5353
if ((returned == null) || (returned.isSuccess())) {
5454
final String domain = "security-domain";
5555
final String jwtToken = authenticationService.createJwtToken(userid, domain, null);
56-
return authenticationService.createTokenAuthentication(jwtToken);
56+
return authenticationService.createTokenAuthentication(userid, jwtToken);
5757
} else {
5858
throw new ZosAuthenticationException(returned);
5959
}

0 commit comments

Comments
 (0)