1 package com.atlassian.asap.core.client.jersey;
2
3 import com.atlassian.asap.api.Jwt;
4 import com.atlassian.asap.api.JwtBuilder;
5 import com.atlassian.asap.api.client.http.AuthorizationHeaderGenerator;
6 import com.atlassian.asap.api.exception.CannotRetrieveKeyException;
7 import com.atlassian.asap.api.exception.InvalidTokenException;
8 import com.atlassian.asap.core.client.http.AuthorizationHeaderGeneratorImpl;
9 import com.google.common.annotations.VisibleForTesting;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 import javax.annotation.Priority;
14 import javax.ws.rs.Priorities;
15 import javax.ws.rs.client.ClientRequestContext;
16 import javax.ws.rs.client.ClientRequestFilter;
17 import javax.ws.rs.core.Response;
18 import javax.ws.rs.ext.Provider;
19 import java.io.IOException;
20 import java.net.URI;
21 import java.time.Instant;
22 import java.util.Objects;
23 import java.util.Optional;
24 import java.util.UUID;
25
26 import static javax.ws.rs.core.HttpHeaders.AUTHORIZATION;
27 import static javax.ws.rs.core.Response.Status.UNAUTHORIZED;
28
29
30
31
32
33
34 @Provider
35 @Priority(Priorities.AUTHENTICATION)
36 public class AsapAuthenticationFilter implements ClientRequestFilter {
37 @VisibleForTesting
38 static final String CLIENT_ASAP_TOKEN_ERROR_MESSAGE = "Client failed to generate ASAP token.";
39
40 private static final Logger log = LoggerFactory.getLogger(AsapAuthenticationFilter.class);
41
42 private final Jwt prototype;
43 private final AuthorizationHeaderGenerator authorizationHeaderGenerator;
44
45 public AsapAuthenticationFilter(Jwt prototype, URI privateKeyPath) {
46 this(prototype, AuthorizationHeaderGeneratorImpl.createDefault(privateKeyPath));
47 }
48
49 public AsapAuthenticationFilter(Jwt prototype, AuthorizationHeaderGenerator authorizationHeaderGenerator) {
50 this.prototype = Objects.requireNonNull(prototype);
51 this.authorizationHeaderGenerator = Objects.requireNonNull(authorizationHeaderGenerator);
52 }
53
54 private String getAsapBearerToken() throws CannotRetrieveKeyException, InvalidTokenException {
55 return authorizationHeaderGenerator.generateAuthorizationHeader(newJwtToken());
56 }
57
58 private Jwt newJwtToken() {
59 Instant now = Instant.now();
60
61 return JwtBuilder.copyJwt(prototype)
62 .notBefore(Optional.of(now))
63 .issuedAt(now)
64 .expirationTime(now.plus(JwtBuilder.DEFAULT_LIFETIME))
65 .jwtId(UUID.randomUUID().toString())
66 .build();
67 }
68
69 @Override
70 public void filter(ClientRequestContext requestContext) throws IOException {
71 if (!requestContext.getHeaders().containsKey(AUTHORIZATION)) {
72 try {
73 requestContext.getHeaders().add(AUTHORIZATION, getAsapBearerToken());
74 } catch (CannotRetrieveKeyException | InvalidTokenException ex) {
75 log.error("Exception generating ASAP token.", ex);
76 requestContext.abortWith(Response.status(UNAUTHORIZED).entity(CLIENT_ASAP_TOKEN_ERROR_MESSAGE).build());
77 }
78 }
79 }
80 }