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 Authentication
  • apiKey when using an API key to secure the API
  • oauth2 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 to apiKey
  • Indicate where the API ley is located with in. An API can be in a header or a query 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 a header parameter named SIMPLE-API-KEY
  • AdminSecurity uses a header parameter named ADMIN-API-KEY
  • MediaSecurity uses a query parameter named media-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 userscope 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:

  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      security:
        - OauthSecurity:
          - 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:

security:
  - OauthSecurity:
    - user
  - LegacySecurity: []

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 userscope 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:

  /images:
    parameters:
      - $ref: '#/parameters/userAgent'
    post:
      summary: Uploads an image
      security:
        - 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.

By continuing to use this web site you agree with the API Handyman website privacy policy (effective date , June 28, 2020).