1 package com.atlassian.asap.service.core.impl;
2
3 import com.atlassian.asap.api.Jwt;
4 import com.atlassian.asap.api.JwtBuilder;
5 import com.atlassian.asap.api.JwtClaims;
6 import com.atlassian.asap.api.client.http.AuthorizationHeaderGenerator;
7 import com.atlassian.asap.api.exception.CannotRetrieveKeyException;
8 import com.atlassian.asap.api.exception.InvalidTokenException;
9 import com.atlassian.asap.core.exception.MissingRequiredClaimException;
10 import com.atlassian.asap.service.api.AuthorizationBuilder;
11 import com.atlassian.asap.service.core.spi.AsapConfiguration;
12 import com.google.common.collect.ImmutableSet;
13
14 import javax.json.JsonObject;
15 import java.time.Duration;
16 import java.time.Instant;
17 import java.util.Optional;
18 import java.util.Set;
19
20 import static java.util.Objects.requireNonNull;
21
22 public class AuthorizationBuilderImpl implements AuthorizationBuilder {
23 private final AsapConfiguration config;
24 private final AuthorizationHeaderGenerator authHeaderGenerator;
25
26 private Optional<String> subject = Optional.empty();
27 private Optional<Duration> expiration = Optional.empty();
28 private Set<String> audience = ImmutableSet.of();
29 private Optional<JsonObject> customClaims = Optional.empty();
30
31 public AuthorizationBuilderImpl(AsapConfiguration config, AuthorizationHeaderGenerator authHeaderGenerator) {
32 this.config = requireNonNull(config, "config");
33 this.authHeaderGenerator = requireNonNull(authHeaderGenerator, "authHeaderGenerator");
34 }
35
36 @Override
37 public AuthorizationBuilder subject(Optional<String> subject) {
38 this.subject = requireNonNull(subject);
39 return this;
40 }
41
42 @Override
43 public AuthorizationBuilder audience(Iterable<String> audience) {
44 this.audience = ImmutableSet.copyOf(audience);
45 return this;
46 }
47
48 @Override
49 public AuthorizationBuilder expiration(Optional<Duration> expiration) {
50 this.expiration = requireNonNull(expiration);
51 return this;
52 }
53
54 @Override
55 public AuthorizationBuilder customClaims(Optional<JsonObject> claims) {
56 this.customClaims = requireNonNull(claims);
57 return this;
58 }
59
60 @Override
61 public String build() throws InvalidTokenException, CannotRetrieveKeyException {
62 final Jwt jwt = buildJwt();
63 return authHeaderGenerator.generateAuthorizationHeader(jwt);
64 }
65
66 private Jwt buildJwt() throws InvalidTokenException {
67 if (audience.isEmpty()) {
68 throw new MissingRequiredClaimException(JwtClaims.RegisteredClaim.AUDIENCE);
69 }
70
71 final Instant now = Instant.now();
72 final JwtBuilder jwtBuilder = JwtBuilder.newJwt()
73 .issuer(config.issuer())
74 .keyId(config.keyId())
75 .subject(subject)
76 .issuedAt(now)
77 .audience(audience);
78
79 expiration.ifPresent(ttl -> jwtBuilder.expirationTime(now.plus(ttl)));
80 customClaims.ifPresent(jwtBuilder::customClaims);
81 return jwtBuilder.build();
82 }
83 }