05 Spring Microservices Security Oauth2
05 Spring Microservices Security Oauth2
Microservices are the components that can be self executable and independently
deployable may be in separate vm per each micro service or in cloud
infrastructure. Microservices may offer APIs or web applications. Our sample
application, NovelHealthCare, flybypoints etc.
HTTP transfers data in plain text, but data transfer over the Internet in plain text is
not secure.We definitely don't want to compromise user data, so we will provide
the most secure way to access our web application. Therefore, we need to encrypt
the information that is exchanged between the end user and our application. We'll
use Secure Socket Layer (SSL) or Transport Security Layer (TSL) to encrypt
the data.
4.The end user's browser receives this certificate and sends it to a trusted
Certificate Authority (CA) for verification.
5.Once the certificate gets verified all the way to the root CA, an encrypted
communication is established between the end user's browser and the application
hosting server.
Securing Microservices
Note: Although SSL ensures security in terms of encryption and web application
authenticity, it does not safeguard against phishing and other attacks. Professional
hackers can decrypt information sent using HTTPS.
Now, after going over the basics of SSL, let's implement it for our sample project.
We don't need to implement SSL for all microservices. All microservices will be
accessed using our proxy or edge server; Zuul-server by the external environment,
except our new microservice, security-service, which we will introduce in this
chapter for authentication and authorization.
First, we'll set up SSL in edge server. We need to have the keystore that is
required for enabling SSL in embedded Tomcat. We'll use the self-signed
certificate for now. We'll use Java keytool to generate the keystore using the
following command. We can use any other tool also:
It asks for information such as name, address details, organization, and so on (see
the following screenshot):
Securing Microservices
1) Use –ext to define Subject Alternative Names (SAN). we can also use IP (for
example, san=ip:190.19.0.11). Earlier, use of the hostname of the machine, where
application deployment takes place was being used as most common name (CN). It
prevents the java.security.cert.CertificateException for No name matching
localhost found.
2) we can use a browser or OpenSSL to download the certificate. Add the newly
generated certificate to the cacerts keystore located at jre/lib/security/cacerts
inside active JDK/JRE home directory by using the keytool –importcert command.
Note that changeit is the default password for the cacerts keystore. Run the
following command:
Note:
Self-signed certificates can be used only for development and testing purposes.
The use of these certificates in a production environment does not provide the
required security. Always use the certificates provided and signed by trusted
signing authorities in production environments. Store your private keys safely.
Note:
1) The key store file can be stored in the preceding class path in Tomcat version
7.0.66+ and 8.0.28+. For older versions, we can use the path of the key store file
for the server:ssl:key-store value.
OAuth 2.0
Securing Microservices
The Internet Engineering Task Force (IETF) governs the standards and
specifications of OAuth. OAuth 1.0a was the most recent version before OAuth 2.0
that was having a fix for session-fixation security flaw in the OAuth 1.0. OAuth
1.0 and 1.0a were very different from OAuth 2.0. OAuth 1.0 relies on security
certificates and channel binding. OAuth 2.0 does not support security
certification and channel binding. It works completely on Transport Security Layer
(TSL). Therefore, OAuth 2.0 does not provide backward compatibility.
Use Cases
3) Or, the opposite of the previous point can be true: we enable other applications
to access the end user's data.
Before understand the OAuth 2.0 specifications in a concise manner. Let's first see
how signing in using Twitter works.
1) The user visits the Quora home page. It shows various login options. We'll
explore the process of the Continue with Twitter link.
2) When the user clicks on the Continue with Twitter link, Quora opens a new
window (in Chrome) that redirects the user to the www.twitter.com application.
During this process few web applications redirect the user to the same opened
tab/window.
4) If the user has not authorized the Quora application to use their data earlier,
Twitter asks for the user's permission to authorize Quora to access the user's
information. If the user has already authorized Quora, then this step is skipped.
5) After proper authentication, Twitter redirects the user to Quora's redirect URI
with an authentication code.
6) Quora sends the client ID, client secret token, and authentication code (sent by
Twitter in step 5) to Twitter when Quora redirect URI entered in the browser.
Securing Microservices
7) After validating these parameters, Twitter sends the access token to Quora.
9) Quora may use this access token to retrieve user information from Quora.
Here we must be wondering how Twitter got Quora's redirect URI, client ID, and
secret token. Quora works as a client application and Twitter as an
authorization server. Quora, as a client, registered on Twitter by using Twitter's
OAuth implementation to use resource owner (end user) information. Quora
provides a redirect URI at the time of registration. Twitter provides the client ID
and secret token to Quora. It works this way. In OAuth 2.0, user information is
known as user resources. Twitter provides a resource server and an authorization
server.
1) Resource owner
2) Resource server
3) Client
4) Authorization server
Resource owner
For the Quora sign in using Twitter example, the Twitter user was the resource
owner. The resource owner is an entity that owns the protected resources
(for example user handle, tweets and so on) that are to be shared. This entity can
be an application or a person. We call this entity the resource owner because
it can only grant access to its resources. Specification also defines, when
resource owner is a person, it is referred to as an end user.
Resource server
The resource server hosts the protected resources. It should be capable of serving
the access requests to these resources using access tokens. For the Quora sign in
Securing Microservices
using Twitter example, Twitter is the resource server.
Client
For the Quora sign in using Twitter example, Quora is the client. The client
is the application that makes access requests for protected resources to the
resource server on behalf of the resource owner.
Authorization server
The authorization server provides different tokens to the client application, such as
access tokens or refresh tokens, only after the resource owner authenticates
themselves.
OAuth 2.0 does not provide any specifications for interactions between the
resource server and the authorization server. Therefore, the authorization
server and resource server can be on the same server, or can be on a
separate one.A single authorization server can also be used to issue access
tokens for multiple resource servers.
The client that communicates with the authorization server to obtain the access
key for a resource should first be registered with the authorization server. The
OAuth 2.0 specification does not specify the way a client registers with the
authorization server. Registration does not require direct communication
between the client and the authorization server. Registration can be done using
self-issued or third-party-issued assertions. The authorization server obtains the
required client properties using one of these assertions. Let's see what the client
properties are:
Client type
Any other information required by the authorization server, for example client
name, description, logo image, contact details, acceptance of legal terms and
conditions, and so on.
Client types
There are two types of client described by the specification, based on their ability
to maintain the confidentiality of client credentials: confidential and public.
Client credentials are secret tokens issued by the authorization server to clients in
Securing Microservices
order to communicate with them.
This is a client application that keeps passwords and other credentials securely or
maintains them confidentially. In the Quora sign in using Twitter example, the
Quora app server is secure and has restricted access implementation. Therefore, it
is of the confidential client type. Only the Quora app administrator has access to
client credentials.
These are client applications that do not keep passwords and other credentials
securely or maintain them confidentially. Any native app on mobile or desktop, or
an app that runs on browser, are perfect examples of the public client type, as
these keep client credentials embedded inside them. Hackers can crack these apps
and the client credentials can be revealed.
Based on the OAuth 2.0 client types, a client can have the following profiles:
Web application
Native application
Web application
The Quora web application used in the Quora sign in using Twitter example is a
perfect example of an OAuth 2.0 web application client profile. Quora is a
confidential client running on a web server. The resource owner (end user)
accesses the Quora application (OAuth 2.0 client) on the browser (user agent)
using a HTML user interface on his device (desktop/tablet/cell phone). The
resource owner cannot access the client (Quora OAuth 2.0 client) credentials and
access tokens, as these are stored on the web server. We can see this behavior in
the diagram of the OAuth 2.0 sample flow. See steps 6 to 8 in the following figure:
Securing Microservices
User agent-based applications are of the public client type. Here, though, the
application resides in the web server, but the resource owner downloads it on the
user agent (for example, a web browser) and then executes the application. Here,
the downloaded application that resides in the user agent on the resource owner's
device communicates with the authorization server. The resource owner can
access the client credentials and access tokens. A gaming application is a good
example of such an application profile.
Securing Microservices
Native application
Native applications are similar to user agent-based applications, except these are
installed on the resource owner's device and execute natively, instead of being
downloaded from the web server, and then executes inside the user agent. Many
native clients (mobile apps) we download on our mobile are of the native
application type. Here, the platform makes sure that other application on the
device do not access the credentials and access tokens of other applications. In
addition, native applications should not share client credentials and OAuth tokens
with servers that communicate with native applications.
Client identifier
The OAuth 2.0 specification does not specify the size of the client
identifier. The authorization server can set the size, and it should document the
size of the client identifier it issues.
Client authentication
The authorization server should authenticate the client based on their client type.
The authorization server should determine the authentication method that suits
and meets security requirements. It should only use one authentication method in
each request.
Securing Microservices
Typically, the authorization server uses a set of client credentials, such as the
client password and some key tokens, to authenticate confidential clients.
The authorization server may establish a client authentication method with public
clients. However, it must not rely on this authentication method to identify the
client, for security reasons.
A client possessing a client password can use basic HTTP authentication. OAuth
2.0 does not recommend sending client credentials in the request body. It
recommends using TLS and brute force attack protection on endpoints required for
authentication.
An endpoint is nothing but a URI we use for REST or web components such as
Servlet or JSP. OAuth 2.0 defines three types of endpoint. Two are authorization
server endpoints and one is a client endpoint:
Authorization endpoint
This endpoint is responsible for verifying the identity of the resource owner and,
once verified, obtaining the authorization grant.
The authorization server require TLS for the authorization endpoint. The endpoint
URI must not include the fragment component. The authorization endpoint must
support the HTTP GET method.
How the client will receive the authorization endpoint URI. Normally,
documentation contains the authorization endpoint URI, or the client obtains it
at the time of registration.
Token endpoint
The client calls the token endpoint to receive the access token by sending the
authorization grant or refresh token. The token endpoint is used by all
Securing Microservices
authorization grants except an implicit grant.
Like the authorization endpoint, the token endpoint also requires TLS. The client
must use the HTTP POST method to make the request to the token endpoint. Like
the authorization endpoint, the specification does not specify how the client will
receive the token endpoint URI.
Redirection endpoint
The authorization server redirects the resource owner's user agent (for example, a
web browser) back to the client using the redirection endpoint, once the
authorization endpoint's interactions are completed between the resource owner
and the authorization server. The client provides the redirection endpoint at the
time of registration. The redirection endpoint must be an absolute URI and not
contain a fragment component.
The client requests an access token from the authorization server, based on the
obtained authorization from the resource owner. The resource owner gives
authorization in the form of an authorization grant. OAuth 2.0 defines four types of
Securing Microservices
authorization grant:
Implicit grant
When a client application requires access to a protected resource, the client sends a
request to an authorization server.
The authorization server validates the request and provides an access token.
This access token is validated for every client-to-server request. The request and
response sent back and forth depends on the grant type.
server.port=9090
security.user.name=user
security.user.password=password
security.user.role= ADMIN
security.oauth2.client.clientId=trustedclient
security.oauth2.client.clientSecret=trustedclient123
security.oauth2.client.authorized-grant-
types:authorization_code,refresh_token,password,client_credentials
security.oauth2.client.scope=apiAccess
4. Create an endpoint called /user in any controller or Application.java file to list the
logged in user details by supplying the access token
Securing Microservices
@EnableResourceServer
@EnableAuthorizationServer
@RestController
@SpringBootApplication
public class UserRegSystemApplication {
public static void main(String[] args) {
SpringApplication.run(UserRegSystemApplication.class, args);
}
@RequestMapping("/user")
public Principal user(Principal user) {
return user;
}
}
Then we will see the token generated by authorization server as shown below
Now by supplying this token, we can get the logged in user details as shown below.
Here in this grant_type client_id it self is the user
Securing Microservices
In general when any user is logged in, we have to generate an access token for that
user and identify the user on the token, but this can not achieved using grant_type:
client_credentials. Hence we go for grant_type: password.
grant_type: password
In grant_type: password, we have to supply the user credentials who wants to logged
in to the application in the defined scope, on behalf of this user, client_id user will
authenticates this user and provide the generated access_token to the user. Hence we
have to supply client_id user details in header and the user credentials who wants to
logged in to application, in the request body as shown below:
Header:
Securing Microservices
Body
Now by supplying this token, we can get the logged in user details as shown below.
Securing Microservices
grant_type: refresh_token
Some times, when the logged in user is doing any operations in the application, an
access token might expires, Then we need to again get a new access token with an
increased time limit. To refresh the token use the greant_type as refresh_token as
shown below.
Header:
Always include an header with the client_id and client_secret as shown below
Securing Microservices
Body:
Supply the grant_type and refresh token that we got when we logged in to the
application first time as shown below: