001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.bean.openapi3; 018 019import static org.apache.juneau.commons.utils.CollectionUtils.*; 020import static org.apache.juneau.bean.openapi3.OpenApiCopyUtils.*; 021import static org.apache.juneau.commons.utils.CollectionUtils.contains; 022import static org.apache.juneau.commons.utils.Shorts.*; 023import static org.apache.juneau.commons.utils.StringUtils.*; 024import static org.apache.juneau.marshall.internal.ConverterUtils.*; 025 026import java.util.*; 027 028import org.apache.juneau.commons.collections.*; 029 030/** 031 * Defines a security scheme that can be used by the operations. 032 * 033 * <p> 034 * The Security Scheme Object defines a security scheme that can be used by the operations. Supported schemes are 035 * HTTP authentication, an API key (either as a header or as a query parameter), OAuth2's common flows (implicit, 036 * password, client credentials and authorization code) as defined in RFC6749, and OpenID Connect Discovery. 037 * 038 * <h5 class='section'>OpenAPI Specification:</h5> 039 * <p> 040 * The Security Scheme Object is composed of the following fields: 041 * <ul class='spaced-list'> 042 * <li><c>type</c> (string, REQUIRED) - The type of the security scheme. Values: <js>"apiKey"</js>, <js>"http"</js>, <js>"oauth2"</js>, <js>"openIdConnect"</js> 043 * <li><c>description</c> (string) - A short description for security scheme (CommonMark syntax may be used) 044 * <li><c>name</c> (string) - The name of the header, query or cookie parameter to be used (for <js>"apiKey"</js> type) 045 * <li><c>in</c> (string) - The location of the API key (for <js>"apiKey"</js> type). Values: <js>"query"</js>, <js>"header"</js>, <js>"cookie"</js> 046 * <li><c>scheme</c> (string) - The name of the HTTP Authorization scheme to be used in the Authorization header (for <js>"http"</js> type) 047 * <li><c>bearerFormat</c> (string) - A hint to the client to identify how the bearer token is formatted (for <js>"http"</js> type with <js>"bearer"</js> scheme) 048 * <li><c>flows</c> ({@link OAuthFlows}) - An object containing configuration information for the flow types supported (for <js>"oauth2"</js> type) 049 * <li><c>openIdConnectUrl</c> (string) - OpenId Connect URL to discover OAuth2 configuration values (for <js>"openIdConnect"</js> type) 050 * </ul> 051 * 052 * <h5 class='section'>Example:</h5> 053 * <p class='bjava'> 054 * <jc>// Create an API key security scheme</jc> 055 * SecuritySchemeInfo <jv>scheme</jv> = <jk>new</jk> SecuritySchemeInfo() 056 * .setType(<js>"apiKey"</js>) 057 * .setDescription(<js>"API key authentication"</js>) 058 * .setName(<js>"X-API-Key"</js>) 059 * .setIn(<js>"header"</js>); 060 * </p> 061 * <p class='bjava'> 062 * <jc>// Create an OAuth2 security scheme</jc> 063 * SecuritySchemeInfo <jv>oauthScheme</jv> = <jk>new</jk> SecuritySchemeInfo() 064 * .setType(<js>"oauth2"</js>) 065 * .setDescription(<js>"OAuth2 authentication"</js>) 066 * .setFlows( 067 * <jk>new</jk> OAuthFlows() 068 * .setAuthorizationCode( 069 * <jk>new</jk> OAuthFlow() 070 * .setAuthorizationUrl(<js>"https://example.com/oauth/authorize"</js>) 071 * .setTokenUrl(<js>"https://example.com/oauth/token"</js>) 072 * .setScopes( 073 * JsonMap.<jsm>of</jsm>( 074 * <js>"read"</js>, <js>"Read access to resources"</js>, 075 * <js>"write"</js>, <js>"Write access to resources"</js> 076 * ) 077 * ) 078 * ) 079 * ); 080 * </p> 081 * 082 * <h5 class='section'>See Also:</h5><ul> 083 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#security-scheme-object">OpenAPI Specification > Security Scheme Object</a> 084 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/authentication/">OpenAPI Authentication</a> 085 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 086 * </ul> 087 */ 088@SuppressWarnings({ 089 "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants 090}) 091public class SecuritySchemeInfo extends OpenApiElement { 092 093 private static final String[] VALID_IN = { "query", "header", "cookie" }; 094 private static final String[] VALID_TYPES = { "apiKey", "http", "oauth2", "openIdConnect" }; 095 096 private String type; 097 private String description; 098 private String name; 099 private String in; 100 private String scheme; 101 private String bearerFormat; 102 private String openIdConnectUrl; 103 104 private OAuthFlow flows; 105 106 /** 107 * Default constructor. 108 */ 109 public SecuritySchemeInfo() {} 110 111 /** 112 * Copy constructor. 113 * 114 * @param copyFrom The object to copy. 115 */ 116 public SecuritySchemeInfo(SecuritySchemeInfo copyFrom) { 117 super(copyFrom); 118 119 this.name = copyFrom.name; 120 this.in = copyFrom.in; 121 this.description = copyFrom.description; 122 this.type = copyFrom.type; 123 this.scheme = copyFrom.scheme; 124 this.bearerFormat = copyFrom.bearerFormat; 125 this.openIdConnectUrl = copyFrom.openIdConnectUrl; 126 this.flows = copyOf(copyFrom.flows); 127 } 128 129 /** 130 * Make a deep copy of this object. 131 * 132 * @return A deep copy of this object. 133 */ 134 public SecuritySchemeInfo copy() { 135 return new SecuritySchemeInfo(this); 136 } 137 138 @Override /* Overridden from SwaggerElement */ 139 public <T> T get(String property, Class<T> type) { 140 reqnn("property", property); 141 return switch (property) { 142 case "name" -> toType(getName(), type); 143 case "in" -> toType(getIn(), type); 144 case "description" -> toType(getDescription(), type); 145 case "scheme" -> toType(getScheme(), type); 146 case "flows" -> toType(getFlows(), type); 147 case "bearerFormat" -> toType(getBearerFormat(), type); 148 case "openIdConnectUrl" -> toType(getOpenIdConnectUrl(), type); 149 case "type" -> toType(getType(), type); 150 default -> super.get(property, type); 151 }; 152 } 153 154 /** 155 * Bean property getter: <property>bearerFormat</property>. 156 * 157 * <p> 158 * A hint to the client to identify how the bearer token is formatted. 159 * 160 * @return The property value, or <jk>null</jk> if it is not set. 161 */ 162 public String getBearerFormat() { return bearerFormat; } 163 164 /** 165 * Bean property getter: <property>description</property>. 166 * 167 * <p> 168 * A short description for the security scheme. 169 * 170 * @return The property value, or <jk>null</jk> if it is not set. 171 */ 172 public String getDescription() { return description; } 173 174 /** 175 * Bean property getter: <property>flows</property>. 176 * 177 * <p> 178 * An object containing configuration information for the flow types supported. 179 * 180 * @return The property value, or <jk>null</jk> if it is not set. 181 */ 182 public OAuthFlow getFlows() { return flows; } 183 184 /** 185 * Bean property getter: <property>in</property>. 186 * 187 * <p> 188 * The location of the API key. 189 * 190 * @return The property value, or <jk>null</jk> if it is not set. 191 */ 192 public String getIn() { return in; } 193 194 /** 195 * Bean property getter: <property>name</property>. 196 * 197 * <p> 198 * The name of the header, query or cookie parameter to be used. 199 * 200 * @return The property value, or <jk>null</jk> if it is not set. 201 */ 202 public String getName() { return name; } 203 204 /** 205 * Bean property getter: <property>openIdConnectUrl</property>. 206 * 207 * <p> 208 * OpenId Connect URL to discover OAuth2 configuration values. 209 * 210 * @return The property value, or <jk>null</jk> if it is not set. 211 */ 212 public String getOpenIdConnectUrl() { return openIdConnectUrl; } 213 214 /** 215 * Bean property getter: <property>scheme</property>. 216 * 217 * <p> 218 * The name of the HTTP Authorization scheme to be used in the Authorization header. 219 * 220 * @return The property value, or <jk>null</jk> if it is not set. 221 */ 222 public String getScheme() { return scheme; } 223 224 /** 225 * Bean property getter: <property>type</property>. 226 * 227 * <p> 228 * The type of the security scheme. 229 * 230 * @return The property value, or <jk>null</jk> if it is not set. 231 */ 232 public String getType() { return type; } 233 234 @Override /* Overridden from SwaggerElement */ 235 public Set<String> keySet() { 236 // @formatter:off 237 var s = stb(String.class) 238 .addIf(nn(bearerFormat), "bearerFormat") 239 .addIf(nn(description), "description") 240 .addIf(nn(flows), "flows") 241 .addIf(nn(in), "in") 242 .addIf(nn(name), "name") 243 .addIf(nn(openIdConnectUrl), "openIdConnectUrl") 244 .addIf(nn(scheme), "scheme") 245 .addIf(nn(type), "type") 246 .build(); 247 // @formatter:on 248 return new MultiSet<>(s, super.keySet()); 249 } 250 251 @Override /* Overridden from SwaggerElement */ 252 public SecuritySchemeInfo set(String property, Object value) { 253 reqnn("property", property); 254 return switch (property) { 255 case "bearerFormat" -> setBearerFormat(s(value)); 256 case "description" -> setDescription(s(value)); 257 case "flows" -> setFlows(toType(value, OAuthFlow.class)); 258 case "in" -> setIn(s(value)); 259 case "name" -> setName(s(value)); 260 case "openIdConnectUrl" -> setOpenIdConnectUrl(s(value)); 261 case "scheme" -> setScheme(s(value)); 262 case "type" -> setType(s(value)); 263 default -> { 264 super.set(property, value); 265 yield this; 266 } 267 }; 268 } 269 270 /** 271 * Bean property setter: <property>bearerFormat</property>. 272 * 273 * <p> 274 * A hint to the client to identify how the bearer token is formatted. 275 * 276 * @param value The new value for this property. 277 * <br>Can be <jk>null</jk> to unset the property. 278 * @return This object 279 */ 280 public SecuritySchemeInfo setBearerFormat(String value) { 281 bearerFormat = value; 282 return this; 283 } 284 285 /** 286 * Bean property setter: <property>description</property>. 287 * 288 * <p> 289 * A short description for the security scheme. 290 * 291 * @param value 292 * The new value for this property. 293 * <br>Can be <jk>null</jk> to unset the property. 294 * @return This object 295 */ 296 public SecuritySchemeInfo setDescription(String value) { 297 description = value; 298 return this; 299 } 300 301 /** 302 * Bean property setter: <property>flows</property>. 303 * 304 * <p> 305 * An object containing configuration information for the flow types supported. 306 * 307 * @param value 308 * The new value for this property. 309 * <br>Can be <jk>null</jk> to unset the property. 310 * @return This object 311 */ 312 public SecuritySchemeInfo setFlows(OAuthFlow value) { 313 flows = value; 314 return this; 315 } 316 317 /** 318 * Bean property setter: <property>in</property>. 319 * 320 * <p> 321 * The location of the API key. 322 * 323 * @param value 324 * The new value for this property. 325 * <br>Valid values: 326 * <ul> 327 * <li><js>"query"</js> 328 * <li><js>"header"</js> 329 * <li><js>"cookie"</js> 330 * </ul> 331 * <br>Can be <jk>null</jk> to unset the property. 332 * @return This object 333 */ 334 public SecuritySchemeInfo setIn(String value) { 335 if (isStrict() && ! contains(value, VALID_IN)) 336 throw rex("Invalid value passed in to setIn(String). Value='%s', valid values=[%s]", value, toCdl(VALID_IN)); 337 in = value; 338 return this; 339 } 340 341 /** 342 * Bean property setter: <property>name</property>. 343 * 344 * <p> 345 * The name of the header, query or cookie parameter to be used. 346 * 347 * @param value 348 * The new value for this property. 349 * <br>Can be <jk>null</jk> to unset the property. 350 * @return This object 351 */ 352 public SecuritySchemeInfo setName(String value) { 353 name = value; 354 return this; 355 } 356 357 /** 358 * Bean property setter: <property>openIdConnectUrl</property>. 359 * 360 * <p> 361 * OpenId Connect URL to discover OAuth2 configuration values. 362 * 363 * @param value The new value for this property. 364 * <br>Can be <jk>null</jk> to unset the property. 365 * @return This object 366 */ 367 public SecuritySchemeInfo setOpenIdConnectUrl(String value) { 368 openIdConnectUrl = value; 369 return this; 370 } 371 372 /** 373 * Bean property setter: <property>scheme</property>. 374 * 375 * <p> 376 * The name of the HTTP Authorization scheme to be used in the Authorization header. 377 * 378 * @param value 379 * The new value for this property. 380 * <br>Can be <jk>null</jk> to unset the property. 381 * @return This object 382 */ 383 public SecuritySchemeInfo setScheme(String value) { 384 scheme = value; 385 return this; 386 } 387 388 /** 389 * Bean property setter: <property>type</property>. 390 * 391 * <p> 392 * The type of the security scheme. 393 * 394 * @param value 395 * The new value for this property. 396 * <br>Valid values: 397 * <ul> 398 * <li><js>"apiKey"</js> 399 * <li><js>"http"</js> 400 * <li><js>"oauth2"</js> 401 * <li><js>"openIdConnect"</js> 402 * </ul> 403 * <br>Can be <jk>null</jk> to unset the property. 404 * @return This object 405 */ 406 public SecuritySchemeInfo setType(String value) { 407 if (isStrict() && ! contains(value, VALID_TYPES)) 408 throw rex("Invalid value passed in to setType(String). Value='%s', valid values=[%s]", value, toCdl(VALID_TYPES)); 409 type = value; 410 return this; 411 } 412 413 @Override /* Overridden from OpenApiElement */ 414 public SecuritySchemeInfo strict(Object value) { 415 super.strict(value); 416 return this; 417 } 418 419 @Override /* Overridden from SwaggerElement */ 420 protected SecuritySchemeInfo strict() { 421 super.strict(); 422 return this; 423 } 424}