001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2021, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.oauth2.sdk.dpop.verifiers; 019 020 021import com.nimbusds.jose.JOSEException; 022import com.nimbusds.jose.JWSAlgorithm; 023import com.nimbusds.jwt.SignedJWT; 024import com.nimbusds.oauth2.sdk.dpop.JWKThumbprintConfirmation; 025import com.nimbusds.oauth2.sdk.id.JWTID; 026import com.nimbusds.oauth2.sdk.util.singleuse.SingleUseChecker; 027import com.nimbusds.openid.connect.sdk.Nonce; 028import net.jcip.annotations.ThreadSafe; 029 030import java.net.URI; 031import java.util.Map; 032import java.util.Objects; 033import java.util.Set; 034 035 036/** 037 * DPoP proof JWT verifier for the OAuth 2.0 token endpoint of an authorisation 038 * server. 039 */ 040@ThreadSafe 041public class DPoPTokenRequestVerifier extends DPoPCommonVerifier { 042 043 044 /** 045 * The token endpoint URI. 046 */ 047 private final URI endpointURI; 048 049 050 /** 051 * Creates a new DPoP proof JWT verifier for the OAuth 2.0 token 052 * endpoint. 053 * 054 * @param acceptedJWSAlgs The accepted JWS algorithms. Must be 055 * supported and not {@code null}. 056 * @param endpointURI The token endpoint URI. Any query or 057 * fragment component will be stripped from 058 * it before performing the comparison. Must 059 * not be {@code null}. 060 * @param maxClockSkewSeconds The maximum permitted DPoP proof "iat" 061 * clock skew, in seconds. A proof with 062 * "iat" in the future is accepted if it is 063 * within this skew tolerance. Intended to 064 * prevent rejections due to client and 065 * server system time differences. 066 * @param maxAgeSeconds The maximum accepted DPoP proof "iat" age 067 * relative to the current system time, in 068 * seconds. Intended to limit replay by 069 * bounding how long a proof is valid after 070 * issue. 071 * @param singleUseChecker The single use checker for the DPoP proof 072 * "jti" (JWT ID) claims, {@code null} if 073 * not specified. 074 */ 075 public DPoPTokenRequestVerifier(final Set<JWSAlgorithm> acceptedJWSAlgs, 076 final URI endpointURI, 077 final long maxClockSkewSeconds, 078 final long maxAgeSeconds, 079 final SingleUseChecker<DPoPProofUse> singleUseChecker) { 080 081 super(acceptedJWSAlgs, maxClockSkewSeconds, maxAgeSeconds, singleUseChecker); 082 this.endpointURI = Objects.requireNonNull(endpointURI); 083 } 084 085 086 /** 087 * Creates a new DPoP proof JWT verifier for the OAuth 2.0 token 088 * endpoint. 089 * 090 * @param acceptedJWSAlgs The accepted JWS algorithms. Must be 091 * supported and not {@code null}. 092 * @param endpointURI The token endpoint URI. Any query or 093 * fragment component will be stripped from 094 * it before performing the comparison. Must 095 * not be {@code null}. 096 * @param maxClockSkewSeconds The maximum permitted DPoP proof "iat" 097 * clock skew, in seconds. A proof with 098 * "iat" in the future is accepted if it is 099 * within this skew tolerance. Intended to 100 * prevent rejections due to client and 101 * server system time differences. 102 * @param singleUseChecker The single use checker for the DPoP proof 103 * "jti" (JWT ID) claims, {@code null} if 104 * not specified. 105 */ 106 @Deprecated 107 public DPoPTokenRequestVerifier(final Set<JWSAlgorithm> acceptedJWSAlgs, 108 final URI endpointURI, 109 final long maxClockSkewSeconds, 110 final SingleUseChecker<Map.Entry<DPoPIssuer, JWTID>> singleUseChecker) { 111 112 super(acceptedJWSAlgs, maxClockSkewSeconds, singleUseChecker); 113 this.endpointURI = Objects.requireNonNull(endpointURI); 114 } 115 116 117 /** 118 * Verifies the specified DPoP proof and returns the DPoP JWK SHA-256 119 * thumbprint confirmation. 120 * 121 * @param issuer Unique identifier for the DPoP proof issuer, typically 122 * as its client ID. Must not be {@code null}. 123 * @param proof The DPoP proof JWT. Must not be {@code null}. 124 * 125 * @return The DPoP JWK SHA-256 thumbprint confirmation. 126 * 127 * @throws InvalidDPoPProofException If the DPoP proof is invalid. 128 * @throws JOSEException If an internal JOSE exception is 129 * encountered. 130 */ 131 @Deprecated 132 public JWKThumbprintConfirmation verify(final DPoPIssuer issuer, final SignedJWT proof) 133 throws InvalidDPoPProofException, JOSEException { 134 135 return verify(issuer, proof, null); 136 } 137 138 139 /** 140 * Verifies the specified DPoP proof and returns the DPoP JWK SHA-256 141 * thumbprint confirmation. 142 * 143 * @param issuer Unique identifier for the DPoP proof issuer, typically 144 * as its client ID. Must not be {@code null}. 145 * @param proof The DPoP proof JWT. Must not be {@code null}. 146 * @param nonce The expected DPoP proof JWT nonce, {@code null} if 147 * none. 148 * 149 * @return The DPoP JWK SHA-256 thumbprint confirmation. 150 * 151 * @throws InvalidDPoPProofException If the DPoP proof is invalid. 152 * @throws JOSEException If an internal JOSE exception is 153 * encountered. 154 */ 155 public JWKThumbprintConfirmation verify(final DPoPIssuer issuer, final SignedJWT proof, final Nonce nonce) 156 throws InvalidDPoPProofException, JOSEException { 157 158 try { 159 super.verify("POST", endpointURI, issuer, proof, null, null, nonce); 160 } catch (AccessTokenValidationException e) { 161 throw new RuntimeException("Unexpected exception", e); 162 } 163 164 return new JWKThumbprintConfirmation(proof.getHeader().getJWK().computeThumbprint()); 165 } 166}