This is an automated email from the ASF dual-hosted git repository.
smolnar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new fbed6e7cf KNOX-2970 - Removing KnoxSSO cookie from the token state
service upon logout (#806)
fbed6e7cf is described below
commit fbed6e7cf095f3e5f6328163de15e5925544372d
Author: Sandor Molnar <[email protected]>
AuthorDate: Thu Oct 19 20:00:46 2023 +0200
KNOX-2970 - Removing KnoxSSO cookie from the token state service upon
logout (#806)
Additionally, the Token Management UI displays the 'current' KnoxSSO cookie
row in bold.
---
.../jwt/filter/SSOCookieFederationFilter.java | 2 ++
.../gateway/service/knoxsso/KnoxSSOutMessages.java | 3 +++
.../gateway/service/knoxsso/WebSSOutResource.java | 29 ++++++++++++++++++++++
.../service/session/SessionInformation.java | 11 ++++++++
.../gateway/service/session/SessionResource.java | 4 ++-
.../services/security/token/TokenUtils.java | 1 +
.../token-management/app/session.information.ts | 1 +
.../app/token.management.component.html | 8 +++---
.../app/token.management.component.ts | 14 +++++++++--
9 files changed, 66 insertions(+), 7 deletions(-)
diff --git
a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
index 81d6e1a97..e329037de 100644
---
a/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
+++
b/gateway-provider-security-jwt/src/main/java/org/apache/knox/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
@@ -22,6 +22,7 @@ import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.provider.federation.jwt.JWTMessages;
import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.apache.knox.gateway.services.security.token.TokenUtils;
import org.apache.knox.gateway.services.security.token.UnknownTokenException;
import org.apache.knox.gateway.services.security.token.impl.JWT;
import org.apache.knox.gateway.services.security.token.impl.JWTToken;
@@ -165,6 +166,7 @@ public class SSOCookieFederationFilter extends
AbstractJWTFilter {
JWT token = new JWTToken(wireToken);
if (validateToken(req, res, chain, token)) {
Subject subject = createSubjectFromToken(token);
+
request.setAttribute(TokenUtils.ATTR_CURRENT_KNOXSSO_COOKIE_TOKEN_ID,
token.getClaim(JWTToken.KNOX_ID_CLAIM));
continueWithEstablishedSecurityContext(subject, req, res, chain);
// we found a valid cookie we don't need to keep checking anymore
diff --git
a/gateway-service-knoxssout/src/main/java/org/apache/knox/gateway/service/knoxsso/KnoxSSOutMessages.java
b/gateway-service-knoxssout/src/main/java/org/apache/knox/gateway/service/knoxsso/KnoxSSOutMessages.java
index e94dab897..72ce31217 100644
---
a/gateway-service-knoxssout/src/main/java/org/apache/knox/gateway/service/knoxsso/KnoxSSOutMessages.java
+++
b/gateway-service-knoxssout/src/main/java/org/apache/knox/gateway/service/knoxsso/KnoxSSOutMessages.java
@@ -28,4 +28,7 @@ public interface KnoxSSOutMessages {
@Message(level = MessageLevel.WARN, text = "Could not find cookie with the
name: {0} in the request to be removed from the concurrent session counter for
user: {1}. ")
void couldNotFindCookieWithTokenToRemove(String cookieName, String username);
+
+ @Message( level = MessageLevel.INFO, text = "Knox Token service ({0})
revoked token {1} ({2}) (renewer={3})")
+ void revokedToken(String topologyName, String tokenDisplayText, String
tokenId, String renewer);
}
\ No newline at end of file
diff --git
a/gateway-service-knoxssout/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOutResource.java
b/gateway-service-knoxssout/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOutResource.java
index 0ce423760..72f2ffcc0 100644
---
a/gateway-service-knoxssout/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOutResource.java
+++
b/gateway-service-knoxssout/src/main/java/org/apache/knox/gateway/service/knoxsso/WebSSOutResource.java
@@ -18,9 +18,15 @@
package org.apache.knox.gateway.service.knoxsso;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.security.SubjectUtils;
import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.ServiceType;
+import org.apache.knox.gateway.services.security.token.TokenStateService;
+import org.apache.knox.gateway.services.security.token.TokenUtils;
+import org.apache.knox.gateway.services.security.token.UnknownTokenException;
+import org.apache.knox.gateway.services.security.token.impl.JWTToken;
import org.apache.knox.gateway.session.control.ConcurrentSessionVerifier;
+import org.apache.knox.gateway.util.Tokens;
import org.apache.knox.gateway.util.Urls;
import javax.annotation.PostConstruct;
@@ -35,6 +41,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.net.MalformedURLException;
+import java.text.ParseException;
import java.util.Arrays;
import java.util.Optional;
@@ -118,6 +125,7 @@ public class WebSSOutResource {
if (gwServices != null) {
ConcurrentSessionVerifier verifier =
gwServices.getService(ServiceType.CONCURRENT_SESSION_VERIFIER);
verifier.sessionEndedForUser(request.getUserPrincipal().getName(),
ssoCookie.get().getValue());
+ removeKnoxSsoCookie(ssoCookie.get(), gwServices);
}
} else {
log.couldNotFindCookieWithTokenToRemove(cookieName,
request.getUserPrincipal().getName());
@@ -125,6 +133,27 @@ public class WebSSOutResource {
return rc;
}
+ private void removeKnoxSsoCookie(Cookie ssoCookie, GatewayServices
gwServices) {
+ final TokenStateService tokenStateService =
gwServices.getService(ServiceType.TOKEN_STATE_SERVICE);
+ if (tokenStateService!= null) {
+ try {
+ final JWTToken jwt = new JWTToken(ssoCookie.getValue());
+ tokenStateService.revokeToken(jwt);
+ final String revoker = SubjectUtils.getCurrentEffectivePrincipalName();
+ log.revokedToken(getTopologyName(),
+ Tokens.getTokenDisplayText(ssoCookie.getValue()),
+ Tokens.getTokenIDDisplayText(TokenUtils.getTokenId(jwt)),
+ revoker);
+ } catch (ParseException | UnknownTokenException e) {
+ // NOP: cookie maybe invalid or token management was disabled anyway
+ }
+ }
+ }
+
+ private String getTopologyName() {
+ return (String)
context.getAttribute("org.apache.knox.gateway.gateway.cluster");
+ }
+
private Optional<Cookie> findCookie(String cookieName) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
diff --git
a/gateway-service-session/src/main/java/org/apache/knox/gateway/service/session/SessionInformation.java
b/gateway-service-session/src/main/java/org/apache/knox/gateway/service/session/SessionInformation.java
index 9ebba4632..d572ebf5d 100644
---
a/gateway-service-session/src/main/java/org/apache/knox/gateway/service/session/SessionInformation.java
+++
b/gateway-service-session/src/main/java/org/apache/knox/gateway/service/session/SessionInformation.java
@@ -37,6 +37,9 @@ public class SessionInformation {
@XmlElement
private boolean canSeeAllTokens;
+ @XmlElement
+ private String currentKnoxSsoCookieTokenId;
+
public String getUser() {
return user;
}
@@ -77,4 +80,12 @@ public class SessionInformation {
this.canSeeAllTokens = canSeeAllTokens;
}
+ public String getCurrentKnoxSsoCookieTokenId() {
+ return currentKnoxSsoCookieTokenId;
+ }
+
+ public void setCurrentKnoxSsoCookieTokenId(String
currentKnoxSsoCookieTokenId) {
+ this.currentKnoxSsoCookieTokenId = currentKnoxSsoCookieTokenId;
+ }
+
}
diff --git
a/gateway-service-session/src/main/java/org/apache/knox/gateway/service/session/SessionResource.java
b/gateway-service-session/src/main/java/org/apache/knox/gateway/service/session/SessionResource.java
index 1d1500294..40dda8e81 100644
---
a/gateway-service-session/src/main/java/org/apache/knox/gateway/service/session/SessionResource.java
+++
b/gateway-service-session/src/main/java/org/apache/knox/gateway/service/session/SessionResource.java
@@ -31,6 +31,7 @@ import javax.ws.rs.core.Context;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.security.SubjectUtils;
+import org.apache.knox.gateway.services.security.token.TokenUtils;
@Singleton
@Path("session/api/v1/")
@@ -57,8 +58,9 @@ public class SessionResource {
sessionInfo.setLogoutUrl(logoutUrl);
sessionInfo.setLogoutPageUrl(getLogoutPageUrl(config));
sessionInfo.setGlobalLogoutPageUrl(getGlobalLogoutPageUrl(config));
- sessionInfo.setCanSeeAllTokens(config.canSeeAllTokens(user));
}
+ sessionInfo.setCanSeeAllTokens(config != null ?
config.canSeeAllTokens(user) : false);
+ sessionInfo.setCurrentKnoxSsoCookieTokenId((String)
this.request.getAttribute(TokenUtils.ATTR_CURRENT_KNOXSSO_COOKIE_TOKEN_ID));
return sessionInfo;
}
diff --git
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/TokenUtils.java
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/TokenUtils.java
index 4ba1defb0..e9620a425 100644
---
a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/TokenUtils.java
+++
b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/TokenUtils.java
@@ -33,6 +33,7 @@ import java.security.interfaces.RSAPublicKey;
import java.util.LinkedHashMap;
public class TokenUtils {
+ public static final String ATTR_CURRENT_KNOXSSO_COOKIE_TOKEN_ID =
"currentKnoxSsoCookieTokenId";
public static final String SIGNING_HMAC_SECRET_ALIAS =
"gateway.signing.hmac.secret";
private static final String DEFAULT_RSA_SIG_ALG = "RS256";
private static final String DEFAULT_HMAC_SIG_ALG = "HS256";
diff --git
a/knox-token-management-ui/token-management/app/session.information.ts
b/knox-token-management-ui/token-management/app/session.information.ts
index 3d748deaf..7d64b026b 100644
--- a/knox-token-management-ui/token-management/app/session.information.ts
+++ b/knox-token-management-ui/token-management/app/session.information.ts
@@ -21,4 +21,5 @@ export class SessionInformation {
logoutPageUrl: string;
globalLgoutPageUrl: string;
canSeeAllTokens: boolean;
+ currentKnoxSsoCookieTokenId: string;
}
diff --git
a/knox-token-management-ui/token-management/app/token.management.component.html
b/knox-token-management-ui/token-management/app/token.management.component.html
index 49a0debd4..ca93fef22 100644
---
a/knox-token-management-ui/token-management/app/token.management.component.html
+++
b/knox-token-management-ui/token-management/app/token.management.component.html
@@ -59,7 +59,7 @@
<ng-container matColumnDef="tokenId">
<mat-header-cell *matHeaderCellDef mat-sort-header="tokenId"
style="text-align: center; justify-content: center;">Token ID</mat-header-cell>
- <mat-cell *matCellDef="let knoxToken" style="text-align:
center; justify-content: center;">
+ <mat-cell *matCellDef="let knoxToken" style="text-align:
center; justify-content: center;"
[style.font-weight]="getFontWeight(knoxToken)">
<div
*ngIf="knoxToken.metadata.enabled">{{knoxToken.tokenId}}</div>
<div *ngIf="!knoxToken.metadata.enabled"
style="color:orange">{{knoxToken.tokenId}}</div>
</mat-cell>
@@ -67,17 +67,17 @@
<ng-container matColumnDef="issued">
<mat-header-cell *matHeaderCellDef mat-sort-header="issueTime"
style="text-align: center; justify-content: center;">Issued</mat-header-cell>
- <mat-cell *matCellDef="let knoxToken" style="text-align:
center; justify-content:
center;">{{formatDateTime(knoxToken.issueTimeLong)}}</mat-cell>
+ <mat-cell *matCellDef="let knoxToken" style="text-align:
center; justify-content: center;"
[style.font-weight]="getFontWeight(knoxToken)">{{formatDateTime(knoxToken.issueTimeLong)}}</mat-cell>
</ng-container>
<ng-container matColumnDef="expires">
<mat-header-cell *matHeaderCellDef
mat-sort-header="expiration" style="text-align: center; justify-content:
center;">Expires</mat-header-cell>
- <mat-cell *matCellDef="let knoxToken"
[style.color]="getExpirationColor(knoxToken.expirationLong)" style="text-align:
center; justify-content:
center;">{{formatDateTime(knoxToken.expirationLong)}}</mat-cell>
+ <mat-cell *matCellDef="let knoxToken"
[style.color]="getExpirationColor(knoxToken.expirationLong)" style="text-align:
center; justify-content: center;"
[style.font-weight]="getFontWeight(knoxToken)">{{formatDateTime(knoxToken.expirationLong)}}</mat-cell>
</ng-container>
<ng-container matColumnDef="userName">
<mat-header-cell *matHeaderCellDef mat-sort-header="userName"
style="text-align: center; justify-content: center;">User Name</mat-header-cell>
- <mat-cell *matCellDef="let knoxToken" style="text-align:
center; justify-content: center;">{{knoxToken.metadata.userName}}</mat-cell>
+ <mat-cell *matCellDef="let knoxToken" style="text-align:
center; justify-content: center;"
[style.font-weight]="getFontWeight(knoxToken)">{{knoxToken.metadata.userName}}</mat-cell>
</ng-container>
<ng-container matColumnDef="impersonated">
diff --git
a/knox-token-management-ui/token-management/app/token.management.component.ts
b/knox-token-management-ui/token-management/app/token.management.component.ts
index edc5f3493..daa210127 100644
---
a/knox-token-management-ui/token-management/app/token.management.component.ts
+++
b/knox-token-management-ui/token-management/app/token.management.component.ts
@@ -38,6 +38,7 @@ export class TokenManagementComponent implements OnInit {
userName: string;
canSeeAllTokens: boolean;
+ currentKnoxSsoCookieTokenId: string;
knoxTokens: MatTableDataSource<KnoxToken> = new MatTableDataSource();
selection = new SelectionModel<KnoxToken>(true, []);
allKnoxTokens: KnoxToken[];
@@ -104,8 +105,9 @@ export class TokenManagementComponent implements OnInit {
console.debug('TokenManagementComponent --> ngOnInit()');
this.tokenManagementService.getSessionInformation()
.then(sessionInformation => {
- this.canSeeAllTokens = sessionInformation.canSeeAllTokens;
- this.setUserName(sessionInformation.user);
+ this.canSeeAllTokens = sessionInformation.canSeeAllTokens;
+ this.currentKnoxSsoCookieTokenId =
sessionInformation.currentKnoxSsoCookieTokenId;
+ this.setUserName(sessionInformation.user);
});
}
@@ -270,4 +272,12 @@ export class TokenManagementComponent implements OnInit {
return this.selection.selected.every(token =>
!token.metadata.knoxSsoCookie);
}
+ getFontWeight(token: KnoxToken): string {
+ return this.isCurrentKnoxSsoCookietoken(token) ? 'bold' : 'normal';
+ }
+
+ private isCurrentKnoxSsoCookietoken(token: KnoxToken): boolean {
+ return this.isKnoxSsoCookie(token) && token.tokenId ===
this.currentKnoxSsoCookieTokenId;
+ }
+
}