View Javadoc

1   package com.atlassian.asap.core.server.jersey;
2   
3   import com.atlassian.asap.api.exception.AuthenticationFailedException;
4   import com.atlassian.asap.api.exception.AuthorizationFailedException;
5   import com.atlassian.asap.api.exception.PermanentAuthenticationFailedException;
6   import com.atlassian.asap.api.exception.TransientAuthenticationFailedException;
7   import com.atlassian.asap.core.JwtConstants;
8   
9   import javax.ws.rs.container.ContainerRequestContext;
10  import javax.ws.rs.core.HttpHeaders;
11  import javax.ws.rs.core.Response;
12  
13  import static java.lang.String.format;
14  
15  /**
16   * An extension point for customizing how the authentication and authorization failures are returned to the client.
17   */
18  @SuppressWarnings("WeakerAccess")
19  public interface FailureHandler {
20      /**
21       * Handles when the Jwt token cannot validated, because of a possibly transient error (like a communication
22       * failure or 500 error response). In this case a retry maybe possible.
23       *
24       * <p>Iif no retry is to be attempted (returning {@code false}, then the request should be aborted using the
25       * {@link ContainerRequestContext} instance.
26       *
27       * <p>By default, this method simply delegate to
28       * {@link #onAuthenticationFailure(ContainerRequestContext, AuthenticationFailedException)} and returns
29       * {@code false} in order to NOT retry.
30       *
31       * @param context The request context
32       * @param e       The {@link TransientAuthenticationFailedException}
33       * @return {@code true} if the authentication should be retried, {@code false} otherwise.
34       * @see #onPermanentAuthenticationFailure(ContainerRequestContext, PermanentAuthenticationFailedException)
35       * @see #onAuthenticationFailure(ContainerRequestContext, AuthenticationFailedException)
36       * @since 2.9.0
37       */
38      default boolean onTransientAuthenticationFailure(ContainerRequestContext context,
39                                                       TransientAuthenticationFailedException e) {
40          onAuthenticationFailure(context, e);
41          return false; // do not retry by default
42      }
43  
44      /**
45       * Handles when the Jwt token cannot validated, because of a permanent error (such as wrong header value,
46       * incorrect signature, etc.).  Requests should be aborted using the {@link ContainerRequestContext} instance.
47       *
48       * <p>By default, this method simply delegate to
49       * {@link #onAuthenticationFailure(ContainerRequestContext, AuthenticationFailedException)}
50       *
51       * @param context The request context
52       * @param e       The {@link PermanentAuthenticationFailedException}
53       * @see #onTransientAuthenticationFailure(ContainerRequestContext, TransientAuthenticationFailedException)
54       * @see #onAuthenticationFailure(ContainerRequestContext, AuthenticationFailedException)
55       * @since 2.9.0
56       */
57      default void onPermanentAuthenticationFailure(ContainerRequestContext context,
58                                                    PermanentAuthenticationFailedException e) {
59          onAuthenticationFailure(context, e);
60      }
61  
62      /**
63       * Handles when the Jwt token cannot be parsed or validated.  Requests should be aborted using the {@link
64       * ContainerRequestContext} instance
65       *
66       * <p>Default implementation returns a {@link Response.Status#UNAUTHORIZED HTTP 401} with an empty body.
67       *
68       * <p>If you want to handle more sprecific {@link TransientAuthenticationFailedException}
69       * and {@link PermanentAuthenticationFailedException}, respectively implement
70       * {@link #onTransientAuthenticationFailure(ContainerRequestContext, TransientAuthenticationFailedException)}
71       * and {@link #onPermanentAuthenticationFailure(ContainerRequestContext, PermanentAuthenticationFailedException)}.
72       * <strong>Note</strong> you'll still need to implement this method to handle generic
73       * {@link AuthenticationFailedException}s.
74       *
75       * @param context The request context
76       * @param e       The {@link AuthenticationFailedException}
77       * @since 2.9.0
78       */
79      default void onAuthenticationFailure(ContainerRequestContext context, AuthenticationFailedException e) {
80          onAuthenticationFailure(context, format("JWT token cannot be verified: %s", e.getMessage()));
81      }
82  
83      /**
84       * Handles when the Jwt token cannot be parsed or validated.  Requests should be aborted using the {@link
85       * ContainerRequestContext} instance
86       *
87       * @param context The request context
88       * @param message The error message
89       * @since 2.9.0.
90       * @deprecated Use {@link #onAuthenticationFailure(ContainerRequestContext, AuthenticationFailedException)} instead.
91       */
92      @Deprecated
93      default void onAuthenticationFailure(ContainerRequestContext context, String message) {
94          context.abortWith(Response.status(Response.Status.UNAUTHORIZED)
95                  .header(HttpHeaders.WWW_AUTHENTICATE, JwtConstants.BEARER_AUTHENTICATION_SCHEME)
96                  .build());
97      }
98  
99      /**
100      * Handles when the Jwt token claims cannot be authorized.  Requests should be aborted using the {@link
101      * ContainerRequestContext} instance
102      *
103      * @param context The request context
104      * @param e       The {@link AuthorizationFailedException authorization exception}
105      * @since 2.9.0
106      */
107     default void onAuthorizationFailure(ContainerRequestContext context, AuthorizationFailedException e) {
108         onAuthorizationFailure(context, e.getMessage());
109     }
110 
111     /**
112      * Handles when the Jwt token claims cannot be authorized.  Requests should be aborted using the {@link
113      * ContainerRequestContext} instance
114      *
115      * @param context The request context
116      * @param message The error message
117      * @since v2.9.0.
118      * @deprecated Use {@link #onAuthorizationFailure(ContainerRequestContext, AuthorizationFailedException)} instead.
119      */
120     @Deprecated
121     default void onAuthorizationFailure(ContainerRequestContext context, String message) {
122         context.abortWith(Response.status(Response.Status.FORBIDDEN).build());
123     }
124 }