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 }