Security API
So the endpoint is there and anyone can do whatever they want? Of course not.
Going back to the top level of the specification we have security which expects a list of Security Requirement Object that will be used by operations within the API. We can define a scope for each of these objects in a list for global application. It is possible to override within each operation if necessary.
The definitions of these objects are inside components in securitySchemes.

#...
security:
- MyApiKeyAuth: [] # Security Requirement Object for `ApiKeyAuth`, empty list as there are no scopes.
- MyOtherApiKeyAuth: []
components:
##...
securitySchemes: # <<<<<<<<<<<<<<<<<<< here inside
MyApiKeyAuth:
#...
MyOtherApiKeyAuth:
#..
## ...
Defining a securitySchema depends on the type of authentication you want to use. The possible parameters used here are:
type: REQUIRED and can be "apiKey", "http", "mutualTLS", "oauth2", "openIdConnect"description:nameOnly used when type is "apiKey" being Requiredin: Only used when type is "apiKey" and the possible values are "query", "header", or "cookie" being Required.schemeOnly used when type is "http" being RequiredbearerFormatOnly used when type is "http" with bearer tokenflowsOnly used when type is "oauth2" being RequiredopenIdConnectUrlOnly used when type is "openIdConnect" being Required
We can see we have many options depending on the chosen type.
Let's illustrate quickly just to see where each thing is defined.
openapi: 3.0.0
info:
#...
security: # Global level
- ApiKeyAuth: []
paths:
/example:
get:
summary: Example endpoint
description: This endpoint requires an API key in the header.
# The field below would override global security if necessary.
# Local level
# security: ##
# - ApiKeyAuth: []
responses:
#...
#...
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
description: Access using an API Key
name: X-API-KEY
in: header
We won't go too deep into the types of authentication, but how to use them.
Understanding the above concept I will put the complete API from the study and comment only the security part. This is the final api that we will later use for code generation.
openapi: 3.0.2
info:
title: OpenAPI Course
description: Specification for OpenAPI Course
termsOfService: http://example.com/terms/
contact:
name: David Puziol
url: https://devsecops.puziol.com.br
email: [email protected]
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
version: "1.0"
servers:
- url: https://dev.example.com
description: Development Server
- url: https://qa.example.com
description: QA Server
- url: https://prod.example.com
description: Production Server
externalDocs:
description: Learn more about how to use the API at devsecops.puziol.com.br
url: https://devsecops.puziol.com.br/docs/development/openapi/1.0%20-%20OpenApi
security: # Will force these two authentications on all operations of all endpoints.
- BasicAuth: []
- JwtAuthToken: []
paths:
/v1/customers:
get:
summary: List of Customers
description: Get a list of customers in the system
operationId: listCustomersV1
externalDocs:
description: Learn more about how to use the API at devsecops.puziol.com.br
url: https://devsecops.puziol.com.br/docs/development/openapi/1.0%20-%20OpenApi
tags:
- Customer
security: [] # Overwrite here to not need authentication
parameters:
- $ref: "#/components/parameters/PageNumber"
- $ref: "#/components/parameters/PageSize"
requestBody:
description: user to add to the system
required: true
content:
text/plain:
schema:
type: array
items:
type: string
responses:
200:
description: List of Customers
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerPagedList'
post:
summary: New Customer
description: Create a new customer
operationId: newCustomer
tags:
- Customer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
responses:
201:
description: New Customer Created
headers:
location:
schema:
description: Location of the created resource
type: string
format: uri
400:
description: Bad Request
409:
description: Conflict
/v1/customers/{Id}:
get:
summary: Get a Customer
description: Get a single customer by its ID value
operationId: getCustomerById
tags:
- Customer
parameters:
- $ref: '#/components/parameters/Id'
responses:
200:
description: Found Customer
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
404:
description: Not found
put:
summary: Update Customer
description: Update customer by id.
tags:
- Customer
operationId: updateCustomerById
parameters:
- $ref: '#/components/parameters/Id'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
responses:
204:
description: Customer Updated
400:
description: Bad Request
404:
description: Not found
409:
description: Conflict
delete:
summary: Delete Customer
description: Delete customer by id.
tags:
- Customer
operationId: deleteCustomerById
parameters:
- $ref: '#/components/parameters/Id'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
responses:
200:
description: Customer Deleted
404:
description: Not found
/v1/customers/{customerId}/orders:
post:
tags:
- Order Service
description: Place Order
parameters:
- name: customerId
in: path
description: Customer Id
required: true
style: simple
explode: false
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/BeerOrder'
required: false
responses:
201:
description: Order Created
headers:
Location:
description: Reference to created Order
style: simple
explode: false
schema:
type: string
format: uri
400:
description: Bad Reqeust
404:
description: Not Found
409:
description: Conflict
callbacks:
orderStatusChange:
${request.body#/orderStatusCallbackUrl}:
description: Webhook for order status change notifications
post:
requestBody:
content:
application/json:
schema:
type: object
properties:
orderId:
type: string
format: uuid
orderStatus:
type: string
responses:
200:
description: Okay
/v1/beers:
get:
summary: List of beers
description: Get a list of beers in the system
operationId: listBeers
tags:
- Beer
parameters:
- $ref: "#/components/parameters/PageNumber"
- $ref: "#/components/parameters/PageSize"
responses:
200:
description: List of Beers
content:
application/json:
schema:
$ref: '#/components/schemas/BeerPagedList'
post:
summary: New Beer
description: Create a new beer
operationId: newBeer
tags:
- Beer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Beer'
responses:
201:
description: New Beer Created
headers:
location:
schema:
description: Location of the created resource
type: string
format: uri
400:
description: Bad Request
409:
description: Conflict
/v1/beer/{Id}:
get:
summary: Get a Customer
description: Get a single customer by its ID value
operationId: getBeerById
tags:
- Beer
parameters:
- $ref: '#/components/parameters/Id' # but this will bring the name Id
responses:
200:
description: Found Beer
content:
application/json:
schema:
$ref: '#/components/schemas/Beer'
404:
description: Not found
put:
summary: Update Beer
description: Update beer by id.
tags:
- Beer
operationId: updateBeerById
parameters:
- $ref: '#/components/parameters/Id'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Beer'
responses:
204:
description: Customer Updated
400:
description: Bad Request
404:
description: Not found
409:
description: Conflict
delete:
summary: Delete Beer
description: Delete beer by id.
tags:
- Beer
operationId: deleteBeerById
parameters:
- $ref: '#/components/parameters/Id'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Beer'
responses:
200:
description: Beer Deleted
404:
description: Not found
components:
securitySchemes:
## Our two types of authentication
BasicAuth:
type: http
scheme: basic
JwtAuthToken:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
Address:
type: object
properties:
line1:
type: string
example: 123 main
city:
type: string
example: St Pete
stateCode:
maxLength: 2
minLength: 2
type: string
description: 2 Letter State Code
enum:
- AL
- AK
- AZ
- AR
- CA
zipCode:
type: string
example: "33701"
Customer:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
firstName:
maxLength: 100
minLength: 2
type: string
example: John
lastName:
maxLength: 100
minLength: 2
type: string
example: Thompson
address:
$ref: '#/components/schemas/Address'
description: customer object
CustomerList:
maxItems: 100
minItems: 1
type: array
description: List of Customers
items:
$ref: '#/components/schemas/Customer'
CustomerPagedList:
type: object
properties:
content:
$ref: '#/components/schemas/CustomerList'
allOf:
- $ref: '#/components/schemas/PagedResponse'
Brewery:
type: object
properties:
name:
type: string
location:
type: string
Beer:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
beerName:
type: string
style:
type: string
enum:
- ALE
- PALE_ALE
- IPA
- WHEAT
- LAGER
price:
type: number
format: float
quantityOnHand:
type: integer
format: int32
brewery:
$ref: '#/components/schemas/Brewery'
description: Beer Object
BeerList:
type: array
items:
$ref: '#/components/schemas/Beer'
BeerPagedList:
type: object
properties:
content:
$ref: '#/components/schemas/BeerList'
allOf:
- $ref: '#/components/schemas/PagedResponse'
BeerOrder:
required:
- customerId
type: object
properties:
id:
type: string
format: uuid
nullable: true
readOnly: true
customerId:
type: string
format: uuid
customerRef:
type: string
nullable: true
beerOrderLines:
type: array
items:
$ref: '#/components/schemas/BeerOrderLine'
orderStatusCallbackUrl:
type: string
format: uri
BeerOrderLine:
required:
- orderQuantity
- upc
type: object
properties:
id:
type: string
format: uuid
nullable: true
readOnly: true
beerId:
type: string
format: uuid
readOnly: true
upc:
type: string
orderQuantity:
maximum: 999
minimum: 1
type: integer
quantityAllocated:
type: integer
nullable: true
readOnly: true
PagedResponse:
type: object
properties:
pageable:
$ref: '#/components/schemas/PagedResponse_pageable'
totalPages:
type: integer
format: int32
last:
type: boolean
totalElements:
type: integer
format: int32
size:
type: integer
format: int32
number:
type: integer
format: int32
numberOfElements:
type: integer
format: int32
sort:
$ref: '#/components/schemas/PagedResponse_pageable_sort'
first:
type: boolean
PagedResponse_pageable_sort:
type: object
properties:
sorted:
type: boolean
unsorted:
type: boolean
PagedResponse_pageable:
type: object
properties:
sort:
$ref: '#/components/schemas/PagedResponse_pageable_sort'
offset:
type: integer
format: int32
pageNumber:
type: integer
format: int32
pageSize:
type: integer
format: int32
paged:
type: boolean
unpaged:
type: boolean
parameters:
PageNumber:
name: pageNumber
in: query
description: Page number
schema:
type: integer
format: int32
default: 1
PageSize:
name: pageSize
in: query
required: false # this is already the default
schema:
type: integer
format: int32
Id:
name: Id
in: path
required: true # this is already the default
description: UUID for Id
schema:
type: string
format: uuid

And where you click that has the lock will show this

When it appears logged in with any password you put at that moment it will show like this.

All requests will use this login from now on.