001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2021, 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.ciba; 019 020 021import net.jcip.annotations.Immutable; 022import net.minidev.json.JSONObject; 023 024import com.nimbusds.common.contenttype.ContentType; 025import com.nimbusds.oauth2.sdk.ParseException; 026import com.nimbusds.oauth2.sdk.SuccessResponse; 027import com.nimbusds.oauth2.sdk.http.HTTPResponse; 028import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 029 030 031/** 032 * Successful CIBA request acknowledgement from an OpenID provider / OAuth 2.0 033 * authorisation server backend authentication endpoint. 034 * 035 * <p>Example HTTP response: 036 * 037 * <pre> 038 * HTTP/1.1 200 OK 039 * Content-Type: application/json 040 * Cache-Control: no-store 041 * 042 * { 043 * "auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac1", 044 * "expires_in": 120, 045 * "interval": 2 046 * } 047 * </pre> 048 * 049 * <p>Related specifications: 050 * 051 * <ul> 052 * <li>OpenID Connect CIBA Flow - Core 1.0, section 7.3. 053 * </ul> 054 */ 055@Immutable 056public class CIBARequestAcknowledgement extends CIBAResponse implements SuccessResponse { 057 058 059 /** 060 * The default minimal wait interval in seconds for polling the token 061 * endpoint for the poll and ping delivery modes. 062 */ 063 public static final int DEFAULT_MIN_WAIT_INTERVAL = 5; 064 065 066 /** 067 * The CIBA request ID. 068 */ 069 private final AuthRequestID authRequestID; 070 071 072 /** 073 * The expiration time of the CIBA request ID, in seconds. 074 */ 075 private final int expiresIn; 076 077 078 /** 079 * The minimal wait interval in seconds for polling the token endpoint 080 * for the poll or ping delivery modes. 081 */ 082 private final Integer minWaitInterval; 083 084 085 /** 086 * Creates a new successful CIBA request acknowledgement. 087 * 088 * @param authRequestID The CIBA request ID. 089 * @param expiresIn The expiration time of the CIBA request ID, 090 * in seconds. Must be positive. 091 * @param minWaitInterval The minimal wait interval in seconds for 092 * polling the token endpoint for the poll or 093 * ping delivery modes, {@code null} if not 094 * specified. 095 */ 096 public CIBARequestAcknowledgement(final AuthRequestID authRequestID, 097 final int expiresIn, 098 final Integer minWaitInterval) { 099 100 super(); 101 102 if (authRequestID == null) { 103 throw new IllegalArgumentException("The auth_req_id must not be null"); 104 } 105 this.authRequestID = authRequestID; 106 107 if (expiresIn < 1) { 108 throw new IllegalArgumentException("The expiration must be a positive integer"); 109 } 110 this.expiresIn = expiresIn; 111 112 if (minWaitInterval != null && minWaitInterval < 1) { 113 throw new IllegalArgumentException("The interval must be a positive integer"); 114 } 115 this.minWaitInterval = minWaitInterval; 116 } 117 118 119 @Override 120 public boolean indicatesSuccess() { 121 return true; 122 } 123 124 125 /** 126 * Returns the CIBA request ID. 127 * 128 * @return The CIBA request ID. 129 */ 130 public AuthRequestID getAuthRequestID() { 131 return authRequestID; 132 } 133 134 135 /** 136 * Returns the expiration time of the CIBA request ID in seconds. 137 * 138 * @return The expiration time in seconds. 139 */ 140 public int getExpiresIn() { 141 return expiresIn; 142 } 143 144 145 /** 146 * Returns the minimum wait interval in seconds for polling the token 147 * endpoint for the poll and ping delivery modes. 148 * 149 * @return The interval in seconds, {@code null} if not specified. 150 */ 151 public Integer getMinWaitInterval() { 152 return minWaitInterval; 153 } 154 155 156 /** 157 * Returns a JSON object representation of this CIBA request 158 * acknowledgement. 159 * 160 * @return The JSON object. 161 */ 162 public JSONObject toJSONObject() { 163 164 JSONObject o = new JSONObject(); 165 o.put("auth_req_id", authRequestID); 166 o.put("expires_in", expiresIn); 167 if (minWaitInterval != null) { 168 o.put("interval", minWaitInterval); 169 } 170 return o; 171 } 172 173 174 @Override 175 public HTTPResponse toHTTPResponse() { 176 177 HTTPResponse httpResponse = new HTTPResponse(HTTPResponse.SC_OK); 178 httpResponse.setEntityContentType(ContentType.APPLICATION_JSON); 179 httpResponse.setCacheControl("no-store"); 180 httpResponse.setPragma("no-cache"); 181 httpResponse.setContent(toJSONObject().toString()); 182 return httpResponse; 183 } 184 185 186 /** 187 * Parses a successful CIBA request acknowledgement from the specified 188 * JSON object. 189 * 190 * @param jsonObject The JSON object to parse. Must not be {@code null}. 191 * 192 * @return The CIBA request acknowledgement. 193 * 194 * @throws ParseException If parsing failed. 195 */ 196 public static CIBARequestAcknowledgement parse(final JSONObject jsonObject) 197 throws ParseException { 198 199 AuthRequestID authRequestID = AuthRequestID.parse(JSONObjectUtils.getString(jsonObject, "auth_req_id")); 200 201 int expiresIn = JSONObjectUtils.getInt(jsonObject, "expires_in"); 202 203 if (expiresIn < 1) { 204 throw new ParseException("The expires_in parameter must be a positive integer"); 205 } 206 207 Integer minWaitInterval = null; 208 if (jsonObject.get("interval") != null) { 209 minWaitInterval = JSONObjectUtils.getInt(jsonObject, "interval"); 210 } 211 212 if (minWaitInterval != null && minWaitInterval < 1) { 213 throw new ParseException("The interval parameter must be a positive integer"); 214 } 215 216 return new CIBARequestAcknowledgement(authRequestID, expiresIn, minWaitInterval); 217 } 218 219 220 /** 221 * Parses a successful CIBA request acknowledgement from the specified 222 * HTTP response. 223 * 224 * @param httpResponse The HTTP response to parse. Must not be 225 * {@code null}. 226 * 227 * @return The CIBA request acknowledgement. 228 * 229 * @throws ParseException If parsing failed. 230 */ 231 public static CIBARequestAcknowledgement parse(final HTTPResponse httpResponse) 232 throws ParseException { 233 234 httpResponse.ensureStatusCode(HTTPResponse.SC_OK); 235 JSONObject jsonObject = httpResponse.getContentAsJSONObject(); 236 return parse(jsonObject); 237 } 238}