Allow setting custom entitlements

This commit is contained in:
Andreas Svanberg 2025-03-27 15:03:45 +01:00
parent 7fd46e88fe
commit 2c6716865b
Signed by: ansv7779
GPG Key ID: 2D081222BBEB56A3
5 changed files with 67 additions and 2 deletions
docker-compose.yaml
src
main
test/java/se/su/dsv/oauth2

@ -7,4 +7,4 @@ services:
MARIADB_USER: oauth2
MARIADB_PASSWORD: oauth2
ports:
- "3306"
- "60123:3306"

@ -5,6 +5,8 @@ import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
/**
* All the details provided by Shibboleth. Each entitlement is represented as a {@link GrantedAuthority}.
@ -47,4 +49,12 @@ public class ShibbolethAuthenticationDetails extends PreAuthenticatedGrantedAuth
public String familyName() {
return familyName;
}
public Set<Entitlement> entitlements() {
return getGrantedAuthorities()
.stream()
.filter(Entitlement.class::isInstance)
.map(Entitlement.class::cast)
.collect(Collectors.toUnmodifiableSet());
}
}

@ -28,9 +28,12 @@ import se.su.dsv.oauth2.shibboleth.ShibbolethAuthenticationDetails;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class CustomAuthorizationEndpointFilter extends HttpFilter {
@ -143,7 +146,7 @@ public class CustomAuthorizationEndpointFilter extends HttpFilter {
}
private ShibbolethAuthenticationDetails buildShibbolethDetails(final HttpServletRequest request) {
final Collection<? extends GrantedAuthority> authorities = Set.of();
final Collection<? extends GrantedAuthority> authorities = getEntitlements(request);
final String emailAddress = request.getParameter("mail");
final String displayName = request.getParameter("displayName");
final String givenName = request.getParameter("givenName");
@ -151,6 +154,19 @@ public class CustomAuthorizationEndpointFilter extends HttpFilter {
return new ShibbolethAuthenticationDetails(request, authorities, emailAddress, displayName, givenName, familyName);
}
private Collection<? extends GrantedAuthority> getEntitlements(HttpServletRequest request) {
String entitlements = request.getParameter("entitlements");
if (entitlements == null) {
return Set.of();
}
return Arrays.stream(entitlements.split("\n"))
.map(String::trim)
.filter(Predicate.not(String::isBlank))
.map(Entitlement::new)
.collect(Collectors.toUnmodifiableSet());
}
private static void respondWithTemplate(final HttpServletResponse response, final JteModel view) throws IOException {
Utf8ByteOutput output = new Utf8ByteOutput();
view.render(output);

@ -21,6 +21,13 @@
The username, e.g. abcd1234@su.se
</small>
</div>
<div class="mb-3">
<label class="form-label" for="entitlements">Entitlements</label>
<textarea class="form-control" name="entitlements" id="entitlements" rows="3"></textarea>
<small class="text-muted">
One entitlement per line, e.g. urn:mace:swami.se:gmai:dsv-user:staff
</small>
</div>
<div class="mb-3">
<label class="form-label" for="mail">E-mail address</label>
<input class="form-control" name="mail" id="mail">
@ -47,6 +54,15 @@
<dt>Principal</dt>
<dd>${principalName}</dd>
<dt>Entitlements</dt>
<dd>
<ul>
@for (var entitlement : shibbolethDetails.entitlements())
<li>${entitlement.entitlement()}</li>
@endfor
</ul>
</dd>
<dt>E-mail address</dt>
<dd>${shibbolethDetails.emailAddress()}</dd>

@ -132,4 +132,27 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
assertEquals(customFamilyName, claimsSet.getClaim(StandardClaimNames.FAMILY_NAME));
}
@Test
public void custom_entitlements() throws Exception {
String principal = "developer";
String customEntitlement = "custom-entitlement";
TokenResponse tokenResponse = authorizePost(request -> request
.with(remoteUser(principal)
.entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("scope", "openid profile")
.formField("principal", principal)
.formField("entitlements", customEntitlement));
String accessToken = tokenResponse.accessToken();
assertNotNull(accessToken, "No id token issued");
JWTClaimsSet claims = verifyToken(accessToken);
assertNotNull(claims.getClaim("entitlements"), "No entitlements claim");
assertTrue(claims.getStringListClaim("entitlements").contains(customEntitlement),
"Does not contain custom entitlement");
}
}