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; 035 036 037/** 038 * Default DPoP proof factory. 039 */ 040public class DefaultDPoPProofFactory implements DPoPProofFactory { 041 042 043 /** 044 * The public signing JWK. 045 */ 046 private final JWK publicJWK; 047 048 049 /** 050 * The signing JWS algorithm. 051 */ 052 private final JWSAlgorithm jwsAlg; 053 054 055 /** 056 * The JWS signer. 057 */ 058 private final JWSSigner jwsSigner; 059 060 061 /** 062 * Creates a new DPoP proof factory using the default JCA provider. 063 * 064 * @param jwk The signing JWK. Must not be {@code null}. 065 * @param jwsAlg The signing JWS algorithm. Must not be {@code null}. 066 * 067 * @throws JOSEException If signer creation failed. 068 */ 069 public DefaultDPoPProofFactory(final JWK jwk, final JWSAlgorithm jwsAlg) 070 throws JOSEException { 071 072 this(jwk, jwsAlg, null); 073 } 074 075 076 /** 077 * Creates a new DPoP proof factory. 078 * 079 * @param jwk The signing JWK. Must not be {@code null}. 080 * @param jwsAlg The signing JWS algorithm. Must not be 081 * {@code null}. 082 * @param jcaProvider The JCA provider to use for signing, {@code null} 083 * to use the default. 084 * 085 * @throws JOSEException If signer creation failed. 086 */ 087 public DefaultDPoPProofFactory(final JWK jwk, final JWSAlgorithm jwsAlg, final Provider jcaProvider) 088 throws JOSEException { 089 090 if (! jwk.isPrivate()) { 091 throw new IllegalArgumentException("The JWK must include private parameters"); 092 } 093 094 if (! JWSAlgorithm.Family.SIGNATURE.contains(jwsAlg)) { 095 throw new IllegalArgumentException("The JWS algorithm must be for a digital signature"); 096 } 097 098 this.jwsAlg = jwsAlg; 099 100 DefaultJWSSignerFactory factory = new DefaultJWSSignerFactory(); 101 if (jcaProvider != null) { 102 factory.getJCAContext().setProvider(jcaProvider); 103 } 104 jwsSigner = factory.createJWSSigner(jwk, jwsAlg); 105 106 publicJWK = jwk.toPublicJWK(); 107 } 108 109 110 /** 111 * Returns the configured public signing JWK. 112 * 113 * @return The public signing JWK. 114 */ 115 public JWK getPublicJWK() { 116 return publicJWK; 117 } 118 119 120 /** 121 * Returns the configured JWS algorithm. 122 * 123 * @return The JWS algorithm. 124 */ 125 public JWSAlgorithm getJWSAlgorithm() { 126 return jwsAlg; 127 } 128 129 130 /** 131 * Returns the JWS signer. 132 * 133 * @return The JWS signer. 134 */ 135 public JWSSigner getJWSSigner() { 136 return jwsSigner; 137 } 138 139 140 @Override 141 public SignedJWT createDPoPJWT(final String htm, 142 final URI htu) 143 throws JOSEException { 144 145 return createDPoPJWT(htm, htu, null); 146 } 147 148 149 @Override 150 public SignedJWT createDPoPJWT(final String htm, 151 final URI htu, 152 final AccessToken accessToken) 153 throws JOSEException { 154 155 return createDPoPJWT(new JWTID(MINIMAL_JTI_BYTE_LENGTH), htm, htu, new Date(), accessToken); 156 } 157 158 159 @Override 160 public SignedJWT createDPoPJWT(final JWTID jti, 161 final String htm, 162 final URI htu, 163 final Date iat, 164 final AccessToken accessToken) 165 throws JOSEException { 166 167 JWSHeader jwsHeader = new JWSHeader.Builder(getJWSAlgorithm()) 168 .type(TYPE) 169 .jwk(getPublicJWK()) 170 .build(); 171 172 JWTClaimsSet jwtClaimsSet = DPoPUtils.createJWTClaimsSet(jti, htm, htu, iat, accessToken); 173 SignedJWT signedJWT = new SignedJWT(jwsHeader, jwtClaimsSet); 174 signedJWT.sign(getJWSSigner()); 175 return signedJWT; 176 } 177}