001 package com.nimbusds.jose; 002 003 004 import java.text.ParseException; 005 006 import java.util.Collections; 007 import java.util.HashSet; 008 import java.util.Set; 009 010 import net.minidev.json.JSONObject; 011 012 import com.nimbusds.jose.util.Base64URL; 013 import com.nimbusds.jose.util.JSONObjectUtils; 014 015 016 /** 017 * Plaintext JOSE header. 018 * 019 * <p>Supports all {@link #getReservedParameterNames reserved header parameters} 020 * of the plain specification: 021 * 022 * <ul> 023 * <li>alg (set to {@link Algorithm#NONE "none"}). 024 * <li>typ 025 * <li>cty 026 * </ul> 027 * 028 * <p>The header may also carry {@link #setCustomParameters custom parameters}; 029 * these will be serialised and parsed along the reserved ones. 030 * 031 * <p>Example: 032 * 033 * <pre> 034 * { 035 * "alg" : "none" 036 * } 037 * </pre> 038 * 039 * @author Vladimir Dzhuvinov 040 * @version $version$ (2013-01-08) 041 */ 042 public class PlainHeader extends Header implements ReadOnlyPlainHeader { 043 044 045 /** 046 * The reserved parameter names. 047 */ 048 private static final Set<String> RESERVED_PARAMETER_NAMES; 049 050 051 /** 052 * Initialises the reserved parameter name set. 053 */ 054 static { 055 Set<String> p = new HashSet<String>(); 056 057 p.add("alg"); 058 p.add("typ"); 059 p.add("cty"); 060 061 RESERVED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 062 } 063 064 065 /** 066 * Creates a new plain header with algorithm 067 * {@link Algorithm#NONE none}. 068 */ 069 public PlainHeader() { 070 071 super(Algorithm.NONE); 072 } 073 074 075 /** 076 * Gets the reserved parameter names for plain headers. 077 * 078 * @return The reserved parameter names, as an unmodifiable set. 079 */ 080 public static Set<String> getReservedParameterNames() { 081 082 return RESERVED_PARAMETER_NAMES; 083 } 084 085 086 @Override 087 public Algorithm getAlgorithm() { 088 089 return alg; 090 } 091 092 093 /** 094 * @throws IllegalArgumentException If the specified parameter name 095 * matches a reserved parameter name. 096 */ 097 @Override 098 public void setCustomParameter(final String name, final Object value) { 099 100 if (getReservedParameterNames().contains(name)) 101 throw new IllegalArgumentException("The parameter name \"" + name + "\" matches a reserved name"); 102 103 super.setCustomParameter(name, value); 104 } 105 106 107 @Override 108 public Set<String> getIncludedParameters() { 109 110 Set<String> includedParameters = 111 new HashSet<String>(getCustomParameters().keySet()); 112 113 includedParameters.add("alg"); 114 115 if (getType() != null) 116 includedParameters.add("typ"); 117 118 if (getContentType() != null) 119 includedParameters.add("cty"); 120 121 return includedParameters; 122 } 123 124 125 /** 126 * Parses a plain header from the specified JSON object. 127 * 128 * @param json The JSON object to parse. Must not be {@code null}. 129 * 130 * @return The plain header. 131 * 132 * @throws ParseException If the specified JSON object doesn't represent 133 * a valid plain header. 134 */ 135 public static PlainHeader parse(final JSONObject json) 136 throws ParseException { 137 138 // Get the "alg" parameter 139 Algorithm alg = Header.parseAlgorithm(json); 140 141 if (alg != Algorithm.NONE) 142 throw new ParseException("The algorithm \"alg\" header parameter must be \"none\"", 0); 143 144 145 // Create a minimal header, type may be set later 146 PlainHeader h = new PlainHeader(); 147 148 149 // Parse optional + custom parameters 150 for(final String name: json.keySet()) { 151 152 if (name.equals("alg")) 153 continue; // skip 154 155 else if (name.equals("typ")) 156 h.setType(new JOSEObjectType(JSONObjectUtils.getString(json, name))); 157 158 else if (name.equals("cty")) 159 h.setContentType(JSONObjectUtils.getString(json, name)); 160 161 else 162 h.setCustomParameter(name, json.get(name)); 163 } 164 165 return h; 166 } 167 168 169 /** 170 * Parses a plain header from the specified JSON string. 171 * 172 * @param s The JSON string to parse. Must not be {@code null}. 173 * 174 * @return The plain header. 175 * 176 * @throws ParseException If the specified JSON string doesn't 177 * represent a valid plain header. 178 */ 179 public static PlainHeader parse(final String s) 180 throws ParseException { 181 182 JSONObject jsonObject = JSONObjectUtils.parseJSONObject(s); 183 184 return parse(jsonObject); 185 } 186 187 188 /** 189 * Parses a plain header from the specified Base64URL. 190 * 191 * @param base64URL The Base64URL to parse. Must not be {@code null}. 192 * 193 * @return The plain header. 194 * 195 * @throws ParseException If the specified Base64URL doesn't represent a 196 * valid plain header. 197 */ 198 public static PlainHeader parse(final Base64URL base64URL) 199 throws ParseException { 200 201 if (base64URL == null) 202 throw new ParseException("The Base64URL must not be null", 0); 203 204 return parse(base64URL.decodeToString()); 205 } 206 }