001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2020, 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; 019 020 021import java.net.URI; 022import java.security.Provider; 023import java.util.Date; 024 025import com.nimbusds.jose.JOSEException; 026import com.nimbusds.jose.JWSAlgorithm; 027import com.nimbusds.jose.JWSHeader; 028import com.nimbusds.jose.JWSSigner; 029import com.nimbusds.jose.crypto.factories.DefaultJWSSignerFactory; 030import com.nimbusds.jose.jwk.JWK; 031import com.nimbusds.jwt.JWTClaimsSet; 032import com.nimbusds.jwt.SignedJWT; 033import com.nimbusds.oauth2.sdk.id.JWTID; 034import com.nimbusds.oauth2.sdk.token.AccessToken; 035import com.nimbusds.openid.connect.sdk.Nonce; 036 037 038/** 039 * Default DPoP proof factory. 040 */ 041public class DefaultDPoPProofFactory implements DPoPProofFactory { 042 043 044 /** 045 * The public signing JWK. 046 */ 047 private final JWK publicJWK; 048 049 050 /** 051 * The signing JWS algorithm. 052 */ 053 private final JWSAlgorithm jwsAlg; 054 055 056 /** 057 * The JWS signer. 058 */ 059 private final JWSSigner jwsSigner; 060 061 062 /** 063 * Creates a new DPoP proof factory using the default JCA provider. 064 * 065 * @param jwk The signing JWK. Must not be {@code null}. 066 * @param jwsAlg The signing JWS algorithm. Must not be {@code null}. 067 * 068 * @throws JOSEException If signer creation failed. 069 */ 070 public DefaultDPoPProofFactory(final JWK jwk, final JWSAlgorithm jwsAlg) 071 throws JOSEException { 072 073 this(jwk, jwsAlg, null); 074 } 075 076 077 /** 078 * Creates a new DPoP proof factory. 079 * 080 * @param jwk The signing JWK. Must not be {@code null}. 081 * @param jwsAlg The signing JWS algorithm. Must not be 082 * {@code null}. 083 * @param jcaProvider The JCA provider to use for signing, {@code null} 084 * to use the default. 085 * 086 * @throws JOSEException If signer creation failed. 087 */ 088 public DefaultDPoPProofFactory(final JWK jwk, final JWSAlgorithm jwsAlg, final Provider jcaProvider) 089 throws JOSEException { 090 091 if (! jwk.isPrivate()) { 092 throw new IllegalArgumentException("The JWK must include private parameters"); 093 } 094 095 if (! JWSAlgorithm.Family.SIGNATURE.contains(jwsAlg)) { 096 throw new IllegalArgumentException("The JWS algorithm must be for a digital signature"); 097 } 098 099 this.jwsAlg = jwsAlg; 100 101 DefaultJWSSignerFactory factory = new DefaultJWSSignerFactory(); 102 if (jcaProvider != null) { 103 factory.getJCAContext().setProvider(jcaProvider); 104 } 105 jwsSigner = factory.createJWSSigner(jwk, jwsAlg); 106 107 publicJWK = jwk.toPublicJWK(); 108 } 109 110 111 /** 112 * Returns the configured public signing JWK. 113 * 114 * @return The public signing JWK. 115 */ 116 public JWK getPublicJWK() { 117 return publicJWK; 118 } 119 120 121 /** 122 * Returns the configured JWS algorithm. 123 * 124 * @return The JWS algorithm. 125 */ 126 public JWSAlgorithm getJWSAlgorithm() { 127 return jwsAlg; 128 } 129 130 131 /** 132 * Returns the JWS signer. 133 * 134 * @return The JWS signer. 135 */ 136 public JWSSigner getJWSSigner() { 137 return jwsSigner; 138 } 139 140 141 @Override 142 public SignedJWT createDPoPJWT(final String htm, 143 final URI htu) 144 throws JOSEException { 145 146 return createDPoPJWT(htm, htu, null, null); 147 } 148 149 150 @Override 151 public SignedJWT createDPoPJWT(final String htm, 152 final URI htu, 153 final Nonce nonce) 154 throws JOSEException { 155 156 return createDPoPJWT(htm, htu, null, nonce); 157 } 158 159 160 @Override 161 public SignedJWT createDPoPJWT(final String htm, 162 final URI htu, 163 final AccessToken accessToken) 164 throws JOSEException { 165 166 return createDPoPJWT(htm, htu, accessToken, null); 167 } 168 169 170 @Override 171 public SignedJWT createDPoPJWT(final String htm, 172 final URI htu, 173 final AccessToken accessToken, 174 final Nonce nonce) 175 throws JOSEException { 176 177 return createDPoPJWT(new JWTID(MINIMAL_JTI_BYTE_LENGTH), htm, htu, new Date(), accessToken, nonce); 178 } 179 180 181 @Override 182 public SignedJWT createDPoPJWT(final JWTID jti, 183 final String htm, 184 final URI htu, 185 final Date iat, 186 final AccessToken accessToken) 187 throws JOSEException { 188 189 return createDPoPJWT(jti, htm, htu, iat, accessToken, null); 190 } 191 192 193 @Override 194 public SignedJWT createDPoPJWT(final JWTID jti, 195 final String htm, 196 final URI htu, 197 final Date iat, 198 final AccessToken accessToken, 199 final Nonce nonce) 200 throws JOSEException { 201 202 JWSHeader jwsHeader = new JWSHeader.Builder(getJWSAlgorithm()) 203 .type(TYPE) 204 .jwk(getPublicJWK()) 205 .build(); 206 207 JWTClaimsSet jwtClaimsSet = DPoPUtils.createJWTClaimsSet(jti, htm, htu, iat, accessToken, nonce); 208 SignedJWT signedJWT = new SignedJWT(jwsHeader, jwtClaimsSet); 209 signedJWT.sign(getJWSSigner()); 210 return signedJWT; 211 } 212}