Writing OpenAPI (Swagger) Specification Tutorial Series - Part 6
Defining Security
By Arnaud Lauret, May 22, 2016
After mastering input and output modeling like a Jedi, let’s see how we can describe API’s security with the OpenAPI specification’s.
Writing OpenAPI (Swagger) Specification Tutorial Series
This tutorial teaches everything about the OpenAPI 2.0 Specification (fka. as Swagger), most of what you’ll read here can still be applied on version 3.
If you’re a bit lost in the specification (version 2 or 3), take a look at the OpenAPI Map:
In previous parts we’ve learned to write efficiently highly accurate interface description, in this seventh part we’ll learn how to describe how an API is secured.
Security definitions
Following (almost) the same principle used with parameters
and definitions
, security can be defined and then used on different levels.
Security definition takes place on specification’s root level in securityDefinition
section. It contains a list of named security definitions. Each definition can be of type:
basic
for Basic AuthenticationapiKey
when using an API key to secure the APIoauth2
for Oauth 2
Basic Authentication
To define a basic
security it’s fairly easy, we only have to set its type
to basic
:
securityDefinitions:
UserSecurity:
type: basic
AdminSecurity:
type: basic
MediaSecurity:
type: basic
In this example we have defined three security definitions (UserSecurity
, AdminSecurity
and MediaSecurity
), each of them is of basic
type.
API Key
To define an apiKey
security we have to:
- Set
type
toapiKey
- Indicate where the API ley is located with
in
. An API can be in aheader
or aquery
parameter - And then give the parameter’s
name
securityDefinitions:
UserSecurity:
type: apiKey
in: header
name: SIMPLE-API-KEY
AdminSecurity:
type: apiKey
in: header
name: ADMIN-API-KEY
MediaSecurity:
type: apiKey
in: query
name: media-api-key
In this example, we have defined three security definitions of apiKey
type:
UserSecurity
uses aheader
parameter namedSIMPLE-API-KEY
AdminSecurity
uses aheader
parameter namedADMIN-API-KEY
MediaSecurity
uses aquery
parameter namedmedia-api-key
Oauth 2
Flow and URLs
When defining an oauth2
security definition, we can define the Oauth2 flow
used and corresponding authorizationUrl
and/or tokenUrl
depending on the chosen flow:
Flow | Required URLs |
---|---|
implicit | authorizationUrl |
password | tokenUrl |
application | tokenUrl |
accessCode | authorizationUrl and tokenUrl |
securityDefinitions:
OauthSecurity:
type: oauth2
flow: accessCode
authorizationUrl: 'https://oauth.simple.api/authorization'
tokenUrl: 'https://oauth.simple.api/token'
In this example we have defined a OauthSecurity
security definition of oauth2
type using an accessCode
flow with an authorizationUrl and a tokenUrl.
Scopes
We can also define scopes
by using a hashmap, the key is the scope’s name and the value is its description.
securityDefinitions:
OauthSecurity:
type: oauth2
flow: accessCode
authorizationUrl: 'https://oauth.simple.api/authorization'
tokenUrl: 'https://oauth.simple.api/token'
scopes:
admin: Admin scope
user: User scope
media: Media scope
In this example, we’ve added three scopes (admin
, user
and media
) to our OauthSecurity
security definition
Using security definitions
Once we have described security definitions in securityDefinition
we can apply them to the overall API or to specific operations with the security
sections.
When we apply a security definition to an operation, it overrides API security.
Basic Authentication
Let’s see how we can use a basic
security definition.
API level
In this example the security definition which apply to ALL API operations is UserSecurity
:
securityDefinitions:
UserSecurity:
type: basic
AdminSecurity:
type: basic
MediaSecurity:
type: basic
security:
- UserSecurity: []
paths:
/persons:
Operation level
As GET /persons
operation do not define a security
, it’s the UserSecurity
defined on top level which applies:
paths:
/persons:
parameters:
- $ref: '#/parameters/userAgent'
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
parameters:
- $ref: '#/parameters/pageSize'
- $ref: '#/parameters/pageNumber'
- $ref: '#/parameters/includeNonVerifiedUsers'
- $ref: '#/parameters/sortPersons'
On POST /persons
operation, the top level security is overridden by AdminSecurity
:
post:
summary: Creates a person
description: Adds a new person to the persons list.
security:
- AdminSecurity: []
On POST /images
operation, the top level security is also overridden, but this time it’s by MediaSecurity
:
/images:
parameters:
- $ref: '#/parameters/userAgent'
post:
summary: Uploads an image
security:
- MediaSecurity: []
API Key
We can do exactly the same things with an API key security definition.
API level
In this example the security definition which apply to ALL API operations is UserSecurity
:
securityDefinitions:
UserSecurity:
type: apiKey
in: header
name: SIMPLE-API-KEY
AdminSecurity:
type: apiKey
in: header
name: ADMIN-API-KEY
MediaSecurity:
type: apiKey
in: query
name: media-api-key
security:
- UserSecurity: []
paths:
/persons:
Operation level
As GET /persons
operation do not define a security
, it’s the UserSecurity
defined on top level which applies:
paths:
/persons:
parameters:
- $ref: '#/parameters/userAgent'
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
parameters:
- $ref: '#/parameters/pageSize'
- $ref: '#/parameters/pageNumber'
- $ref: '#/parameters/includeNonVerifiedUsers'
- $ref: '#/parameters/sortPersons'
On POST /persons
operation, the top level security is overridden by AdminSecurity
:
post:
summary: Creates a person
description: Adds a new person to the persons list.
security:
- AdminSecurity: []
On POST /images
operation, the top level security is also overridden, but this time it’s by MediaSecurity
:
/images:
parameters:
- $ref: '#/parameters/userAgent'
post:
summary: Uploads an image
security:
- MediaSecurity: []
Oauth 2
With an oauth2
the principle is the same but you can also define which scope(s) you use.
API level
In this example the security definition which apply to ALL API operations is OauthSecurity
with the user
scope:
securityDefinitions:
OauthSecurity:
type: oauth2
flow: accessCode
authorizationUrl: 'https://oauth.simple.api/authorization'
tokenUrl: 'https://oauth.simple.api/token'
scopes:
admin: Admin scope
user: User scope
media: Media scope
security:
- OauthSecurity:
- user
paths:
/persons:
Operation level
As GET /persons
operation do not define a security
, it’s the OauthSecurity
with user
scope defined on top level which applies:
paths:
/persons:
parameters:
- $ref: '#/parameters/userAgent'
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
parameters:
- $ref: '#/parameters/pageSize'
- $ref: '#/parameters/pageNumber'
- $ref: '#/parameters/includeNonVerifiedUsers'
- $ref: '#/parameters/sortPersons'
On POST /persons
operation, the top level security scope is overridden by admin
:
post:
summary: Creates a person
description: Adds a new person to the persons list.
security:
- OauthSecurity:
- admin
On POST /images
operation, the top level security is also overridden, but this time it’s by media
:
Using multiple security types
It’s not mandatory to define a single type of security definition and use only one at a time. The examples below show how we can define security definitions of different types and use more than one on operations.
Security definitions
Here we define there different types of security:
securityDefinitions:
OauthSecurity:
type: oauth2
flow: accessCode
authorizationUrl: 'https://oauth.simple.api/authorization'
tokenUrl: 'https://oauth.simple.api/token'
scopes:
admin: Admin scope
user: User scope
MediaSecurity:
type: apiKey
in: query
name: media-api-key
LegacySecurity:
type: basic
Global security
Then we choose to apply both of them globally:
It means that a consumer can call any operation (which do not override security) with one of those two security types.
Overriding global security
As GET /persons
operation do not define a security
, it’s the Oauth 2 OauthSecurity
with user
scope OR the basic authentication LegacySecurity
defined on top level which applies:
paths:
/persons:
parameters:
- $ref: '#/parameters/userAgent'
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
parameters:
- $ref: '#/parameters/pageSize'
- $ref: '#/parameters/pageNumber'
- $ref: '#/parameters/includeNonVerifiedUsers'
- $ref: '#/parameters/sortPersons'
On POST /persons
operation, the top level security scope Oauth 2 OauthSecurity
is overridden by admin
and consumer can also still use the basic authentication LegacySecurity
:
post:
summary: Creates a person
description: Adds a new person to the persons list.
security:
- OauthSecurity:
- admin
- LegacySecurity: []
On POST /images
operation, the top level security is fully overridden by the API Key MediaSecurity
:
Conclusion
You now have mastered security. With this new post you are now a full expert when it comes to describe an API interface with the OpenAPI specification. But an interface contract alone may not be easy to understand without some explainations. In next post we’ll learn how to document this interface description to ease its understanding.