1 package com.atlassian.asap.core.server.filter;
2
3 import com.atlassian.asap.api.Jwt;
4 import com.google.common.collect.ImmutableMap;
5
6 import javax.servlet.http.HttpServletRequest;
7 import java.util.Map;
8 import java.util.Optional;
9 import java.util.function.Predicate;
10
11 /**
12 * This class accepts a list of issuers and the authentication rules associated with each one.
13 *
14 * <p>Any issuer that is not in the list will be rejected.
15 *
16 * <p>For example, we might have some requirement that the issuer Mallory should only be able to use the subject "Mallory",
17 * whereas the issuer Alice might be able to use the subject "Alice" or "Bob". We might write something like this:
18 *
19 * <pre>{@code
20 * rules = ImmutableMap.of(
21 * "Mallory", jwt -> "Mallory".equals(jwt.getClaims().getSubject().orElse("Mallory")),
22 * "Alice", jwt -> ImmutableSet.of("Alice", "Bob").contains(jwt.getClaims().getSubject().orElse("Alice"))
23 * );
24 * }</pre>
25 *
26 * <p>This would prevent Mallory from using Alice or Bob as the subject when we don't expect them to. (This particular
27 * example is actually covered better by the {@link IssuerAndSubjectAwareRequestAuthorizationFilter}, which extends this
28 * class.)
29 */
30 public class RulesAwareRequestAuthorizationFilter extends AbstractRequestAuthorizationFilter {
31 private final Map<String, Predicate<Jwt>> issuersAndChecks;
32
33 public RulesAwareRequestAuthorizationFilter(
34 Map<String, Predicate<Jwt>> issuersAndChecks) {
35 this.issuersAndChecks = ImmutableMap.copyOf(issuersAndChecks);
36 }
37
38 @Override
39 protected boolean isAuthorized(HttpServletRequest request, Jwt jwt) {
40 String issuer = jwt.getClaims().getIssuer();
41
42 return Optional.ofNullable(issuersAndChecks.get(issuer))
43 .map(pred -> pred.test(jwt))
44 .orElse(false);
45 }
46 }