001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2016, 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.auth; 019 020 021import java.security.cert.X509Certificate; 022import java.text.ParseException; 023import java.util.AbstractMap; 024import java.util.Map; 025 026import com.nimbusds.jose.util.Base64URL; 027import com.nimbusds.jose.util.JSONObjectUtils; 028import com.nimbusds.jose.util.X509CertUtils; 029import com.nimbusds.jwt.JWTClaimsSet; 030import net.jcip.annotations.Immutable; 031import net.minidev.json.JSONObject; 032 033 034/** 035 * X.509 certificate SHA-256 confirmation. 036 */ 037@Immutable 038public final class X509CertificateConfirmation { 039 040 041 /** 042 * The X.509 certificate SHA-256 thumbprint. 043 */ 044 private final Base64URL x5tS256; 045 046 047 /** 048 * Creates a new X.509 certificate SHA-256 confirmation. 049 * 050 * @param x5tS256 The X.509 certificate SHA-256 thumbprint. 051 */ 052 public X509CertificateConfirmation(final Base64URL x5tS256) { 053 054 if (x5tS256 == null) { 055 throw new IllegalArgumentException("The X.509 certificate thumbprint must not be null"); 056 } 057 058 this.x5tS256 = x5tS256; 059 } 060 061 062 /** 063 * Returns the X.509 certificate SHA-256 thumbprint. 064 * 065 * @return The X.509 certificate SHA-256 thumbprint. 066 */ 067 public Base64URL getValue() { 068 069 return x5tS256; 070 } 071 072 073 /** 074 * Returns this X.509 certificate SHA-256 confirmation as a JSON 075 * object. 076 * 077 * <p>Example: 078 * 079 * <pre> 080 * { 081 * "cnf" : { "x5t#S256" : "bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2" } 082 * } 083 * </pre> 084 * 085 * @return The JSON object. 086 */ 087 public JSONObject toJSONObject() { 088 089 JSONObject jsonObject = new JSONObject(); 090 Map.Entry<String, JSONObject> cnfClaim = toJWTClaim(); 091 jsonObject.put(cnfClaim.getKey(), cnfClaim.getValue()); 092 return jsonObject; 093 } 094 095 096 /** 097 * Returns this X.509 certificate SHA-256 confirmation as a JWT claim. 098 * 099 * <p>Example: 100 * 101 * <pre> 102 * "cnf" : { "x5t#S256" : "bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2" } 103 * </pre> 104 * 105 * @return The JWT claim name / value. 106 */ 107 public Map.Entry<String,JSONObject> toJWTClaim() { 108 109 JSONObject cnf = new JSONObject(); 110 cnf.put("x5t#S256", x5tS256.toString()); 111 112 return new AbstractMap.SimpleImmutableEntry<>( 113 "cnf", 114 cnf 115 ); 116 } 117 118 119 /** 120 * Applies this X.509 certificate SHA-256 confirmation to the specified 121 * JWT claims set. 122 * 123 * @param jwtClaimsSet The JWT claims set. 124 * 125 * @return The modified JWT claims set. 126 */ 127 public JWTClaimsSet applyTo(final JWTClaimsSet jwtClaimsSet) { 128 129 Map.Entry<String, JSONObject> cnfClaim = toJWTClaim(); 130 131 return new JWTClaimsSet.Builder(jwtClaimsSet) 132 .claim(cnfClaim.getKey(), cnfClaim.getValue()) 133 .build(); 134 } 135 136 137 @Override 138 public String toString() { 139 return toJSONObject().toJSONString(); 140 } 141 142 143 @Override 144 public boolean equals(final Object o) { 145 if (this == o) return true; 146 if (!(o instanceof X509CertificateConfirmation)) return false; 147 X509CertificateConfirmation that = (X509CertificateConfirmation) o; 148 return x5tS256 != null ? x5tS256.equals(that.x5tS256) : that.x5tS256 == null; 149 } 150 151 152 @Override 153 public int hashCode() { 154 return x5tS256 != null ? x5tS256.hashCode() : 0; 155 } 156 157 158 /** 159 * Parses a X.509 certificate confirmation from the specified JWT 160 * claims set. 161 * 162 * @param jwtClaimsSet The JWT claims set. 163 * 164 * @return The X.509 certificate confirmation, {@code null} if not 165 * found. 166 */ 167 public static X509CertificateConfirmation parse(final JWTClaimsSet jwtClaimsSet) { 168 169 JSONObject cnf; 170 try { 171 cnf = jwtClaimsSet.getJSONObjectClaim("cnf"); 172 } catch (ParseException e) { 173 return null; 174 } 175 176 return parseFromConfirmationJSONObject(cnf); 177 } 178 179 180 /** 181 * Parses a X.509 certificate confirmation from the specified JSON 182 * object representation of a JWT claims set. 183 * 184 * @param jsonObject The JSON object. 185 * 186 * @return The X.509 certificate confirmation, {@code null} if not 187 * found. 188 */ 189 public static X509CertificateConfirmation parse(final JSONObject jsonObject) { 190 191 if (! jsonObject.containsKey("cnf")) { 192 return null; 193 } 194 195 try { 196 return parseFromConfirmationJSONObject(JSONObjectUtils.getJSONObject(jsonObject, "cnf")); 197 } catch (ParseException e) { 198 return null; 199 } 200 } 201 202 203 /** 204 * Parses a X.509 certificate confirmation from the specified 205 * confirmation ("cnf") JSON object. 206 * 207 * @param cnf The confirmation JSON object, {@code null} if none. 208 * 209 * @return The X.509 certificate confirmation, {@code null} if not 210 * found. 211 */ 212 public static X509CertificateConfirmation parseFromConfirmationJSONObject(final JSONObject cnf) { 213 214 if (cnf == null) { 215 return null; 216 } 217 218 try { 219 String x5tString = JSONObjectUtils.getString(cnf, "x5t#S256"); 220 221 if (x5tString == null) { 222 return null; 223 } 224 225 return new X509CertificateConfirmation(new Base64URL(x5tString)); 226 227 } catch (ParseException e) { 228 return null; 229 } 230 } 231 232 233 /** 234 * Creates a confirmation of the specified X.509 certificate. 235 * 236 * @param x509Cert The X.509 certificate. 237 * 238 * @return The X.509 certificate confirmation. 239 */ 240 public static X509CertificateConfirmation of(final X509Certificate x509Cert) { 241 242 return new X509CertificateConfirmation(X509CertUtils.computeSHA256Thumbprint(x509Cert)); 243 } 244}