Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KNOX-2970 - Removing KnoxSSO cookie from the token state service upon logout #806

Merged
merged 1 commit into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 All @@ -57,8 +58,9 @@ public SessionInformation getSessionInformation() {
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;
}
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 @@ -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[];
Expand Down Expand Up @@ -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);
});
}

Expand Down Expand Up @@ -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;
}

}
Loading