View Javadoc

1   package com.atlassian.asap.service.api;
2   
3   
4   import com.atlassian.asap.service.api.ValidationResult.Decision;
5   
6   import java.util.Optional;
7   
8   import static java.util.Arrays.asList;
9   
10  /**
11   * A builder-style tool for specifying and enforcing ASAP authentication and authorization requirements.
12   *
13   * @since 2.8
14   */
15  public interface TokenValidator {
16      /**
17       * Specifies the issuer(s) that are authorized to use this resource. Issuers in this list would be able to execute
18       * this resource without authorization checks.
19       * Note, it's possible to list the same issuer both in 'issuer' and in 'subjectImpersonationIssuer'.
20       * <p>
21       * Issuer validation is appropriate unless the resource is intended to be used as an open service that many different issuers can access.
22       * </p>
23       * <p>
24       * Failures reported as: {@link Decision#NOT_AUTHORIZED}
25       * </p>
26       *
27       * @param authorizedIssuers the issuers that are authorized to use this resource; {@code null} elements are not permitted
28       * @return {@code this}
29       */
30      default TokenValidator issuer(String... authorizedIssuers) {
31          return issuer(asList(authorizedIssuers));
32      }
33  
34      /**
35       * As for {@link #issuer(String...)}.
36       *
37       * @param authorizedIssuers as for {@link #issuer(String...)}
38       * @return {@code this}
39       */
40      TokenValidator issuer(Iterable<String> authorizedIssuers);
41  
42      /**
43       * Specifies the issuer(s) that are authorized to impersonate a user while using this resource. Issuers in this list would be able to execute
44       * this resource authorized as a certain user. Typically username comes as a subject in ASAP hence the name prefix.
45       * <p>
46       * Issuer validation is required to be used if the resource is intended to be used in the context of a user, with all the access checks
47       * </p>
48       * <p>
49       * Failures reported as: {@link Decision#NOT_AUTHORIZED}
50       * </p>
51       *
52       * @param impersonationIssuers the issuers that are authorized to impersonate a user while using this resource;
53       *                             {@code null} elements are not permitted
54       * @return {@code this}
55       */
56      default TokenValidator impersonationIssuer(String... impersonationIssuers) {
57          return impersonationIssuer(asList(impersonationIssuers));
58      }
59  
60      /**
61       * As for {@link #impersonationIssuer(String...)}.
62       *
63       * @param impersonationIssuers as for {@link #impersonationIssuer(String...)}
64       * @return {@code this}
65       */
66      TokenValidator impersonationIssuer(Iterable<String> impersonationIssuers);
67  
68      /**
69       * Specifies that the subject is to be interpreted as identifying a specific user whose identity should be
70       * assumed for this request.
71       *
72       * <p>
73       * The subject is ignored by default.  If subject impersonation is enabled, then the subject is understood
74       * to identify a user known to the application, or anonymous access when the subject is not specified.  If
75       * subject impersonation is enabled, then the {@link #issuer(String...) issuer whitelist} <strong>MUST</strong>
76       * be provided, or all tokens will be rejected.
77       * </p>
78       * <p>
79       * The validation service only approves the request for subject impersonation.  The actual implementation is
80       * left up to the surrounding framework.
81       * </p>
82       *
83       * @param subjectImpersonation {@code true} to use subject impersonation
84       * @return {@code this}
85       * @deprecated move/copy issuers that are allowed to impersonate users from the 'issuer' to the 'impersonationIssuer' list
86       */
87      @Deprecated
88      TokenValidator subjectImpersonation(boolean subjectImpersonation);
89  
90      /**
91       * Specifies the effective subject(s) that are authorized to use this resource.
92       * <p>
93       * The subject is ignored by default.  If an explicit whitelist is provided, then the effective subject
94       * must be in it for the token to pass authorization.  The effective subject is defined as:
95       * </p>
96       * <ul>
97       * <li>The token's subject, if it is specified.</li>
98       * <li>The token's issuer, if the subject is not specified and subject impersonation is not used.</li>
99       * <li>Nobody at all, if the subject is not specified and subject impersonation is enabled.</li>
100      * </ul>
101      * <p>
102      * Failures reported as: {@link Decision#NOT_AUTHORIZED}
103      * </p>
104      *
105      * @param authorizedSubjects the subjects that are authorized to use this resource; {@code null} elements are not
106      *                           permitted, and an empty list disables this check.
107      * @return {@code this}
108      */
109     default TokenValidator subject(String... authorizedSubjects) {
110         return subject(asList(authorizedSubjects));
111     }
112 
113     /**
114      * As for {@link #subject(String...)}.
115      *
116      * @param authorizedSubjects as for {@link #subject(String...)}
117      * @return {@code this}
118      */
119     TokenValidator subject(Iterable<String> authorizedSubjects);
120 
121     /**
122      * Specifies the audience(s) that will be accepted.
123      *
124      * <p>
125      * By default, the globally configured audience is assumed to be the expected value, and it is always accepted.
126      * If the token does not specify either the globally configured audience or one of the alternate values (if any)
127      * provided here, then it will not pass authentication.
128      * </p>
129      * <p>
130      * For security reasons, it is not possible to disable audience validation.  Note: This is an authentication
131      * failure, because the token itself is not accepted as valid if it is meant for some other service.
132      * </p>
133      * <p>
134      * Failures reported as: {@link Decision#NOT_AUTHENTICATED}
135      * </p>
136      *
137      * @param additionalAudienceValues the audience values that, in addition to the globally configured default, are
138      *                                 acceptable for other services to specify when creating a token to access this
139      *                                 resource
140      * @return {@code this}
141      */
142     default TokenValidator audience(String... additionalAudienceValues) {
143         return audience(asList(additionalAudienceValues));
144     }
145 
146     /**
147      * As for {@link #audience(String...)}.
148      *
149      * @param additionalAudienceValues as for {@link #audience(String...)}
150      * @return {@code this}
151      */
152     TokenValidator audience(Iterable<String> additionalAudienceValues);
153 
154     /**
155      * Specifies the validation policy for this validator.
156      *
157      * <p>
158      * By default, the validator will use {@link Policy#REQUIRE}.  If those are not the desired authentication
159      * semantics, then this method can be used to specify one of the other {@link Policy policies}, instead.
160      * The most useful ones are probably {@link Policy#IGNORE} (to disable ASAP authentication when it might
161      * otherwise have been inherited from a superclass or the surrounding context) and {@link Policy#OPTIONAL},
162      * to allow ASAP authentication to be validated when it is attempted, but without mandating its use.
163      * </p>
164      *
165      * @param policy the enforcement policy to use
166      * @return {@code this}
167      */
168     TokenValidator policy(Policy policy);
169 
170     /**
171      * Perform the validation.
172      *
173      * @param authHeader the contents of the {@code Authorization} header from the HTTP request, if any.
174      * @return the outcome from validating the {@code authHeader}
175      */
176     ValidationResult validate(Optional<String> authHeader);
177 
178 
179     /**
180      * Specifies the desired enforcement policy for ASAP authentication.
181      */
182     enum Policy {
183         /**
184          * Specifies that attempts to perform ASAP authentication with this resource should be actively rejected.
185          *
186          * <p>
187          * This policy is intended to prohibit ASAP authentication when that ability might otherwise
188          * have been inherited from some other source, such as a superclass or package annotation.
189          * </p>
190          * <p>
191          * Note that since this policy refuses all ASAP tokens regardless of their contents, tokens are not passed
192          * through their normal validity checks.  Any token received is assumed to pass authentication and
193          * rejected as unauthorized, instead.
194          * </p>
195          */
196         REJECT,
197 
198         /**
199          * Specifies that attempts to perform ASAP authentication with this resource should be silently ignored.
200          *
201          * <p>
202          * This annotation is intended to ignore ASAP authentication when that ability might otherwise
203          * have been inherited from some other source, such as a superclass or package annotation.
204          * The validator will always {@link Decision#ABSTAIN ABSTAIN} from the decision and
205          * will not attempt to examine the {@code Authorization} header in any way.
206          * </p>
207          */
208         IGNORE,
209 
210         /**
211          * Specifies that ASAP authentication is optional, but will be enforced exactly as it would for the
212          * {@link #REQUIRE} policy whenever a suitable {@code Authorization} header is present.
213          *
214          * <p>
215          * This permits alternative forms of authentication and/or anonymous request processing to be used.
216          * The resource is responsible for arranging whatever additional annotations and/or access filtering
217          * might be needed.
218          * </p>
219          * <p>
220          * Note that the only difference between {@code OPTIONAL} and {@code REQUIRED} is how the <em>complete
221          * absence</em> of an ASAP token is handled, with this policy returning {@link Decision#ABSTAIN ABSTAIN}
222          * instead of {@link Decision#NOT_AUTHENTICATED NOT_AUTHENTICATED} for that specific case.  In particular,
223          * a client cannot attempt ASAP authentication, fail at it, and then proceed anonymously.  If an ASAP
224          * token is provided, then it must meet all the necessary requirements, or the request will be rejected.
225          * </p>
226          */
227         OPTIONAL,
228 
229         /**
230          * Specifies that ASAP authentication is required.
231          * <p>
232          * If no authentication token is provided or if it does not satisfy the restrictions specified by
233          * the annotation, then the request should be actively rejected.
234          * </p>
235          */
236         REQUIRE
237     }
238 }