001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, Connect2id Ltd.
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.jose;
019
020
021import java.io.Serializable;
022import java.text.ParseException;
023import java.util.Map;
024import java.util.Objects;
025
026import com.nimbusds.jose.util.JSONObjectUtils;
027
028
029/**
030 * The base abstract class for JSON Web Signature (JWS) secured and JSON Web
031 * Encryption (JWE) secured objects serialisable to JSON.
032 *
033 * @author Vladimir Dzhuvinov
034 * @version 2021-10-05
035 */
036public abstract class JOSEObjectJSON implements Serializable {
037        
038        
039        private static final long serialVersionUID = 1L;
040
041
042        /**
043         * The MIME type of JOSE objects serialised to JSON:
044         * {@code application/jose+json; charset=UTF-8}
045         */
046        public static final String MIME_TYPE_JOSE_JSON = "application/jose+json; charset=UTF-8";
047
048
049        /**
050         * The payload (message), {@code null} if not specified.
051         */
052        private Payload payload;
053
054
055        /**
056         * Creates a new JOSE object with the specified payload.
057         *
058         * @param payload The payload, {@code null} if not available (e.g. for
059         *                an encrypted JWE object).
060         */
061        protected JOSEObjectJSON(final Payload payload) {
062
063                this.payload = payload;
064        }
065
066
067        /**
068         * Sets the payload of this JOSE object.
069         *
070         * @param payload The payload, {@code null} if not available (e.g. for 
071         *                an encrypted JWE object).
072         */
073        protected void setPayload(final Payload payload) {
074
075                this.payload = payload;
076        }
077
078
079        /**
080         * Returns the payload of this JOSE object.
081         *
082         * @return The payload, {@code null} if not available (for an encrypted
083         *         JWE object that hasn't been decrypted).
084         */
085        public Payload getPayload() {
086
087                return payload;
088        }
089        
090        
091        /**
092         * Returns a general JSON object representation of this JOSE secured
093         * object.
094         *
095         * <p>See
096         * <a href="https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.1">JWS
097         * general serialisation</a> or
098         * <a href="https://datatracker.ietf.org/doc/html/rfc7516#section-7.2.1">JWE
099         * general serialisation</a>.
100         *
101         * @return The JSON object.
102         *
103         * @throws IllegalStateException If the JOSE object is not in a state
104         *                               that permits serialisation.
105         */
106        abstract Map<String, Object> toGeneralJSONObject();
107        
108        
109        /**
110         * Returns a flattened JSON object representation of this JOSE secured
111         * object. There must be exactly one JWS signature or JWE recipient for
112         * a flattened JSON serialisation.
113         *
114         * <p>See
115         * <a href="https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.2">JWS
116         * flattened serialisation</a> or
117         * <a href="https://datatracker.ietf.org/doc/html/rfc7516#section-7.2.2">JWE
118         * flattened serialisation</a>.
119         *
120         * @return The JSON object.
121         *
122         * @throws IllegalStateException If the JOSE object is not in a state
123         *                               that permits serialisation or there
124         *                               is more than one JWS signature or JWE
125         *                               recipient.
126         */
127        abstract Map<String, Object> toFlattenedJSONObject();
128        
129        
130        /**
131         * Serialises this JOSE object to a general JOSE object string.
132         *
133         * <p>See
134         * <a href="https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.1">JWS
135         * general serialisation</a> or
136         * <a href="https://datatracker.ietf.org/doc/html/rfc7516#section-7.2.1">JWE
137         * general serialisation</a>.
138         *
139         * @return The JSON object string.
140         *
141         * @throws IllegalStateException If the JOSE object is not in a state
142         *                               that permits serialisation.
143         */
144        public abstract String serializeGeneral();
145        
146        
147        /**
148         * Serialises this JOSE object to a flattened JSON object string. There
149         * must be exactly one JWS signature or JWE recipient for a flattened
150         * JSON serialisation.
151         *
152         * <p>See
153         * <a href="https://datatracker.ietf.org/doc/html/rfc7515#section-7.2.2">JWS
154         * flattened serialisation</a> or
155         * <a href="https://datatracker.ietf.org/doc/html/rfc7516#section-7.2.2">JWE
156         * flattened serialisation</a>.
157         *
158         * @return The JSON object string.
159         *
160         * @throws IllegalStateException If the JOSE object is not in a state
161         *                               that permits serialisation or there
162         *                               is more than one JWS signature or JWE
163         *                               recipient.
164         */
165        public abstract String serializeFlattened();
166        
167        
168        /**
169         * Parses a JOSE secured object from the specified JSON object
170         * representation.
171         *
172         * @param jsonObject The JSON object to parse. Must not be
173         *                   {@code null}.
174         *
175         * @return The corresponding {@link JWSObjectJSON} or
176         *         {@link JWEObjectJSON}.
177         *
178         * @throws ParseException If the JSON object couldn't be parsed to a
179         *                        valid JWS or JWE secured object.
180         */
181        public static JOSEObjectJSON parse(final Map<String, Object> jsonObject)
182                throws ParseException {
183                
184                if (jsonObject.containsKey("signature") || jsonObject.containsKey("signatures")) {
185                        return JWSObjectJSON.parse(jsonObject);
186                } else if (jsonObject.containsKey("ciphertext")) {
187                        throw new ParseException("JWE JSON not supported", 0); // TODO
188                } else {
189                        throw new ParseException("Invalid JOSE object", 0);
190                }
191        }
192
193
194        /**
195         * Parses a JOSE secured object from the specified JSON string.
196         *
197         * @param json The JSON string to parse. Must not be {@code null}.
198         *
199         * @return The corresponding {@link JWSObjectJSON} or
200         *         {@link JWEObjectJSON}.
201         *
202         * @throws ParseException If the string couldn't be parsed to a valid 
203         *                        JWS or JWE secured object.
204         */
205        public static JOSEObjectJSON parse(final String json)
206                throws ParseException {
207                
208                Objects.requireNonNull(json);
209
210                return parse(JSONObjectUtils.parse(json));
211        }
212}