Enterprise Integration Zone is brought to you in partnership with:

Nial is an engineer at Mulesoft. He writes blogs about use cases and technologies catered for by Mule. Nial is a DZone MVB and is not an employee of DZone and has posted 8 posts at DZone. You can read more from them at their website. View Full User Profile

SOA School: Architecting Watertight Security for the New Enterprise

06.23.2013
| 5291 views |
  • submit to reddit

is an ever-present concern for IT. It can be a rather daunting area when one considers all of the different possible dangers and the large variety of solutions to address them. But, the aim of Enterprise Security really just boils down to establishing and maintaining various levels of access control. Mule itself has always facilitated secure message processing both at the level of the transport, the service layer and of the message. Mule configurations can include all that Spring Security has to offer giving, for example, easy access to an LDAP server for authentication and authorisation. On top of that Mule  Applications can apply WS-Security thus facilitating, for example, the validation of  incoming SAML messages. But in this post, rather than delve into all the details of the very extensive security feature set , I would rather approach the subject by considering the primary concerns that drive the need for security in a Service Oriented Architecture, how the industry as a whole has addressed those concerns, the consequent emergence of popular technologies based on this Industrial best practice and finally, the implementation of these technologies in Mule.

Primary Concerns

Integrity

This is all about knowing who sent the Message. Securing our IT resources is a matter of deciding who gets access to them and of course, entering into the realms of Authorisation, to what extent each person or system should have access to them. A Message (which is also akin to a service invocation) must be determined to be authentic in order for the Server to accept it and process it. It’s authentic if the Server recognizes the Client as a valid user of the service. Now such recognition is usually achieved by some sort of Credentials accompanying the Message. However, verifying which Client sent the Message does not guarantee the Integrity of the Message: it may have been modified by some unfriendly third party during transit! Message Integrity, which includes Authentication, guarantees that the Message the Server received is exactly the one that was sent by the known Client.

Confidentiality

It is all very well for the Server to rest assured with the Integrity of a Message sent by a known Client, but the journey from Client to Server may have been witnessed by some unwelcome spies who got to see all of those potentially very private details inside the Message! Thus, it is necessary to hide those details from the point of delivery by the Client to the reception by the Server. An agreement is needed between the Client and Server in order to be able to hide the details of the Message in a way that allows only the Server to uncover them and vice versa.

Response of the Industry

Token based Credentials

The common practice of sending Username / Password pairs with Messages is not recommendable from two perspectives: 

  1. Passwords have a level of predictability whereas the ideal is to maximise on randomness or entropy. Username / Password pairs are a low entropy form of authentication. 
  2. Also, the maintenance of Passwords is a pain! If you need to change a password then you immediately affect all Clients that make use of that password. Until each of these has been reconfigured you have broken communication with them. As a consequence there is no way you can block access to one Client in particular without blocking all the Clients that use the same password. 

A much better alternative exists in the form of high entropy Tokens which represent a more secure form of Authentication and, as we’ll see, Authorisation. The idea is for the Server to issue tokens based on an initial authentication request with Username / Password credentials. From then on the Client only has to send the token, so the net result is a great reduction in Username / Password credentials going to and fro on the network.  Also, Tokens usually are issued with an expiration period and can even be revoked. Furthermore, because they are issued uniquely to each Client, when you choose to revoke a particular Token or if it expires, none of the other Clients will suffer any consequences. 

Digitial Signing

We humans sign all kinds of documents when it matters in the civil, legal and even personal transactions in which we partake. It is a mechanism we use to establish the authenticity of the transaction. The digitial world mimics this with its use of Digital Signatures. The idea is for the Client to produce a signature by using some algorithm and a secret code. The Server should apply the same algorithm with a secret code to produce its own signature and compare the incoming signature against this. If the two match, the Server has effectively completed Authentication by guaranteeing not only that this Message was sent by a known Client (only a known Client could have produced a recognisable signature), but that it has maintained its integrity because it was not modified by a third party while in transit. As an added benefit for when it matters with third party Clients, the mechanism also brings Non-repudiation into the equation because the Client cannot claim not to have sent the signed Message.

Public Key Cryptography

The age old practice of Cryptography has made a science of the art of hiding things! IT has adopted this science and can produce an Encryption of the message which is practically impossible to decrypt without a corresponding key to do so. It is as if the Client had the ability to lock a Message inside some imaginary box with a special key, hiding it from prying eyes, until the Server unlocks the box with its own special key. The Digital Signing discussed above produces signatures in this very way. Cryptography comes in two forms: Symmetric, when both Client and Server share the same key to encrypt and decrypt the Message; and Asymmetric, when the Server issues a public key to the Client allowing the Client to encrypt the Message, but keeps a private key which is the only one that can decrypt the Message: one key to lock the Message and another key to unlock it!

Defacto Standard Implementations

HTTPS

This is a rock solid standard protocol that implements at the level of the transport both Integrity and Condifentiality at the same time. Public Keys are emitted on Certificates which have been digitally signed by independant and trusted Certificate Authorities, thus guaranteeing that the public key was issued by the Server. Once the initial handshake has been completed by the exchange of Messages using public and private keys, the communication switches to the more efficient symmetric form using a shared key generated just for the duration of the communication, all of which occurs transparently.

OAuth2

This emerging standard governs the world of Authorisation using Tokens. I won´t go into all of the complexities of the complete OAuth2 dance here, but I can recommend OAuth2 as a valid way to secure our Enterprise and which scales well to meet the needs of the SAAS oriented New Enterprise. To that end there are two types of Clients we should cater for in our Secured SOA Architecture:

  1. The in-house Applications which are typically exposed to end-users. These should provide the username and password of the end-user and request a token on the strength of those. The process also affords us with the luxury of Single-Sign-On, because the token can be stored by the browser as a cookie based on the domain name of the organisation. All other web applcations can access the cookie. This is what Google are doing with their SSO for each of their cloud apps like Gmail, Calendar, Documents, etc.
  2. Third-party Applications providing services to our users but to which we’d like to grant limited access to our systems. We don’t want those Applications getting their hands on our end-users’ credentials, so we can force them through the typical OAuth2 dance which is what we all see so often nowadays when websites invite us to sign in using our Google, Facebook or Twitter accounts.

Solution in Mule

Let’s implement a RESTful webservice in Mule which will expose a list of Products in our online shop to various Client Applications. We will configure the access control so that certain operations are available only to certain Clients. We could even apply more specific access control by considering the roles of the users of these Applications: Admin for complete access and Standard for read-only access. 

HTTPS Inbound Endpoint

The https inbound endpoint on our API needs to use a connector with a reference to a keystore. A keystore is a repository of public key certificates together with their private keys. These certificates are sent to the Client upon the first HTTPS request. The certificate contains the public key and identity of the server and is digitally signed either by the same server (self-signed certificate) or by an independent Certificate Authority. You can create your own self-signed certificate for development purposes using the JDK keytool utility. The keystore needs a password both for the keystore and for the private key.

<https:connector name="httpsConnector" cookieSpec="netscape" validateConnections="true" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" doc:name="HTTP\HTTPS">
    <https:tls-key-store path="src/main/resources/keystore.jks" keyPassword="mule123" storePassword="mule123"/>
</https:connector>

Anypoint Secure Token Service

Mule can now act as an OAuth2 Provider, issuing tokens to registered Clients, applying expiration periods to these tokens, associating them to User roles and fine-grained access control known in the OAuth world as scopes. Refresh tokens can also be issued and tokens can be invalidated. Mule can of course subsequently validate incoming tokens against expiration periods, roles and scopes and thus grant or deny access to the Flows in the Application.

  <oauth2-provider:config 
		host="0.0.0.0" 
		port="8081" 
		name="oauth2-provider" 
		accessTokenEndpointPath="access-token" 
		scopes="READ WRITE" 
		resourceOwnerSecurityProvider-ref="security-provider" 
		supportedGrantTypes="IMPLICIT RESOURCE_OWNER_PASSWORD_CREDENTIALS" 
		tokenTtlSeconds="300" 
		enableRefreshToken="true" 
		authorizationEndpointPath="authorization-code"
		loginPage="login.html"
		connector-ref="httpsConnector" 
		doc:name="OAuth provider module">
		<oauth2-provider:clients>
			<oauth2-provider:client clientId="customer-web-app" type="PUBLIC" clientName="Web UI" description="Javascript web UI">
				<oauth2-provider:authorized-grant-types>
					<oauth2-provider:authorized-grant-type>PASSWORD</oauth2-provider:authorized-grant-type>
				</oauth2-provider:authorized-grant-types>
				<oauth2-provider:scopes>
					<oauth2-provider:scope>READ</oauth2-provider:scope>
				</oauth2-provider:scopes>
			</oauth2-provider:client>
			<oauth2-provider:client clientId="admin-web-app" type="PUBLIC" clientName="Private Web UI" description="Javascript web UI">
				<oauth2-provider:authorized-grant-types>
					<oauth2-provider:authorized-grant-type>PASSWORD</oauth2-provider:authorized-grant-type>
					<oauth2-provider:authorized-grant-type>REFRESH_TOKEN</oauth2-provider:authorized-grant-type>
				</oauth2-provider:authorized-grant-types>
				<oauth2-provider:scopes>
					<oauth2-provider:scope>READ</oauth2-provider:scope>
					<oauth2-provider:scope>WRITE</oauth2-provider:scope>
				</oauth2-provider:scopes>
			</oauth2-provider:client>
		</oauth2-provider:clients>
	</oauth2-provider:config>

The above configuration registers 2 different clients for our API:

  • Web UI: a public web application providing read-only access to the protected Product listing.
  • Private Web UI: an internal admin app which allows Administrators to add new Products.

Note how the two web applications are considered in-house applications as described above and as such may exchange User Credentials directly for a Token. For example,


GET https://localhost:8081/access-token?grant_type=password&client_id=admin-web-app&username=nialdarbey&password=hello123&scope=READ%20WRITE 
This would give a Response something like:
{
  "scope":"READ WRITE",
  "expires_in":299,
  "token_type":"bearer",
  "access_token":"l8bFMEC9PA7NcpmHeTYS43Wl96_Y6LuIOhGci2zMJf0Qso9llgRLkgQjarMzUhvQz8vGVHmazrZ2C-Gjo20khg"
}

The request includes both scopes READ and WRITE. These appear in the requestable scopes for that particular client. Scopes represent broad levels of access to the Mule flows. The provided access token must be sent in with each request and can be validated by Mule to ensure it hasn’t expired or been revoked and that it has the scopes that correspond to a particular flow. In the following example we only allow requests that have WRITE scope.
<flow name="createProduct" doc:name="createProduct">
    <oauth2-provider:validate scopes="WRITE" config-ref="oauth2-provider" doc:name="Validate WRITE scope" />
    <logger level="INFO" doc:name="Logger"/>
    <jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="select" queryTimeout="-1" connector-ref="Database" doc:name="Select Manufacturers">
        <jdbc-ee:query key="insert" value="insert into products (name, description) values (#[payload.name], #[payload.description])"/>
    </jdbc-ee:outbound-endpoint>
</flow>
More fine grained control can also be applied by comparing the role of the user for whom the token was issued with the allowed roles for the flow. The validate filter has a resourceOwnerRoles attribute to specify these. (The granularity of access control can be in either the grant or the role).
<oauth2-provider:validate resourceOwnerRoles="Administrator" scopes="WRITE" config-ref="oauth2-provider" doc:name="Validate WRITE scope" />
As we venture into the world of the New Enterprise, no doubt we may have to cater for applications belonging to partners. Imagine we were to expose access to our service to a Mobile Application. We need only register this new client in our OAuth2 Provider configuration. Note how the grant type for this configuration is TOKEN which corresponds to the IMPLICIT type according to the OAuth2 specification. This will result in the full dance that we all have experienced when Websites allow us to sign in using our Google, Facebook or Twitter accounts.
<oauth2-provider:client clientId="partner-smartphone-app" type="PUBLIC" clientName="Smartphone App" description="Smartphone app produced by partner">
    <oauth2-provider:redirect-uris>
        <oauth2-provider:redirect-uri>http://localhost*</oauth2-provider:redirect-uri>
    </oauth2-provider:redirect-uris>
    <oauth2-provider:authorized-grant-types>
        <oauth2-provider:authorized-grant-type>TOKEN</oauth2-provider:authorized-grant-type>
    </oauth2-provider:authorized-grant-types>
    <oauth2-provider:scopes>
        <oauth2-provider:scope>READ</oauth2-provider:scope>
    </oauth2-provider:scopes>
</oauth2-provider:client>

Finally

Anypoint Enterprise Security also allows us to explicitly sign Messages and verify incoming signatures and encrypt Messages with 3 different strategies and 20 different algorithms as well as to decrypt incoming Messages. There may be cases when you have to explicitly sign or encypt Messages you send out to third parties or likewise decrypt and verify signatures from third parties. For the purpose of the Clients over which we have complete control in our architecture, it is sufficient to use HTTPS, but for those sideline cases you have all the power of the best that the Industry has to offer in the extremely easy configurations that Mule demands of you! You can download the above example Application here.

Published at DZone with permission of Nial Darbey, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)