001package com.nimbusds.oauth2.sdk.assertions.jwt; 002 003 004import java.security.Provider; 005import java.security.interfaces.ECPrivateKey; 006import java.security.interfaces.RSAPrivateKey; 007import java.util.Collections; 008import java.util.HashSet; 009import java.util.Set; 010 011import com.nimbusds.oauth2.sdk.auth.Secret; 012 013import com.nimbusds.jose.JOSEException; 014import com.nimbusds.jose.JWSAlgorithm; 015import com.nimbusds.jose.JWSHeader; 016import com.nimbusds.jose.crypto.ECDSASigner; 017import com.nimbusds.jose.crypto.MACSigner; 018import com.nimbusds.jose.crypto.RSASSASigner; 019import com.nimbusds.jwt.SignedJWT; 020 021 022/** 023 * Static JWT bearer assertion factory. 024 * 025 * <p>Related specifications: 026 * 027 * <ul> 028 * <li>Assertion Framework for OAuth 2.0 Client Authentication and 029 * Authorization Grants (RFC 7521). 030 * <li>JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and 031 * Authorization Grants (RFC 7523). 032 * </ul> 033 */ 034public class JWTAssertionFactory { 035 036 037 /** 038 * Returns the supported signature JSON Web Algorithms (JWAs). 039 * 040 * @return The supported JSON Web Algorithms (JWAs). 041 */ 042 public static Set<JWSAlgorithm> supportedJWAs() { 043 044 Set<JWSAlgorithm> supported = new HashSet<>(); 045 supported.addAll(JWSAlgorithm.Family.HMAC_SHA); 046 supported.addAll(JWSAlgorithm.Family.RSA); 047 supported.addAll(JWSAlgorithm.Family.EC); 048 return Collections.unmodifiableSet(supported); 049 } 050 051 052 /** 053 * Creates a new HMAC-protected JWT bearer assertion. 054 * 055 * @param details The JWT bearer assertion details. Must not be 056 * {@code null}. 057 * @param jwsAlgorithm The expected HMAC algorithm (HS256, HS384 or 058 * HS512) for the JWT assertion. Must be supported 059 * and not {@code null}. 060 * @param secret The secret. Must be at least 256-bits long. 061 * 062 * @return The JWT bearer assertion. 063 * 064 * @throws JOSEException If the client secret is too short, or HMAC 065 * computation failed. 066 */ 067 public static SignedJWT create(final JWTAssertionDetails details, 068 final JWSAlgorithm jwsAlgorithm, 069 final Secret secret) 070 throws JOSEException { 071 072 SignedJWT signedJWT = new SignedJWT(new JWSHeader(jwsAlgorithm), details.toJWTClaimsSet()); 073 signedJWT.sign(new MACSigner(secret.getValueBytes())); 074 return signedJWT; 075 } 076 077 078 /** 079 * Creates a new RSA-signed JWT bearer assertion. 080 * 081 * @param details The JWT bearer assertion details. Must not be 082 * be {@code null}. 083 * @param jwsAlgorithm The expected RSA signature algorithm (RS256, 084 * RS384, RS512, PS256, PS384 or PS512) for the 085 * JWT assertion. Must be supported and not 086 * {@code null}. 087 * @param rsaPrivateKey The RSA private key. Must not be {@code null}. 088 * @param keyID Optional identifier for the RSA key, to aid key 089 * selection on the recipient side. Recommended. 090 * {@code null} if not specified. 091 * @param jcaProvider Optional specific JCA provider, {@code null} to 092 * use the default one. 093 * 094 * @return The JWT bearer assertion. 095 * 096 * @throws JOSEException If RSA signing failed. 097 */ 098 public static SignedJWT create(final JWTAssertionDetails details, 099 final JWSAlgorithm jwsAlgorithm, 100 final RSAPrivateKey rsaPrivateKey, 101 final String keyID, 102 final Provider jcaProvider) 103 throws JOSEException { 104 105 SignedJWT signedJWT = new SignedJWT( 106 new JWSHeader.Builder(jwsAlgorithm).keyID(keyID).build(), 107 details.toJWTClaimsSet()); 108 RSASSASigner signer = new RSASSASigner(rsaPrivateKey); 109 if (jcaProvider != null) { 110 signer.getJCAContext().setProvider(jcaProvider); 111 } 112 signedJWT.sign(signer); 113 return signedJWT; 114 } 115 116 117 /** 118 * Creates a new EC-signed JWT bearer assertion. 119 * 120 * @param details The JWT bearer assertion details. Must not be 121 * {@code null}. 122 * @param jwsAlgorithm The expected EC signature algorithm (ES256, 123 * ES384 or ES512) for the JWT assertion. Must be 124 * supported and not {@code null}. 125 * @param ecPrivateKey The EC private key. Must not be {@code null}. 126 * @param keyID Optional identifier for the EC key, to aid key 127 * selection on the recipient side. Recommended. 128 * {@code null} if not specified. 129 * @param jcaProvider Optional specific JCA provider, {@code null} to 130 * use the default one. 131 * 132 * @return The JWT bearer assertion. 133 * 134 * @throws JOSEException If RSA signing failed. 135 */ 136 public static SignedJWT create(final JWTAssertionDetails details, 137 final JWSAlgorithm jwsAlgorithm, 138 final ECPrivateKey ecPrivateKey, 139 final String keyID, 140 final Provider jcaProvider) 141 throws JOSEException { 142 143 SignedJWT signedJWT = new SignedJWT( 144 new JWSHeader.Builder(jwsAlgorithm).keyID(keyID).build(), 145 details.toJWTClaimsSet()); 146 ECDSASigner signer = new ECDSASigner(ecPrivateKey); 147 if (jcaProvider != null) { 148 signer.getJCAContext().setProvider(jcaProvider); 149 } 150 signedJWT.sign(signer); 151 return signedJWT; 152 } 153 154 155 /** 156 * Prevents public instantiation. 157 */ 158 private JWTAssertionFactory() {} 159}