Skip to content

Commit

Permalink
CDPD-62595, KNOX-2970: Removing KnoxSSO cookie from the token state s…
Browse files Browse the repository at this point in the history
…ervice upon logout (apache#806)

Additionally, the Token Management UI displays the 'current' KnoxSSO cookie row in bold.

Change-Id: I2c1f44d4fda67eeae5396dfb56a7116303a06fa3
  • Loading branch information
smolnar82 authored and Sandor Molnar committed Oct 25, 2023
1 parent e0d4f39 commit 65b392e
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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;
Expand Down Expand Up @@ -165,6 +166,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -35,6 +41,7 @@
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;

Expand Down Expand Up @@ -118,13 +125,35 @@ private boolean removeAuthenticationToken(HttpServletResponse response) {
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());
}
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public class SessionInformation {
@XmlElement
private boolean canSeeAllTokens;

@XmlElement
private String currentKnoxSsoCookieTokenId;

public String getUser() {
return user;
}
Expand Down Expand Up @@ -77,4 +80,12 @@ public void setCanSeeAllTokens(boolean canSeeAllTokens) {
this.canSeeAllTokens = canSeeAllTokens;
}

public String getCurrentKnoxSsoCookieTokenId() {
return currentKnoxSsoCookieTokenId;
}

public void setCurrentKnoxSsoCookieTokenId(String currentKnoxSsoCookieTokenId) {
this.currentKnoxSsoCookieTokenId = currentKnoxSsoCookieTokenId;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
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/")
Expand Down Expand Up @@ -58,7 +59,8 @@ public SessionInformation getSessionInformation() {
sessionInfo.setLogoutPageUrl(getLogoutPageUrl(config));
sessionInfo.setGlobalLogoutPageUrl(getGlobalLogoutPageUrl(config));
}
sessionInfo.setCanSeeAllTokens(config == null ? false : 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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ export class SessionInformation {
logoutPageUrl: string;
globalLgoutPageUrl: string;
canSeeAllTokens: boolean;
currentKnoxSsoCookieTokenId: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,25 @@

<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>
</ng-container>

<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">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class TokenManagementComponent implements OnInit {

userName: string;
canSeeAllTokens: boolean;
currentKnoxSsoCookieTokenId: string;
knoxTokens: MatTableDataSource<KnoxToken> = new MatTableDataSource();
selection = new SelectionModel<KnoxToken>(true, []);
allKnoxTokens: KnoxToken[];
Expand Down Expand Up @@ -102,8 +103,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);
});
}

Expand Down Expand Up @@ -268,4 +270,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;
}

}

0 comments on commit 65b392e

Please sign in to comment.