com.google.api.client.auth.openidconnect.IdToken Maven / Gradle / Ivy
Show all versions of google-oauth-client Show documentation
/*
* Copyright (c) 2013 Google Inc.
*
* 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.api.client.auth.openidconnect;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.webtoken.JsonWebSignature;
import com.google.api.client.json.webtoken.JsonWebToken;
import com.google.api.client.util.Beta;
import com.google.api.client.util.Key;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* {@link Beta}
* ID token as described in ID Token.
*
* Use {@link #parse(JsonFactory, String)} to parse an ID token from a string. Then, use the
* {@code verify} methods to verify the ID token as required by the specification.
*
*
Implementation is not thread-safe.
*
* @since 1.14
* @author Yaniv Inbar
*/
@Beta
public class IdToken extends JsonWebSignature {
/**
* @param header header
* @param payload payload
* @param signatureBytes bytes of the signature
* @param signedContentBytes bytes of the signature content
*/
public IdToken(Header header, Payload payload, byte[] signatureBytes, byte[] signedContentBytes) {
super(header, payload, signatureBytes, signedContentBytes);
}
@Override
public Payload getPayload() {
return (Payload) super.getPayload();
}
/**
* Returns whether the issuer in the payload matches the given expected issuer as specified in
* step 1 of ID Token
* Validation.
*
* @param expectedIssuer expected issuer
*/
public final boolean verifyIssuer(String expectedIssuer) {
return verifyIssuer(Collections.singleton(expectedIssuer));
}
/**
* Returns whether the issuer in the payload matches the given expected issuer as specified in
* step 1 of ID Token
* Validation. When an issuer is migrating to a new issuer string the expected issuer has
* multiple aliases, so multiple are permitted here.
*
* @since 1.21.0
*/
public final boolean verifyIssuer(Collection expectedIssuer) {
return expectedIssuer.contains(getPayload().getIssuer());
}
/**
* Returns whether the audience in the payload contains only client IDs that are trusted as
* specified in step 2 of ID Token
* Validation.
*
* @param trustedClientIds list of trusted client IDs
*/
public final boolean verifyAudience(Collection trustedClientIds) {
Collection audience = getPayload().getAudienceAsList();
if (audience.isEmpty()) {
return false;
}
return trustedClientIds.containsAll(audience);
}
/**
* Returns whether the {@link Payload#getExpirationTimeSeconds} and {@link
* Payload#getIssuedAtTimeSeconds} are valid relative to the current time, allowing for a clock
* skew as specified in steps 5 and 6 of ID Token
* Validation.
*
* @param currentTimeMillis current time in milliseconds (typically {@link
* System#currentTimeMillis()})
* @param acceptableTimeSkewSeconds seconds of acceptable clock skew
*/
public final boolean verifyTime(long currentTimeMillis, long acceptableTimeSkewSeconds) {
return verifyExpirationTime(currentTimeMillis, acceptableTimeSkewSeconds)
&& verifyIssuedAtTime(currentTimeMillis, acceptableTimeSkewSeconds);
}
/**
* Returns whether the {@link Payload#getExpirationTimeSeconds} is valid relative to the current
* time, allowing for a clock skew as specified in step 5 of ID Token
* Validation.
*
* @param currentTimeMillis current time in milliseconds (typically {@link
* System#currentTimeMillis()})
* @param acceptableTimeSkewSeconds seconds of acceptable clock skew
*/
public final boolean verifyExpirationTime(
long currentTimeMillis, long acceptableTimeSkewSeconds) {
return currentTimeMillis
<= (getPayload().getExpirationTimeSeconds() + acceptableTimeSkewSeconds) * 1000;
}
/**
* Returns whether the {@link Payload#getIssuedAtTimeSeconds} is valid relative to the current
* time, allowing for a clock skew as specified in step 6 of ID Token
* Validation.
*
* @param currentTimeMillis current time in milliseconds (typically {@link
* System#currentTimeMillis()})
* @param acceptableTimeSkewSeconds seconds of acceptable clock skew
*/
public final boolean verifyIssuedAtTime(long currentTimeMillis, long acceptableTimeSkewSeconds) {
return currentTimeMillis
>= (getPayload().getIssuedAtTimeSeconds() - acceptableTimeSkewSeconds) * 1000;
}
/**
* Parses the given ID token string and returns the parsed ID token.
*
* @param jsonFactory JSON factory
* @param idTokenString ID token string
* @return parsed ID token
*/
public static IdToken parse(JsonFactory jsonFactory, String idTokenString) throws IOException {
JsonWebSignature jws =
JsonWebSignature.parser(jsonFactory).setPayloadClass(Payload.class).parse(idTokenString);
return new IdToken(
jws.getHeader(),
(Payload) jws.getPayload(),
jws.getSignatureBytes(),
jws.getSignedContentBytes());
}
/**
* {@link Beta}
* ID token payload.
*/
@Beta
public static class Payload extends JsonWebToken.Payload {
/** Time (in seconds) of end-user authorization or {@code null} for none. */
@Key("auth_time")
private Long authorizationTimeSeconds;
/** Authorized party or {@code null} for none. */
@Key("azp")
private String authorizedParty;
/** Value used to associate a client session with an ID token or {@code null} for none. */
@Key private String nonce;
/** Access token hash value or {@code null} for none. */
@Key("at_hash")
private String accessTokenHash;
/** Authentication context class reference or {@code null} for none. */
@Key("acr")
private String classReference;
/** Authentication methods references or {@code null} for none. */
@Key("amr")
private List methodsReferences;
/** Returns the time (in seconds) of end-user authorization or {@code null} for none. */
public final Long getAuthorizationTimeSeconds() {
return authorizationTimeSeconds;
}
/**
* Sets the time (in seconds) of end-user authorization or {@code null} for none.
*
* Overriding is only supported for the purpose of calling the super implementation and
* changing the return type, but nothing else.
*/
public Payload setAuthorizationTimeSeconds(Long authorizationTimeSeconds) {
this.authorizationTimeSeconds = authorizationTimeSeconds;
return this;
}
/**
* Returns the authorized party or {@code null} for none.
*
*
Upgrade warning: in prior version 1.15 this method returned an {@link Object}, but
* starting with version 1.16 it returns a {@link String}.
*/
public final String getAuthorizedParty() {
return authorizedParty;
}
/**
* Sets the authorized party or {@code null} for none.
*
*
Overriding is only supported for the purpose of calling the super implementation and
* changing the return type, but nothing else.
*
*
Upgrade warning: in prior version 1.15 the parameter was an {@link Object}, but starting
* with version 1.16 the parameter is a {@link String}.
*/
public Payload setAuthorizedParty(String authorizedParty) {
this.authorizedParty = authorizedParty;
return this;
}
/**
* Returns the value used to associate a client session with an ID token or {@code null} for
* none.
*
* @since 1.16
*/
public final String getNonce() {
return nonce;
}
/**
* Sets the value used to associate a client session with an ID token or {@code null} for none.
*
*
Overriding is only supported for the purpose of calling the super implementation and
* changing the return type, but nothing else.
*
* @since 1.16
*/
public Payload setNonce(String nonce) {
this.nonce = nonce;
return this;
}
/**
* Returns the access token hash value or {@code null} for none.
*
* @since 1.16
*/
public final String getAccessTokenHash() {
return accessTokenHash;
}
/**
* Sets the access token hash value or {@code null} for none.
*
*
Overriding is only supported for the purpose of calling the super implementation and
* changing the return type, but nothing else.
*
* @since 1.16
*/
public Payload setAccessTokenHash(String accessTokenHash) {
this.accessTokenHash = accessTokenHash;
return this;
}
/**
* Returns the authentication context class reference or {@code null} for none.
*
* @since 1.16
*/
public final String getClassReference() {
return classReference;
}
/**
* Sets the authentication context class reference or {@code null} for none.
*
*
Overriding is only supported for the purpose of calling the super implementation and
* changing the return type, but nothing else.
*
* @since 1.16
*/
public Payload setClassReference(String classReference) {
this.classReference = classReference;
return this;
}
/**
* Returns the authentication methods references or {@code null} for none.
*
* @since 1.16
*/
public final List getMethodsReferences() {
return methodsReferences;
}
/**
* Sets the authentication methods references or {@code null} for none.
*
* Overriding is only supported for the purpose of calling the super implementation and
* changing the return type, but nothing else.
*
* @since 1.16
*/
public Payload setMethodsReferences(List methodsReferences) {
this.methodsReferences = methodsReferences;
return this;
}
@Override
public Payload setExpirationTimeSeconds(Long expirationTimeSeconds) {
return (Payload) super.setExpirationTimeSeconds(expirationTimeSeconds);
}
@Override
public Payload setNotBeforeTimeSeconds(Long notBeforeTimeSeconds) {
return (Payload) super.setNotBeforeTimeSeconds(notBeforeTimeSeconds);
}
@Override
public Payload setIssuedAtTimeSeconds(Long issuedAtTimeSeconds) {
return (Payload) super.setIssuedAtTimeSeconds(issuedAtTimeSeconds);
}
@Override
public Payload setIssuer(String issuer) {
return (Payload) super.setIssuer(issuer);
}
@Override
public Payload setAudience(Object audience) {
return (Payload) super.setAudience(audience);
}
@Override
public Payload setJwtId(String jwtId) {
return (Payload) super.setJwtId(jwtId);
}
@Override
public Payload setType(String type) {
return (Payload) super.setType(type);
}
@Override
public Payload setSubject(String subject) {
return (Payload) super.setSubject(subject);
}
@Override
public Payload set(String fieldName, Object value) {
return (Payload) super.set(fieldName, value);
}
@Override
public Payload clone() {
return (Payload) super.clone();
}
}
}