• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019, Google LLC
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *    * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *    * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *
15  *    * Neither the name of Google LLC nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package com.google.auth.oauth2;
33 
34 import com.google.auto.value.AutoValue;
35 import com.google.common.collect.ImmutableMap;
36 import java.io.Serializable;
37 import java.util.Map;
38 import javax.annotation.Nullable;
39 
40 /**
41  * Value class representing the set of fields used as the payload of a JWT token.
42  *
43  * <p>To create and customize claims, use the builder:
44  *
45  * <pre><code>
46  * Claims claims = Claims.newBuilder()
47  *     .setAudience("https://example.com/some-audience")
48  *     .setIssuer("some-issuer@example.com")
49  *     .setSubject("some-subject@example.com")
50  *     .build();
51  * </code></pre>
52  */
53 @AutoValue
54 public abstract class JwtClaims implements Serializable {
55   private static final long serialVersionUID = 4974444151019426702L;
56 
57   @Nullable
getAudience()58   abstract String getAudience();
59 
60   @Nullable
getIssuer()61   abstract String getIssuer();
62 
63   @Nullable
getSubject()64   abstract String getSubject();
65 
66   /**
67    * Returns additional claims for this object. The returned map is not guaranteed to be mutable.
68    *
69    * @return additional claims
70    */
getAdditionalClaims()71   abstract Map<String, String> getAdditionalClaims();
72 
newBuilder()73   public static Builder newBuilder() {
74     return new AutoValue_JwtClaims.Builder().setAdditionalClaims(ImmutableMap.<String, String>of());
75   }
76 
77   /**
78    * Returns a new Claims instance with overridden fields.
79    *
80    * <p>Any non-null field will overwrite the value from the original claims instance.
81    *
82    * @param other claims to override
83    * @return new claims
84    */
merge(JwtClaims other)85   public JwtClaims merge(JwtClaims other) {
86     ImmutableMap.Builder<String, String> newClaimsBuilder = ImmutableMap.builder();
87     newClaimsBuilder.putAll(getAdditionalClaims());
88     newClaimsBuilder.putAll(other.getAdditionalClaims());
89 
90     return newBuilder()
91         .setAudience(other.getAudience() == null ? getAudience() : other.getAudience())
92         .setIssuer(other.getIssuer() == null ? getIssuer() : other.getIssuer())
93         .setSubject(other.getSubject() == null ? getSubject() : other.getSubject())
94         .setAdditionalClaims(newClaimsBuilder.build())
95         .build();
96   }
97 
98   /**
99    * Returns whether or not this set of claims is complete.
100    *
101    * <p>Audience, issuer, and subject are required to be set in order to use the claim set for a JWT
102    * token. An incomplete Claims instance is useful for overriding claims when using {@link
103    * ServiceAccountJwtAccessCredentials#jwtWithClaims(JwtClaims)} or {@link
104    * JwtCredentials#jwtWithClaims(JwtClaims)}.
105    *
106    * @return true if all required fields have been set; false otherwise
107    */
isComplete()108   public boolean isComplete() {
109     boolean hasScopes =
110         getAdditionalClaims().containsKey("scope") && !getAdditionalClaims().get("scope").isEmpty();
111     return (getAudience() != null || hasScopes) && getIssuer() != null && getSubject() != null;
112   }
113 
114   @AutoValue.Builder
115   public abstract static class Builder {
setAudience(String audience)116     public abstract Builder setAudience(String audience);
117 
setIssuer(String issuer)118     public abstract Builder setIssuer(String issuer);
119 
setSubject(String subject)120     public abstract Builder setSubject(String subject);
121 
setAdditionalClaims(Map<String, String> additionalClaims)122     public abstract Builder setAdditionalClaims(Map<String, String> additionalClaims);
123 
build()124     public abstract JwtClaims build();
125   }
126 }
127