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