View Javadoc

1   package com.atlassian.asap.core.server.filter;
2   
3   import com.atlassian.asap.api.Jwt;
4   
5   import java.util.Map;
6   import java.util.Set;
7   import java.util.function.Predicate;
8   
9   import static java.util.function.Function.identity;
10  import static java.util.stream.Collectors.toMap;
11  
12  /**
13   * This filter takes a map of issuers and predicates that define which issuers should be allowed to make ASAP requests
14   * and what the subjects for those issuers should look like.
15   *
16   * <p>If a request does not specify the subject, the subject is assumed to be the issuer.
17   *
18   * <p>A concrete use case for this would be if you have a service that is only allowed to specify certain users as the
19   * subject. For example, if {@code "impersonation-service"} is allowed to use any {@code @atlassian.com} users as the
20   * subject, you could define a set of rules like this:
21   *
22   * <pre>{@code
23   *      ImmutableMap.of("impersonation-service", Pattern.compile(".*@atlassian\\.com").asPredicate())
24   * }</pre>
25   */
26  public class IssuerAndSubjectAwareRequestAuthorizationFilter extends RulesAwareRequestAuthorizationFilter {
27      public IssuerAndSubjectAwareRequestAuthorizationFilter(Map<String, Predicate<String>> issuersAndSubjectChecks) {
28          super(toJwtRules(issuersAndSubjectChecks));
29      }
30  
31      /**
32       * A helper constructor to construct a filter from a list of issuers.
33       *
34       * <p>Issuers cannot impersonate anybody. The issuer must be the same as the subject. (The subject may be blank, in
35       * which case we treat the issuer as the subject).
36       *
37       * @param issuers A list of issuers to whitelist
38       * @return A filter that only accepts self-signed JWTs from the listed issuers
39       */
40      public static IssuerAndSubjectAwareRequestAuthorizationFilter issuers(Set<String> issuers) {
41          return new IssuerAndSubjectAwareRequestAuthorizationFilter(issuerAndSubjectMatches(issuers));
42      }
43  
44      private static Map<String, Predicate<String>> issuerAndSubjectMatches(Set<String> issuers) {
45          return issuers.stream().collect(toMap(
46                  identity(),
47                  issuer -> issuer::equals
48          ));
49      }
50  
51      private static Map<String, Predicate<Jwt>> toJwtRules(Map<String, Predicate<String>> subjectRules) {
52          return subjectRules.entrySet().stream().collect(toMap(
53                  Map.Entry::getKey,
54                  entry -> jwt -> entry.getValue().test(jwt.getClaims().getSubject().orElse(jwt.getClaims().getIssuer()))
55          ));
56      }
57  }