Introduction
In microservice development, an Application Program Interface (API) is way for applications to communicate with each other in other using a common language. As humans we speak common language, APIs allows machine-to-machine communications.
While we know the uses of API in the microservice architectures, its vital to ensure the API's are secure from attacks. Today we will see how to secure the API. And will discuss various security standards such as OAuth, SAML, PKI, Kerberos, TLS. The security model needs to balance the security, usability and scalability. Strategic planning needs to be done to determine how to connect application identities with user identities. Also there are other forms of security which will not be covered here such as firewalls, intrusion detection software, regular patching, user education, and so on.
To all be in the same page, lets see the difference between authentication and authorization:
Authentication: Process of verifying the identity, confirming they are who you say you are. Usually the user here will provide the combinations of who you are - username, what you know – (password) and what you have – (otp/token/etc)
Federated Authentication: Applications refer or rely other application to verify the identify of the user. OpenID is most common open protocol for handling federated authentication.
Authorization: Process of verifying that you have access or are you allowed to perform the action.
Delegated Authorization: Allowing the granting access process to another resource, on your behalf. OAuth works similarly where the user grant access to an application to perform actions on the user's behave and the application can only perform the authorized access.
![]() |
Fig: Authentication Vs Authorization Credits: https://dzone.com/articles/four-most-used-rest-api-authentication-methods |
Before we get started with the various security standards, lets see the several attacks happening creating the need of these standards.
Attacks
Compromised Or Weak Credentials
Common usernames and weak passwords can lead to compromised credentials
MITM
Man in the middle attacks involve someone intercepting and altering communications between the client and the server. Here the attacker can relay the messages between sender and receiver as they are talking to each other, when in fact the entire conversation is controlled.
API injection attacks
Malicious code is inserted into the program as an attack and performed seem less to the user.
Includes cross-site script and SQL injection attacks
DDOS
Distributed denial of service attacks attempt to disable API from functioning by overwhelming the server with requests.
Flood the bandwidth usually with one or more servers (bots called at times)
Sniffers
Theft of data by capturing the network traffic using packet sniffer.
When the data transmitted across networks, if the data is not encrypted it could be easily read by using the sniffers.
Specially when user name and password transferred over HTTP protocol.
Cache Poisoning
Attacker exploits the behaviour of a webserver and cache so that malicious response is served to the users.
Once the malicious content is cached, the users will receive until its purged or cleared.
Session hijack
Exploitation of the web session control, which is ideally handled by the session token.
Attack compromises the session token by stealing or predicting a valid session token in order to gain unauthorized access to the server.
Buffer overrun
Attackers exploit buffer overflow issue by overwriting the memory of an application. Causing the damage to the files or leaking the private information or even gaining access to the IT systems.
Web API Security
Basic Authentication
Description
Basic Authentication can be performed with a username and password in the request header and verify that the user name and password are valid by comparing them against a database of authorized users.
Basic authentication sends user names and passwords over the Internet as text that is Base64 encoded, and the target server is not authenticated.
Should be used with HTTPS (SSL)
Architecture

Fig: HTTP Basic Authentication
Credits: https://docs.oracle.com/cd/E19226-01/820-7627/bncbo/index.html
Implementation
Source Code
– Server Code using HTTPBasicAuth module
from flask import Flaskfrom flask_httpauth import HTTPBasicAuthfrom werkzeug.security import generate_password_hash, check_password_hashapp = Flask(__name__)auth = HTTPBasicAuth()users = {"john": generate_password_hash("hello"),"susan": generate_password_hash("bye")}@auth.verify_passworddef verify_password(username, password):if username in users and \check_password_hash(users.get(username), password):return username@app.route('/')@auth.login_requireddef index():return "Hello, {}!".format(auth.current_user())if __name__ == '__main__':app.run()
Output
Without user credentials
![]() |
| Fig: HTTP Basic Authentication - Without user credentials |
![]() |
| Fig: HTTP Basic Authentication - Passing user credentials |
Risks
Its is not very secure, the user name and password information can easily be decoded.
Bearer Authentication
Description
Bearer authentication also called as Token Authentication, uses security tokens (bearer tokens) to request resources.
Should be used with HTTPS (SSL)
Flow
Here the client application first sends a request to Authentication server with valid credentials, after successful authentication the server replies back with access token.
Usually this token comes with expiry time and refresh token.
The client application use this token to request resources until the expiry time, and later using the refresh token get the new bearer token.
Need to pass as below syntax in the HTTP Header:
Authorization: Bearer <token>
Here the user credentials are avoided to be passed multiple times, rather the token is used for authentication of the user.
Architecture

Fig: Token Based Authentication
Credit: https://www.ecanarys.com/Blogs/ArticleID/308/Token-Based-Authentication-for-Web-APIs
Implementation
Source Code – Server Code using HTTPBasicAuth module
from flask import Flaskfrom flask_httpauth import HTTPTokenAuthapp = Flask(__name__)auth = HTTPTokenAuth(scheme='Bearer')tokens = {"secret-token-1": "john","secret-token-2": "susan"}@auth.verify_tokendef verify_token(token):if token in tokens:return tokens[token]@app.route('/')@auth.login_requireddef index():return "Hello, {}!".format(auth.current_user())if __name__ == '__main__':app.run()
Output
Invalid Token result
![]() |
Fig: Token Based Authentication - Invalid Token
- Valid Token result
![]() |
| Fig: Token Based Authentication - Valid Token |
- Valid Token HTTP Header
![]() |
| Fig: Token Based Authentication - Valid Token HTTP Header Output |
Risks
One of the major concern is relying on just one token, which is vulnerable if the token key is compromised.
Digest Authentication
- Description
- Digest authentication where the user passes the hashed credentials to the user to the server and sends a special key, called a digest session key, to the server that received the original request.
- The user must then produce a response, which is encrypted and transmitted to the server. If the user's response is of the correct form, the server grants the user access to the network, Web site or requested resources for a single session.
- Flow
- Client requests to access the resource, the server responds first by 401 status code and WWW-Authenticate: Digest <digest challenge> and this response <digest challenge> is created and encrypted to using MD5 algorithm
- The Digest challenge can contain the following attributes
- realm
- domain
- nonce algorithm
- Hashes the username and password and transmits the hashed value, After the user providing the credentials, the encrypted data is append the second request header from the client
- Webserver receiving the validate the response credential using the same algorithm building using the nonce value and compare
- Responds 200 status code on matching, else 403 status code stating invalid credentials.
Architecture

Fig: Digest Authentication
Implementation
Source Code – Server Code using HTTPBasicAuth module
from flask import Flaskfrom flask_httpauth import HTTPDigestAuthapp = Flask(__name__)app.config['SECRET_KEY'] = 'secret key here'auth = HTTPDigestAuth()users = {"admin": "admin","user": "pass","john": "hello","susan": "bye"}@auth.get_passworddef get_pw(username):if username in users:return users.get(username)return None@app.route('/')@auth.login_requireddef index():print(auth.username())return "Hello, {}!".format(auth.username())if __name__ == '__main__':app.run()
Output
## Client Code
import requests
from requests.auth import HTTPDigestAuth
url = 'http://127.0.0.1:5000/'
output = requests.get(url, auth=HTTPDigestAuth('user', 'pass'))
print(output)
print(output.text)
% python digest_auth_client.py
<Response [200]>
Hello, user!
127.0.0.1 - - [30/May/2022 22:43:50] "GET / HTTP/1.1" 401 -
user
127.0.0.1 - - [30/May/2022 22:43:50] "GET / HTTP/1.1" 200 -
Risks
- HTTP Digest serves as SFA i.e Single Factor Authentication (the password or user response) is relatively easy for an experienced hacker to discover and exploit.
- HTTP Digest is vulnerable to a man-in-the-middle security attack which basically means it could be hacked
- HTTP Digest prevents use of the strong password encryption, meaning the passwords stored on the server could be hacked
API Keys
Description
API keys can be used for authentication
- API Keys are widely used but are not considered a good security measure
- API Keys should never be placed in the URL string, as they could be easily discovered
- API Keys are useful for performing simple read operations that do not change the underlying data
- API Key is generated for the first time user creation, and registers with the user. At times this is mapped with hardware address or IP address or such combinations, to make sure even when the key is not misused.
- Need to pass as below syntax in the HTTP Header:
- Authorization: Apikey 9080-20380-9340-98
Architecture

Fig: API Key Authentication
Credits: https://dzone.com/articles/four-most-used-rest-api-authentication-methods
Implementation
- Source Code
Risks
- In case of HTTP network traffic can be sniffed and API key can be stolen.
- Vulnerable to replay attacks.
JSON Web Tokens (JWT)
Description
JWT is abbreviated to JSON (JavaScript Object Notation) Web Token.
It is an open standard for sharing confidential information between two parties.
JWTs are signed using a cryptographic algorithm, which makes sure the data cannot be altered.
Can be used for API client authentication and authorization.
JWT holds of three parts
header
Contains the algorithm used for the signature, the whole part is encoded in Base64
Eg:
“Header” section :
{
“alg”: “HS256”,
“typ”: “JWT”
}
- payload
- Contains the token information, such as username, time of creation, time of expiration, and actual data.
- The data is written in JSON format and encoded as well in Base64
- Eg:
“Payload” section :
{
“iat”: 1480929282,
“exp”: 1480932868,
“name”: “Username”
}
- signature
- Ensures the token cannot be altered.
- Using this signature the header and payload is concatenated and encrypted, this signature could be either common to both the parties (sender and receiver)
- Or it could be the receiver's public key where the sender encrypts the message with receiver's public key and after transmission the receiver will decrypt with its own private key.
- Eg:
Signature = HMACSHA256 (
base64UrlEncode({“alg”: “HS256″,”typ”: “JWT”}) + “.” +
base64UrlEncode({“iat”: 1480929282,”exp”: 1480932868,”name”: “Username”}),
L2VE5VpgChrVPmgh1hgL
)
- L2VE5VpgChrVPmgh1hgL is the private key, HMACSHA256 is the algorithm
- After encryption the data would look something like this.
- eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0ODA5MjkyODIsImV4cCI6MTQ4MDkzMjg2OCwibmFtZSI6IlVzZXJuYW1lIn0.gZeuWNbjO8kyEX92AjgX5oLy5qhu6YWTPr6vtYELZQ4
- Here different colour specifies the data in each section.
Flow
JWTs are generated in the server side when the login happens.
After authentication succeeds, JWT is shared back to the browser.
For each subsequent request, now the JWT is sent to the server, allowing the server to authenticate the user with the token.
While authentication the server will validate the decrypted token which is usual, or compare if it has saved this token against the user in memory database ( eg: Redis ).
- At times the expiration date is as well set to the token, to resolve the vulnerability of lasting forever and could be misused.
- As here we could see, the data doesn't needs to be stored in the server's memory, it because truly stateless and can be easily used as distributed system as well.
Architecture

Fig: JWT Authentication
Credits: https://www.vaadata.com/blog/jwt-tokens-and-security-working-principles-and-use-cases/
Implementation
Source Code
import syssys.path.insert(0,'env/lib/python3.7/site-packages')# flask importsfrom flask import Flask, request, jsonify, make_responseimport uuid # for public idfrom werkzeug.security import generate_password_hash, check_password_hash# imports for PyJWT authenticationimport jwtfrom datetime import datetime, timedeltafrom functools import wraps# creates Flask objectapp = Flask(__name__)# configuration# NEVER HARDCODE YOUR CONFIGURATION IN YOUR CODE# INSTEAD CREATE A .env FILE AND STORE IN ITapp.config['SECRET_KEY'] = 'dummy secret key'USERS_DB = {"admin": {"username": "admin","password": generate_password_hash("admin"),"public_id": str(uuid.uuid4())}}# decorator for verifying the JWTdef token_required(f):@wraps(f)def decorated(*args, **kwargs):token = None# jwt is passed in the request headerif 'x-access-token' in request.headers:token = request.headers['x-access-token']# return 401 if token is not passedif not token:return jsonify({'message' : 'Token is missing !!'}), 401try:# decoding the payload to fetch the stored detailsdata = jwt.decode(token, app.config['SECRET_KEY'])print(data)## here using the data fetched from the token to fetch the user detailsfor x in USERS_DB.keys():if USERS_DB[x]['public_id'] == data['public_id']:current_user = xbreakprint(current_user)except:return jsonify({'message' : 'Token is invalid !!'}), 401# returns the current logged in users contex to the routesreturn f(current_user, *args, **kwargs)return decorated# helloworld route@app.route('/', methods =['GET'])@token_requireddef helloworld(user):return jsonify({'welcome': "hello world {}".format(user)})# route for logging user in@app.route('/login', methods =['POST'])def login():# creates dictionary of form dataauth = request.formif not auth or not auth.get('user') or not auth.get('password'):# returns 401 if any user or / and password is missingreturn make_response('Could not verify',401,{'WWW-Authenticate' : 'Basic realm ="Login required !!"'})user = auth.get('user')if not user:# returns 401 if user does not existreturn make_response('Could not verify',401,{'WWW-Authenticate' : 'Basic realm ="User does not exist !!"'})if check_password_hash(USERS_DB[user]['password'], auth.get('password')):# generates the JWT Tokentoken = jwt.encode({'public_id': USERS_DB[user]['public_id'],'exp' : datetime.utcnow() + timedelta(minutes = 30)}, app.config['SECRET_KEY'])return make_response(jsonify({'token' : token.decode('UTF-8')}), 201)# returns 403 if password is wrongreturn make_response('Could not verify',403,{'WWW-Authenticate' : 'Basic realm ="Wrong Password !!"'})if __name__ == "__main__":# setting debug to True enables hot reload# and also provides a debugger shell# if you hit an error while running the serverapp.run(debug = True)Output

Fig: Get the Token 
Fig: Using token calling the endpoint
Risks
- There is a cost involved in using JWTs: they are sent for every request to the server and it’s always a high cost compared to server-side sessions.
- Server just can’t remove a JWT at the end of a session because it’s self-contained and there’s no central authority to invalidate them. So logout really doesn't logout.
- Needs HTTPS to encrypt the key and credentials passed.
PKI
Description
- PKI is abbreviated as Public Key Infrastructure, also known as asymmetric encryption.
Two keys are involved here:
Public Key -> Known to All
Public Key is used to encrypts the message using the Receiver's Public Key
Eg:
Alice wants to send “Hi” message to Bob, first Alice will need to know Bob's Public Key
Alice encrypts “Hi” message using Public Key of Bob and send him the encrypted message
Private Key -> Known Only to You
Receiver here decrypts the encrypted message using his/her own Primary Key.
Eg:
Bob will decrypt the encrypted message sent by Alice using his own Private Key
Certification Authority (CA) to issue certificates
Here we have an issue, how do we know if we are encrypting our message using the right Private Key, as per our example anyone can claim he is Bob and get the Alice's private message to Bob.
To validate the that a public key is actually owned by the person or entity that claims it, we need Certification Authority.
Digital certificate is issued which contains information about the key-holder, the public key, an expiration date and the signature of the Certificate Authority that issued it.
Using the Digital certificate that is issued, anyone can verify the identity of the key-holder.
In our Scenario, Alice can verify Bob's Public Key from CA.
Architecture

Fig: PKI Authentication Components
Credits: https://cheapsslsecurity.com/blog/understanding-the-role-of-certificate-authorities-in-pki/
- Implementation
- Notes:
- CA: In the below implementation, we have created our own certificate authority (CA)
- Sever: Web server to be bound to a certificate and key, such data can be used by the connecting client to establish the trust of the server’s identity. Since this is self signed certificate we need to enforce externally to trust this.
- Client: Validate the client certificate itself is generated by the correct certificate authority (CA) — in our case root_ca.crt
- Below article is the best read and reference, kudos to the author:
- https://carolinafernandez.github.io/development/2017/09/13/HTTPS-and-trust-chain-in-Flask
- Caveat: Below example authentication of client is still have some hurdles, working on it, will update once resolved.
- Prerequisites
-
openssl genrsa -out root_ca.key 2048
openssl req -x509 -new -nodes -key root_ca.key -sha256 -days 1024 -out root_ca.crt
# Generate server request and sign it by the CA
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -CA root_ca.crt -CAkey root_ca.key -CAcreateserial -out server.crt -days 1024 -sha256
# Generate client request and sign it by the CA
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr
openssl x509 -req -in client.csr -CA root_ca.crt -CAkey root_ca.key -CAcreateserial -out client.crt -days 1024 -sha256
# Define the PEM files for CA and client
cat root_ca.crt root_ca.key > root_ca.pem
cat client.crt client.key > client.pem
- Source Code
- Output
% curl -k https://127.0.0.1:8000/ -E client.pem
Top-level content
- Reference
- https://carolinafernandez.github.io/development/2017/09/13/HTTPS-and-trust-chain-in-Flask
- Risks
- Keys needs to be secured well, leak will give access
Kerberos
Description
Kerberos is an authentication protocol used to verify the identity of the user or host over a non-secure network in a secure way, by avoiding sending open plaintext credentials.
Kerberos protocol is used in the single sign on (SSO) authentication, SSO allows users to use same username and password to access different applications and usually with only onetime login. Port 88 is used for Kerberos.
Fun Fact: Kerberos in Greek Mythology means three headed dog, which guards the gates of underworld to prevent from leaving.
Kerberos offers a methodical process for distributing keys to the communicating hosts and verifying the credentials of a client requesting access to a service.
Terms
Client: A user requesting access to a server
Server: A server, in our scenario a webserver offering a service on the network
KDC: A server designated to provide and manage keys for network communication. TGS and AS both runs inside KDC.
AS:
- Authentication Service (AS) verifies the user access.
- AS creates a Ticket Granting Ticket (TGT) ticket and Session Key
- The client can use the TGT to request access to other service providers for the lifetime of the ticket, which is usually one day.
- TGS:
- User needs to obtain a Service Ticket (ST) and Session Key from Ticket Granting Service (TGS)
- Below all the messages ensures to be timestamped, a short life span of a ticket ensures that if someone attempts to intercept the encrypted data to try to break its keys, the keys would have been changed before the attacker can reasonably succeed in breaking the key using the cryptographic algorithms.
Flow:
Client
Client provides the username and the request is passed to the AS
AS
AS returns client the request, after successful verification of user existence in the DB with TGT and Session Key
The results TGT and Session Key are encrypted using user's password, as you could see the password is not shared over network
Client
Client asked to enter password, now using the password the message is decrypted.
Client sends the TGT and Authenticator details such as time, username, ip address and so on to TGS requesting for SGT. These details are encrypted using the Session Key
TGS
TGS after receiving the request decrypts the message from client using the Session Key, as the TGT is not encrypted it use it to find the matched Session Key
TGS generates a Service Ticket that will be encrypted Requested Service's Key.
This message is not encrypted with Client Password
Client
Receives the message and decrypts with its Password, to make sure this message is from valid source
Now the Encrypted Message is sent to the Requested Service
Requested Service
Decrypts the message using its Service Key, verifies match if yes grants access to the service
SPNEGO
SPNEGO stands for Simple and Protected GSS_API Negotiation Mechanism for extending a Kerberos-based SSO environment for use in web applications using the standard HTTP Protocol
Communication primarily happens between a web browser like Chrome and a web server like Tomcat hosting the web application over HTTP.
If enabled, they can negotiate Kerberos as a security mechanism through SPNEGO and exchange tickets as SPNEGO tokens over HTTP.
So, not much has changed in this compared to our flow except that the communication between client and server happens explicitly over HTTP now.
Architecture

Fig: Kerberos Authentication
Credits: https://en.wikipedia.org/wiki/Kerberos_(protocol)
- Implementation [could not run in local]
- Kerberos authentication server
- https://github.com/apple/ccs-pykerberos
- Kerberos client
- https://github.com/requests/requests-kerberos
Risks
- Difficulties arise to maintain the common time across the systems.
SAML
Description
- SAML is abbreviated as Security Assertion Markup Language
- SAML implements a secure method of passing user authentications and authorizations between the identity provider and service providers using Extensible Markup Language (XML).
- SAML uses SAM, XML, HTTP and SOAP Protocols
- SAML enables Single-Sign On (SSO), where the users can log in once, and those same credentials can be reused to log into other service providers.
- Its is product of OASIS Security Services Technical Committee
- SAML Functions
- Principle
- The user seeking to verify its identify is called as principle
- Identity provider (IdP)
- Performs the authentication that the end user is who they say they are and sends that data to the service provider along with the user’s access rights for the service.
- Service provider (SP)
- Service which user wants to use, this service needs the authentication from the identity provider to grant authorization to the user. Bridge between Principle and IdP
- SAML Assertions
- Authentication assertion prove identification of the user and provide the time the user logged in and what method of authentication they used (i.e., Kerberos, 2 factor, etc.)
- Attribution assertion passes the SAML attributes to the service provider – SAML attributes are specific pieces of data that provide information about the user.
- Authorization decision assertion says if the user is authorized to use the service or if the identify provider denied their request due to a password failure or lack of rights to the service.
- Flow
- The user opens the service provider's web application, which uses an identity provider for authentication.
- The service provider (web application) responds with a SAML request to the identity provider.
- The identity provider parses the SAML request.
- The identity provider authenticates the user by prompting for a username and password or some other authentication factor. NOTE: The identity provider will skip this step if the user is already authenticated.
- The identity provider generates the SAML response and returns it to the service provider's web application which verifies it.
- If the verification succeeds, the web application grants the user access.
Architecture
![]() |
Fig: SAML Authentication Credits: https://labs.tadigital.com/index.php/2018/11/05/single-sign-on-with-saml-standards/ |
Implementation
A minimal but functional example implementation of both a Service Provider and an Identity Provider can be found in the examples/ directory of this flask-saml2 GitHub repository. To get the examples running, first clone the repository and install the dependencies:
$ git clone https://github.com/timheap/flask-saml2
$ cd flask-saml2
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install -e .
$ pip install -r tests/requirements.txt
Next, run the IdP and the SP in separate terminal windows:
Here the IdP server runs in http://localhost:8000/
$ cd flask-saml2
$ source venv/bin/activate
$ ./examples/idp.py
Here the SP server runs in http://localhost:9000/
$ cd flask-saml2
$ source venv/bin/activate
$ ./examples/sp.py
Finally, navigate to http://localhost:9000/ to access the Service Provider landing page.
- Risks
- The weakness in the SAML identity chain is the integrity of the users, hence suggested to use time sessions, HTTPS.
OAuth
- Description
- The OAuth 2.0 specification defines a delegation protocol that is useful for conveying authorization decisions across a network of web-enabled applications and APIs.
- OAuth is used in a wide variety of applications, including providing mechanisms for user authentication.
- OAuth 2.0 is not an authentication protocol, rather it is used for authorization.
- In simple terms, as a user its okay to uber to use your google profile or you can tell Facebook that it's OK for twitter to access your profile or post updates to your timeline without having to give twitter your Facebook password, well OAuth is the key reason to make it work.
- OAuth 2.0 uses JSON and HTTP
- OAuth does not provide authentic services, it is used to exclusively for authorization server, which makes it different from OpenID and SAML.
- Terms
- Resource Owner
- The entity that can grant protected resource access. Eg: Google User
- Resource server
- The host of the protected resource you will access. This would be typically an API provider to allow access to the protected resource such as contacts, photos, calendars and so on. Eg: Google Contacts
- Client Application
- The application making the request to the protected resource on behalf of the resource owner and with its authorization. Usually the request would be API call. Eg: Uber Server, where the user wants to share his/her Google Contacts.
- Authorization server
- Authorization server primarily provide two main features
- Access Tokens
- Authenticates the resource owner and issues access tokens. It interacts with the resource owner to get authorization to access a resource. Also gets the consent from the resource owner. Eg: This is when Google Authorization Server authenticates the Google User and then asks if he/she is willing to provide access to Uber to use the contacts or sometimes only for authentication.
- Authorization Code
- Endpoints provide OAuth clients the ability to communicate with the OAuth server or authorization server within a definition.
- An OAuth2 endpoint is a URL that clients call to request OAuth tokens (or auth codes).
- Clients will pass either an code or user credential to each endpoint to get the access token.
- This token is used later for accessing the service request from the resource server.
- There are different types of endpoint as well, few examples are:
- Token endpoint : used to get an access token or a refresh token
- Token Revocation Endpoint
- Dynamic Client Registration Endpoint
- Token Introspection Endpoint
- Eg: User Server, hits the endpoint to get the access token for accessing the Google Contacts of the user (resource server) with the Authorization code it received after the Resource Owner (user) accepts to share the Google contact details to Client(Uber).
- Scope
- The granular permissions for accessing the resource server.
- Eg: Read the Google Contacts, Write an email from gmail account, etc.
- Grant Types
- Each application is different, and their need of following the appropriate authorization protocol flow varies.
- Application Types
- client server web application – Flask, Django, PHP, and so on
- client side only application – Javascript based application
- native application – Similar to client side application, the application resides in the users desktop without connecting the server
- The OAuth 2.0 protocol defines 4 primary types of “grant types” used for obtaining the access token.
- Also one can define an extension mechanism for enabling additional grant types
- A grant type defines a way of how the authorization server will verify the request and issue the access token.
- Four Primary Types
- Authorization Code:
- Regular web applications can use the Authorization Code Flow, which is used to get an access token.
- After the resource owner (google user) authorized to access his/her data, the authorization code is sent to the client application(uber, usually through redirect url) from the authorization server (google authorization server)
- This authorization code is exchanged with the authorization server (google authorization server) from client application(uber) passing the client id and client secret.
- Access token is provided to client application (uber) after the authorization server authenticates.
- Implicit Grant:
- This grant type is used for client-server web application and doesn't have a server-side component. It skips the authorization code generation step and immediately the user authorises the access token itself is sent to the client application.
- Public clients that are unable to securely store client secrets can use the Implicit Flow to obtain an access token.
- Public clients could be client side only applications or native applications.
- As said, here the access token is immediately sent back to the application in form of URL itself after the resource owner grants access.
- Once the application (javascript) gets the access token, it can start making the API requests.
- Authorization Code is not required in this grant type. Also here the resource owner (google user) can see the access token.
- ROPG / Password Credentials
- Highly trusted applications can use the Resource Owner Password Grant (ROPG) Flow to request an access token
- Here the resource owner's (google user) username and password is shared to get access token
- Client Credential
- Machine-to-machine applications can use the Client Credentials Flow to authenticate and receive an access token
- Here the access token is used for accessing resource owned by the client (uber) rather the resource owner's(google user).
- It’s useful in cases where the client application communicates with the service provider directly and not on behalf of a resource owner.
- Flow
- Prerequisite: Client Application Registration
- OAuth requires the client application which will be making the API calls on behalf of the users should be registered first.
- While registering the Client ID and Client Secret will be provided.
- Eg: Uber has to register first with Google Authorization server, and get the its own Client ID and Client Secret. Later this will be used to authenticate itself with the Google's Authorization Server.
- First Step: The client application to ask for the authorization from the resource owner
- Second Step: The resource owner provides access, then an Authorization Grant credential is sent to the application
- Third Step: The client requests an authorization token using the Authorization Grant credential
- Forth Step: If the client application is authorized and authenticated, an access token is sent to the client
- Fifth Step: The client application sends the access token to the resource server to request a protected resource
- Sixth Step: The access token is validated and the protected resource is returned to the client application
- Architecture
![]() |
Fig: OAuth Framework Credits: https://github.com/DowlathBashaG/SpringBoot-Security-OAuth |
Implementation
Here we are not writing much source code rather using, from the existing module.
Step 1: Create OAuth Provider Server
Download from this URL : https://github.com/authlib/example-oauth2-server
pip install -r requirements.txt
export AUTHLIB_INSECURE_TRANSPORT=1
flask run
Step 1 Output : OAuth Provider Server is running

Fig: OAuth Provider Server is running, login page for the resource owner
Step 2: Lets Create a Client (Dummy), assume we have our own taxi service running like uber and we would want to get user's contacts from OAuth server, e.g. like Google OAuth Server.Click on the "Create Client"
Fill in the details, sample below.

Fig: Create Client Page Step 3: After "Submit" will get the Client ID and Client Secret, which will be needed for every other further communication with the OAuth Provider.

Fig: Details of the created client
Step 4: Lets try to access service provider to get the profile for the user demouser.
Open this URL in browser: http://127.0.0.1:5000/oauth/authorize?response_type=code&client_id=mmNDNHXISaWA5AKhRsbZCDT1&scope=profile
Below we could see from taxi we are logging to our OAuth Server, here after we confirm the next step will be proceed

Fig: Getting consent from user to allow client to use the resource
![]() |
| Fig: After successful consent from resource owner, redirect to client url |
![]() |
| Fig: Error from OAuth Provider ( Authorization Server ) when user rejects the consent |
- Risks
- There is no common format, as a result, each service requires its own implementation.
- In the process of user verification, sometimes you have to make additional requests to get minimal user information.
- When a token is stolen, an attacker gains access to the secure data for a while. Need of secure layer SSL/TLS.
OpenID Connect
Description
Adds a simple identity layer on top of the OAuth framework
Can be used by web-based, mobile, and Javascript clients to get information about authenticate sessions and end-users
- Uses a sign-in flow that permits user authentication and information access by a client app.
- Authorization server we get two tokens
- Access Token
- To get the resource, passing this access token
- ID Token (JWT)
- The user information is encoded via a secure JSON Web Token (JWT).
- JWT is used to prove that the sent dat was created by an authentic source.
- Refresh token [optional]
- As both access token and ID token comes with expiration date, would end up in requesting new tokens again and again.
- An OAuth Refresh Token is a credential artifact that OAuth can use to get a new access token without user interaction. This allows the Authorization Server to shorten the access token lifetime for security purposes without involving the user when the access token expires. You can request new access tokens until the refresh token is on the DenyList.
- It is important to keep the number of refresh tokens within a reasonable manageable limit to make sure that it’s easy to maintain those credentials safely and securely. Applications must store refresh tokens securely because they essentially allow a user to remain authenticated forever.
- This enables SSO, where the user can login from his gmail account to Uber, Myntra and so on.
- Here the OpenID is used in the Scope.
- Architecture
- Implementation
As like OAuth here will as well not write code rather use the available module: https://github.com/authlib/example-oidc-server
Step 1: Create client in the OAuth provider server, here we have autoapp now. We need add string "openid" in the scope of the profile.
![]() |
| Fig: Create Client as like OAuth, but with opening mentioned in the scope |
Step 2: Find the created client details.
Fig: Client Keys
Step 3: To get the consent open the below URL
Open the URL, passing the Client ID: http://127.0.0.1:5000/oauth/authorize?client_id=6jfALUQ8DdlK52OFqnDADloZ&scope=openid+profile&response_type=code&nonce=abc
![]() |
| Fig: Allowing the Client to authenticate using Authorization Server |
Step 4:
Redirection with happen passing the code. URL redirected: http://127.0.0.1:5050/?code=TGrTeFyjEpT6RNr83owcAGrW9HlE3EcNsNJJVxjpFR2wc0B2
Fig: Redirected to the Client page
Step 5:
Let's take Authorization code and get the access token and ID Token. ID tokens carry the following claim and these can be validated.
- Subject (sub) -- identifier for the authenticated user
- Issuer (iss) and audience (aud) -- specify the IdP that created the ID token and who it is intended for (the client_id)
- Timestamps - issue (iat) and expiration (exp) times
- Other attributes, such as authentication time, strength, a nonce and selected user details can also be included.
- The ID token claims are encoded in a simple JSON object like this one:
{
"sub" : "alice",
"iss" : "https://openid.c2id.com",
"aud" : "client-12345",
"iat" : 1311280970,
"exp" : 1311281970,
}
% curl -u "xE1aIpRUv18u7ZQA8fQYfIgU:JR9OSIKarIBVSp4TYelWMpCPO6c1GgOfaLvHXvQmtaK2a92p" -XPOST http://127.0.0.1:5000/oauth/token -F grant_type=authorization_code -F code=TGrTeFyjEpT6RNr83owcAGrW9HlE3EcNsNJJVxjpFR2wc0B2
{"access_token": "UTkAbkl1IgQdAAMPqBeYeg8b5amsYnZ9VkQ58STmb2", "expires_in": 864000, "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2F1dGhsaWIub3JnIiwiYXVkIjpbInhFMWFJcFJVdjE4dTdaUUE4ZlFZZklnVSJdLCJpYXQiOjE2NTgyODAzNzgsImV4cCI6MTY1ODI4Mzk3OCwiYXV0aF90aW1lIjoxNjU4MjgwMzA5LCJub25jZSI6ImFiYyIsImF0X2hhc2giOiI3UnVEVTV5ZWY0dzZnYldwazBOMGRBIiwic3ViIjoiMSIsIm5hbWUiOiJkZW1vdXNlciJ9.qN4Fife9TtXVTaF8_Gu_KyzAHjQITd5AoeoZ0Unp3hA", "scope": "openid profile", "token_type": "Bearer"}%
Step 6 :
Now from the access token lets get the user information. Here client know the identity of the user (resource owner).
% curl -H "Authorization: Bearer UTkAbkl1IgQdAAMPqBeYeg8b5amsYnZ9VkQ58STmb2" http://127.0.0.1:5000/oauth/userinfo
{
"name": "demouser",
"sub": "1"
}
Risks
- Requires HTTPS to be implemented as must
- OAuth Provider Server and Application Server storing access token, is vulnerable if not secured
Secure Development Best Practices
- Implement security early, as its important to take the required security measures during the initial stage of the development of the APIs.
- Ensure regulatory compliance concerns related to your business has been addressed as high priority. Eg: If credit cards/user's personal information cannot be shared without encryption or your apis needs to be access ed only on certain regions.
- Security only to the APIs would not be sufficient the entire stack needs to be secured.
- All data passed to the API needs to be validated for avoiding injection type attacks.
- All API needs to be protected with industry standard mechanisms, such as OAuth or OpenID Connect (at the time of writing this).
- Sensitive data needs to be encrypted when stored and during transmission. And these information should not be the part of a URI and should be sent in the HTTP header using a POST method.
- Transaction replay attacks need to be identified using tools that analyze API request traffic and usage patterns.
- Unexpected surges in API usage can be prevented by enforcing an arrest in spike traffic or using a per-app usage quota.
- Error objects should be well balanced and not contain information regarding the internal workings of the underlying backend system.
- Timestamps can be used to limit the period that a transaction is valid.
- Two-factor authentication can be used to confirm user authenticity.
- OAuth can be used to issue a short lived access token.
- App throttling is a great method for redirecting overflow traffic and preventing denial-of-service(DoS) attacks.
- The API gateway enforces which data is accessible and which APIs are available.
- Use the HTTP Header, X-HTTP-Method-Override when proxies only support GET and POST Methods.
- API and infrastructure can be evaluated for memory leaks and CPU drain using tools available on the market.
- Extensive API documentation and examples in multiple programming languages are valuable in decreasing development time and increasing user acceptance.
- Only asked data should be sent from server, such as filtered, paginated, sorted, data format json/xml.
- Digital Signatures reply on private/public key pairs, and the client provides its public key to the server
- Access Control Policies should be written to limit write access and access to sensitive data
- Role based authentication should be implemented to limit administrative access to resources
- Rate limit thresholds should be set to limit the number of requests from a specified source
- HTTPS should be used to encrypt the requests and responses between the client and the API
- Whitelist IP Address should allow access to the APIs can be limited by the known IP addresses
- Timestamps Values should be added to requests and the server should only accept requests that occur within a reasonable time period
- Input parameter validation need to be validated on the client and on the server before it is accepted and useable
Conclusion
Every security system comes with its own pros and cons. These security standards are just some hints to secure our system, but as said no system is perfect, everyday something new is occurring. We are learning from all our failures. The more secure we try the more complex and less usable it becomes. Though lets make the best balance between the security and usability.
Disclaimer: The above mentioned code is not for production, it is just for learning purpose.
References
- Getting Started with OAuth 2.0 by Ryan Boyd
- https://docs.oracle.com/cd/E19226-01/820-7627/bncbo/index.html
- https://www.ecanarys.com/Blogs/ArticleID/308/Token-Based-Authentication-for-Web-APIs
- https://gist.githubusercontent.com/funkatron/949952/raw/11c11ef47f8dab54722ee20dc33372b7417579a6/http_digest_example.php
- https://programmingsharing.com/digest-authentication-a-replacement-for-basic-authentication-cff8da82e2d1
- https://cheapsslsecurity.com/blog/understanding-the-role-of-certificate-authorities-in-pki/
- https://www.vaadata.com/blog/jwt-tokens-and-security-working-principles-and-use-cases/
- https://blog.openreplay.com/jwt-authentication-best-practices
- https://www.baeldung.com/spring-security-kerberos
- http://user.it.uu.se/~hsander/Courses/DistributedSystems/Reports/Kerberos.pdf
- https://www.onelogin.com/learn/saml
- https://www.varonis.com/blog/what-is-saml
- https://blog.ruanbekker.com/blog/2018/06/01/add-a-authentication-header-to-your-python-flask-app/
- https://www.geeksforgeeks.org/using-jwt-for-user-authentication-in-flask/
- https://github.com/LacunaSoftware/RestPkiSamples/tree/master/Python
- https://support.google.com/cloud/answer/6158849
- https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc
- https://github.com/authlib/example-oidc-server

















