// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.google.crypto.tink.jwt; import com.google.errorprone.annotations.Immutable; import java.time.Instant; import java.util.List; import java.util.Set; /** * A decoded and verified JSON Web Token (JWT). * *

A new instance of this class is returned as the result of a sucessfully verification of a * MACed or signed compact JWT. * *

It gives read-only access all payload claims and a subset of the headers. It does not contain * any headers that depend on the key, such as "alg" or "kid". These headers are checked when the * signature is verified and should not be read by the user. This ensures that the key can be * changed without any changes to the user code. */ @Immutable public final class VerifiedJwt { private final RawJwt rawJwt; VerifiedJwt(RawJwt rawJwt) { this.rawJwt = rawJwt; } /** * Returns the {@code typ} header value. Throws a JwtInvalidException if header is not present. */ public String getTypeHeader() throws JwtInvalidException { return this.rawJwt.getTypeHeader(); } /** * Returns true iff the {@code typ} header is present. */ public boolean hasTypeHeader() { return this.rawJwt.hasTypeHeader(); } /** * Returns the {@code iss} claim that identifies the principal that issued the JWT. Throws a * JwtInvalidException if no such claim is present. */ public String getIssuer() throws JwtInvalidException { return this.rawJwt.getIssuer(); } /** * Returns true iff the {@code iss} claim is present. */ public boolean hasIssuer() { return this.rawJwt.hasIssuer(); } /** * Returns the {@code sub} claim identifying the principal that is the subject of the JWT. Throws * a JwtInvalidException if no such claim is present. */ public String getSubject() throws JwtInvalidException { return this.rawJwt.getSubject(); } /** * Returns true iff the {@code sub} claim is present. */ public boolean hasSubject() { return this.rawJwt.hasSubject(); } /** * Returns the {@code aud} claim identifying the principals that are the audience of the JWT. * Throws a JwtInvalidException if no such claim is present. */ public List getAudiences() throws JwtInvalidException { return this.rawJwt.getAudiences(); } /** * Returns true iff the {@code aud} claim is present. */ public boolean hasAudiences() { return this.rawJwt.hasAudiences(); } /** * Returns the {@code jti} claim that provides a unique identifier for the JWT. Throws a * JwtInvalidException if no such claim is present. */ public String getJwtId() throws JwtInvalidException { return this.rawJwt.getJwtId(); } /** * Returns true iff the {@code jti} claim is present. */ public boolean hasJwtId() { return this.rawJwt.hasJwtId(); } /** * Returns the expiration time claim {@code exp} that identifies the instant on or after which the * token MUST NOT be accepted for processing. Throws a JwtInvalidException if no such claim is * present. * *

This API requires {@link java.time.Instant} which is unavailable on Android until API level * 26. To use it on older Android devices, enable API desugaring as shown in * https://developer.android.com/studio/write/java8-support#library-desugaring. */ public Instant getExpiration() throws JwtInvalidException { return this.rawJwt.getExpiration(); } /** * Returns true iff the {@code exp} claim is present. */ public boolean hasExpiration() { return this.rawJwt.hasExpiration(); } /** * Returns the not before claim {@code nbf} that identifies the instant before which the token * MUST NOT be accepted for processing. Throws a JwtInvalidException if no such claim is * present. * *

This API requires {@link java.time.Instant} which is unavailable on Android until API level * 26. To use it on older Android devices, enable API desugaring as shown in * https://developer.android.com/studio/write/java8-support#library-desugaring. */ public Instant getNotBefore() throws JwtInvalidException { return this.rawJwt.getNotBefore(); } /** * Returns true iff the {@code nbf} claim is present. */ public boolean hasNotBefore() { return this.rawJwt.hasNotBefore(); } /** * Returns the issued at time claim {@code iat} that identifies the instant at which the JWT was * issued. Throws a JwtInvalidException if no such claim is present. * *

This API requires {@link java.time.Instant} which is unavailable on Android until API level * 26. To use it on older Android devices, enable API desugaring as shown in * https://developer.android.com/studio/write/java8-support#library-desugaring. */ public Instant getIssuedAt() throws JwtInvalidException { return this.rawJwt.getIssuedAt(); } /** * Returns true iff the {@code iat} claim is present. */ public boolean hasIssuedAt() { return this.rawJwt.hasIssuedAt(); } /** * Returns the non-registered claim of name {@code name} and type Boolean. Throws a * JwtInvalidException if no such claim is present or the claim has another type. */ public Boolean getBooleanClaim(String name) throws JwtInvalidException { return this.rawJwt.getBooleanClaim(name); } /** * Returns the non-registered claim of name {@code name} and type Number. Throws a * JwtInvalidException if no such claim is present or the claim has another type. */ public Double getNumberClaim(String name) throws JwtInvalidException { return this.rawJwt.getNumberClaim(name); } /** * Returns the non-registered claim of name {@code name} and type String. Throws a * JwtInvalidException if no such claim is present or the claim has another type. */ public String getStringClaim(String name) throws JwtInvalidException { return this.rawJwt.getStringClaim(name); } /** Returns true iff there is a non-registered claim of name {@code name} and type NULL. */ public boolean isNullClaim(String name) { return this.rawJwt.isNullClaim(name); } /** * Returns the non-registered claim of name {@code name} and type JSON Object encoded in a string. * Throws a JwtInvalidException if no such claim is present or the claim has another type. */ public String getJsonObjectClaim(String name) throws JwtInvalidException { return this.rawJwt.getJsonObjectClaim(name); } /** * Returns the non-registered claim of name {@code name} and type JSON Array encoded in a string. * Throws a JwtInvalidException if no such claim is present or the claim has another type. */ public String getJsonArrayClaim(String name) throws JwtInvalidException { return this.rawJwt.getJsonArrayClaim(name); } /** * Returns true iff a non-registered claim of name {@code name} and type boolean is present. */ public boolean hasBooleanClaim(String name) { return this.rawJwt.hasBooleanClaim(name); } /** * Returns true iff a non-registered claim of name {@code name} and type number is present. */ public boolean hasNumberClaim(String name) { return this.rawJwt.hasNumberClaim(name); } /** * Returns true iff a non-registered claim of name {@code name} and type string is present. */ public boolean hasStringClaim(String name) { return this.rawJwt.hasStringClaim(name); } /** * Returns true iff a non-registered claim of name {@code name} and type JsonObject is present. */ public boolean hasJsonObjectClaim(String name) { return this.rawJwt.hasJsonObjectClaim(name); } /** * Returns true iff a non-registered claim of name {@code name} and type JsonArray is present. */ public boolean hasJsonArrayClaim(String name) { return this.rawJwt.hasJsonArrayClaim(name); } /** * Returns all non-registered claim names. */ public Set customClaimNames() { return this.rawJwt.customClaimNames(); } /** * Returns a brief description of a VerifiedJwt object. The exact details of the representation * are unspecified and subject to change. */ @Override public String toString() { return "verified{" + this.rawJwt + "}"; } }