001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2013-2015 ForgeRock AS. 015 */ 016 017package org.forgerock.json.jose.jwt; 018 019import static org.forgerock.json.jose.jwt.JwtHeaderKey.ALG; 020import static org.forgerock.json.jose.jwt.JwtHeaderKey.TYP; 021import static org.forgerock.json.jose.jwt.JwtHeaderKey.getHeaderKey; 022 023import java.util.Map; 024 025/** 026 * A base implementation class for JWT Headers. 027 * <p> 028 * Provides methods to set header parameters for all types of JWT Headers. 029 * 030 * @see org.forgerock.json.jose.jws.JwsHeader 031 * @see org.forgerock.json.jose.jwe.JweHeader 032 * 033 * @since 2.0.0 034 */ 035public abstract class JwtHeader extends JWObject { 036 037 /** 038 * Constructs a new JwtHeader, with the "typ" parameter set to "JWT". 039 */ 040 public JwtHeader() { 041 put(TYP.value(), JwtType.JWT.toString()); 042 } 043 044 /** 045 * Constructs a new JwtHeader, with its parameters set to the contents of the given Map. 046 * 047 * @param headers A Map containing the parameters to be set in the header. 048 */ 049 public JwtHeader(Map<String, Object> headers) { 050 this(); 051 setParameters(headers); 052 } 053 054 /** 055 * Sets the type of JWT this header represents. 056 * <p> 057 * For non-nested JWTs then the "JWT" type is RECOMMENDED to be used but it is OPTIONAL to set the "typ" property. 058 * For nested signed or encrypted JWTs the JWT type MUST be "JWS" and "JWE" respectively and the "typ" property 059 * MUST be set. 060 * 061 * @see JwtType 062 * 063 * @param jwtType The JwtType. 064 */ 065 public void setType(JwtType jwtType) { 066 put(TYP.value(), jwtType.toString()); 067 } 068 069 /** 070 * Gets the type of JWT this header represents. 071 * 072 * @return The JwtType. 073 */ 074 public JwtType getType() { 075 return JwtType.valueOf(get(TYP.value()).asString().toUpperCase()); 076 } 077 078 /** 079 * Sets the algorithm used to perform cryptographic signing and/or encryption on the JWT. 080 * 081 * @param algorithm The Algorithm. 082 */ 083 public void setAlgorithm(Algorithm algorithm) { 084 put(ALG.value(), algorithm.toString()); 085 } 086 087 /** 088 * Gets the Algorithm set in the JWT header. 089 * 090 * @return The Algorithm. 091 */ 092 public abstract Algorithm getAlgorithm(); 093 094 /** 095 * Gets the string representation of the Algorithm set in the JWT header. 096 * 097 * @return The algorithm as a String. 098 */ 099 protected String getAlgorithmString() { 100 return get(ALG.value()).asString(); 101 } 102 103 /** 104 * Sets a header parameter with the specified key and value. 105 * <p> 106 * If the key matches one of the reserved header parameter names, then the relevant <tt>set</tt> method is 107 * called to set that header parameter with the specified value. 108 * 109 * @param key The key of the header parameter. 110 * @param value The value of the header parameter. 111 */ 112 public void setParameter(String key, Object value) { 113 JwtHeaderKey headerKey = getHeaderKey(key.toUpperCase()); 114 115 switch (headerKey) { 116 case TYP: { 117 if (isValueOfType(value, JwtType.class)) { 118 setType((JwtType) value); 119 } else { 120 checkValueIsOfType(value, String.class); 121 setType(JwtType.jwtType((String) value)); 122 } 123 break; 124 } 125 case ALG: { 126 if (isValueOfType(value, Algorithm.class)) { 127 setAlgorithm((Algorithm) value); 128 } else { 129 checkValueIsOfType(value, String.class); 130 put(ALG.value(), value); 131 } 132 break; 133 } 134 default: { 135 put(key, value); 136 } 137 } 138 } 139 140 /** 141 * Sets header parameters using the values contained in the specified map. 142 * 143 * @param headers The Map to use to set header parameters. 144 * @see #setParameter(String, Object) 145 */ 146 public void setParameters(Map<String, Object> headers) { 147 for (String key : headers.keySet()) { 148 setParameter(key, headers.get(key)); 149 } 150 } 151 152 /** 153 * Gets a header parameter for the specified key. 154 * <p> 155 * If the key matches one of the reserved header parameter names, then the relevant <tt>get</tt> method is 156 * called to get that header parameter. 157 * 158 * @param key The header parameter key. 159 * @return The value stored against the header parameter key. 160 */ 161 public Object getParameter(String key) { 162 JwtHeaderKey headerKey = getHeaderKey(key.toUpperCase()); 163 164 Object value; 165 166 switch (headerKey) { 167 case TYP: { 168 value = getType(); 169 break; 170 } 171 case ALG: { 172 value = getAlgorithm(); 173 break; 174 } 175 default: { 176 value = get(key).getObject(); 177 } 178 } 179 180 return value; 181 } 182 183 /** 184 * Gets a header parameter for the specified key and then casts it to the specified type. 185 * 186 * @param key The header parameter key. 187 * @param clazz The class of the required type. 188 * @param <T> The required type for the header parameter value. 189 * @return The value stored against the header parameter key. 190 * @see #getParameter(String) 191 */ 192 public <T> T getParameter(String key, Class<T> clazz) { 193 return clazz.cast(getParameter(key)); 194 } 195 196 /** 197 * Returns this JwtHeader's parameters. 198 * 199 * @return {@code Map} of this JwtHeader's parameters. 200 */ 201 public Map<String, Object> getParameters() { 202 return getAll(); 203 } 204 205 /** 206 * Builds the JWT's header into a <code>String</code> representation of a JSON object. 207 * 208 * @return A JSON string. 209 */ 210 public String build() { 211 return toString(); 212 } 213}