Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into brig/client2-switch
Browse files Browse the repository at this point in the history
  • Loading branch information
brig committed Nov 5, 2023
2 parents 7169495 + 8d61544 commit 2d1aeb3
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ const renderProcessStatus = (process?: ProcessEntry) => {

let duration;
if (process.status === ProcessStatus.RUNNING) {
duration = formatDuration(new Date().getTime() - parseDate(process.createdAt).getTime());
duration = formatDuration(new Date().getTime() - parseDate(process.lastRunAt || process.createdAt).getTime());
}
return (
<>
Expand Down
13 changes: 12 additions & 1 deletion server/dist/src/main/resources/concord-server.conf
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,17 @@ concord-server {
pfed {
enabled = false
priority = 0

bearerToken {
# enable bearer tokens
enableBearerTokens = false

# allow all clientIds
allowAllClientIds = false

# list of allowed pingfed clientids for bearer tokens
allowedClientIds = ["clientId1", "clientId2"]
}
}
authEndpointUrl = "http://auth.example.com/authorize"
tokenEndpointUrl = "http://auth.example.com/token"
Expand All @@ -549,7 +560,7 @@ concord-server {

# enable to validate token signature
tokenSignatureValidation = false

# JSON as a string
#tokenEncryptionKey = "{}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.List;


public class JwtAuthenticator {

Expand Down Expand Up @@ -78,8 +80,8 @@ public JwtAuthenticator(SsoConfiguration cfg, SsoClient ssoClient) {
* @param token the JWT
* @return <code>true</code> if token valid and not expired
*/
public boolean isTokenValid(String token) {
return isTokenValid(token, null);
public boolean isTokenValid(String token, boolean restrictOnClientId) {
return isTokenValid(token, null, restrictOnClientId);
}

/**
Expand All @@ -89,13 +91,22 @@ public boolean isTokenValid(String token) {
* @param nonce nonce
* @return <code>true</code> if token valid, correct nonce and not expired
*/
public boolean isTokenValid(String token, String nonce) {
public boolean isTokenValid(String token, String nonce, boolean restrictOnClientId) {
try {
Map<String, Object> claims = validateTokenAndGetClaims(token);
if (claims == null) {
return false;
}

if (restrictOnClientId) {
List<String> allowedClientIds = cfg.getAllowedClientIds();
String clientId = (String) claims.get("client_id");
if(!allowedClientIds.contains(clientId)) {
log.warn("isTokenValid ['{}', '{}'] -> clientId not in allowed list for bearer tokens", token, clientId);
return false;
}
}

if (nonce == null) {
return true;
}
Expand All @@ -113,22 +124,7 @@ public boolean isTokenValid(String token, String nonce) {
}
}

/**
* Validates the token and returns the corresponding user login.
*
* @param token the JWT
* @return corresponding user login or <code>null</code> if the JWT is invalid
*/
public String validateTokenAndGetLogin(String token) {
Map<String, Object> claims = validateTokenAndGetClaims(token);
if (claims == null) {
return null;
}
return (String) claims.get("sub");
}

private Map<String, Object> validateTokenAndGetClaims(String token) {

public Map<String, Object> validateTokenAndGetClaims(String token) {
try {
JWT jwt = validateToken(token);
if (jwt == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void doFilter(HttpServletRequest request, HttpServletResponse response, F

if (token != null) {
if (refreshToken == null){
boolean isValid = jwtAuthenticator.isTokenValid(token);
boolean isValid = jwtAuthenticator.isTokenValid(token, false);
if (isValid) {
log.info("doFilter -> found valid token in cookies, redirect to '{}'", from);
redirectHelper.sendRedirect(response, from);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ public String getTokenSigningKey() throws IOException {
}
}

public Profile getUserProfile(String refreshToken) throws IOException {
public Profile getUserProfileByRefreshToken(String refreshToken) throws IOException {
Token token = getTokenByRefreshToken(refreshToken);
return getProfile(token);
return getProfile(token.accessToken());
}

private Token getToken(String urlParameters) throws IOException {
Expand Down Expand Up @@ -178,15 +178,15 @@ private void postRequest(HttpURLConnection con, String urlParameters) throws IOE
}
}

private Profile getProfile(Token token) throws IOException {
public Profile getProfile(String accessToken) throws IOException {
if (cfg.getUserInfoEndpointUrl() == null) {
return null;
}
HttpURLConnection con = null;
try {
URL url = new URL(cfg.getUserInfoEndpointUrl());
con = (HttpURLConnection) url.openConnection();
String authzHeaderValue = String.format("Bearer %s", token.accessToken());
String authzHeaderValue = String.format("Bearer %s", accessToken);
con.setRequestProperty(HttpHeaders.AUTHORIZATION, authzHeaderValue);
con.setRequestProperty(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_HEADER);
con.setRequestMethod("GET");
Expand Down Expand Up @@ -240,6 +240,9 @@ public interface Token {
@JsonIgnoreProperties(ignoreUnknown = true)
public interface Profile {

@JsonProperty("sub")
String sub();

@JsonProperty("sAMAccountName")
String userId();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
import javax.inject.Inject;
import java.io.Serializable;
import java.time.Duration;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class SsoConfiguration implements Serializable {

Expand Down Expand Up @@ -63,6 +67,14 @@ public class SsoConfiguration implements Serializable {
@Config("sso.clientSecret")
private String clientSecret;

@Inject
@Config("sso.pfed.bearerToken.enableBearerTokens")
private boolean enableBearerTokens;

@Inject
@Config("sso.pfed.bearerToken.allowAllClientIds")
private boolean allowAllClientIds;

@Inject
@Nullable
@Config("sso.tokenSigningKey")
Expand Down Expand Up @@ -103,6 +115,10 @@ public class SsoConfiguration implements Serializable {
@Config("sso.autoCreateUsers")
private boolean autoCreateUsers;

@Inject
@Config("sso.pfed.bearerToken.allowedClientIds")
private List<String> allowedClientIds;

public boolean isAutoCreateUsers() {
return autoCreateUsers;
}
Expand Down Expand Up @@ -135,6 +151,14 @@ public String getClientSecret() {
return clientSecret;
}

public boolean getEnableBearerTokens() {
return enableBearerTokens;
}

public boolean getAllowAllClientIds() {
return allowAllClientIds;
}

public String getTokenEncryptionKey() {
return tokenEncryptionKey;
}
Expand Down Expand Up @@ -170,4 +194,9 @@ public boolean isTokenSignatureValidation() {
public String getUserInfoEndpointUrl() {
return userInfoEndpointUrl;
}

public List<String> getAllowedClientIds() {
return allowedClientIds;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,34 @@ public AuthenticationToken createToken(ServletRequest request, ServletResponse r

HttpServletRequest req = WebUtils.toHttp(request);

String token = SsoCookies.getTokenCookie(req);
String bearerToken = cfg.getEnableBearerTokens() ? extractTokenFromRequest(req) : null;
String token = bearerToken != null ? bearerToken : SsoCookies.getTokenCookie(req);

if (token == null) {
return null;
}

String login = jwtAuthenticator.validateTokenAndGetLogin(token);
if (login == null) {
boolean restrictOnClientId = (bearerToken != null) && (!cfg.getAllowAllClientIds());

if (!jwtAuthenticator.isTokenValid(token, restrictOnClientId)) {
return null;
}

String[] as = parseDomain(login);

String refreshToken = SsoCookies.getRefreshCookie(req);
// get userprofile send the response as null if refreshToken is expired or used
SsoClient.Profile profile;
try {
profile = ssoClient.getUserProfile(refreshToken);
SsoClient.Profile profile = bearerToken != null ? ssoClient.getProfile(bearerToken) :
ssoClient.getUserProfileByRefreshToken(SsoCookies.getRefreshCookie(req));

if (profile == null) {
return null;
}

String[] as = parseDomain(profile.sub());

return new SsoToken(as[0], as[1], profile.displayName(), profile.mail(), profile.userPrincipalName(), profile.nameInNamespace(), profile.groups());

} catch (IOException e) {
return null;
}
if (profile == null) {
return null;
}
return new SsoToken(as[0], as[1], profile.displayName(), profile.mail(), profile.userPrincipalName(), profile.nameInNamespace(), profile.groups());
}

@Override
Expand Down Expand Up @@ -112,4 +116,20 @@ private String[] parseDomain(String s) {
String domain = s.substring(pos + 1);
return new String[]{username, domain};
}

private String extractTokenFromRequest(HttpServletRequest request) {
final String value = request.getHeader("Authorization");

if (value == null || !value.toLowerCase().startsWith("bearer")) {
return null;
}

String[] parts = value.split(" ");

if (parts.length < 2) {
return null;
}

return parts[1].trim();
}
}

0 comments on commit 2d1aeb3

Please sign in to comment.