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