I had recently reviewed / implemented custom
made OAuth for OSB. The below article takes you through the journey of becoming
secure by using Oauth and the different parameters used and steps to generate
valid payload which will pass OAuth security.
Why Oauth ?
I have tried to map it with the
different parameters I have used for creating the signature.
Excerpts from that article
OAuth uses digital signatures instead of sending the full credentials with each request.
Digital signatures help the recipient to verify that the content of the request
hasn’t changed in transit. To do that, the sender uses a mathematical algorithm
to calculate the signature of the request and includes it with the request.
In turn, the recipient
performs the same workflow to calculate the signature of the request and compares
it to the signature value provided. If the two match, the recipient can be
confident that the request has not been modified in transit. The confidence
level depends on the properties of the signature algorithm used. This mechanism
requires both sides to use the same signature algorithm and apply it in the
same manner.
A common way to sign digital content is using a hash algorithm. In general, hashing is the process of taking data (of any
size) and condensing it to a much smaller value (digest) in a fully
reproducible (one-way) manner. This means that using the same hash algorithm on
the same data will always produce the same smaller value. Unlike compression
which aims to preserve much of the original uncompressed data, hashing usually
does not allow going from the smaller value back to the original.
By itself, hashing does not verify the
identity of the sender, only data integrity. In order to allow the recipient to
verify that the request came from the claimed sender, the hash algorithm is
combined with a shared secret. If both sides agree on some shared secret known only to
them, they can add it to the content being hashed
As long as the shared secrets remains protected, anyone listening in on
the network will not be able to forge new requests as that will require using
the shared secret. They will however, be able to make the same sign request
over and over again. If the intercepted request provides access to sensitive
protected data, it can be a significant security risk.
To prevent compromised requests from
being used again (replayed), OAuth uses a nonce and timestamp. The term nonce
means ‘number used once’ and is a unique and usually random string that is
meant to uniquely identify each signed request. Since the nonce value is
included in the signature, it cannot be changed by an attacker without knowing
the shared secret.
Signature(geo-signature - HMAC-SHAxxx)
OAuth defines multiple signature methods
to sign and verify requests: We can use HMAC-SHA 1 ,256 ,512, HMAC
signature algorithm combined with the SHA hash method. Since these methods are
too complex, so it’s better not to write their own implementations, but instead
use trusted open source solutions available for most languages.
UserId
/Target sys/Source sys/Module/Service(geo-username , geo-target-system-name,
geo-source-system-name)
The user Id / Target
system/Source system is used to create
the signature.
These are not mandatory values , but
just added to give more information at the receiver side to do more processing
with the payload. This information can be encapsulated under a shared key, but
kept it separate so that we need to maintain less number of shared keys.
Based on requirement you can have more
service level information to be passed from the Consumer, like different levels
of maintaining the shared secret.It can be at a Department/Group level, then
modules in each group/dept /then at each service level.
How to get started
?
Pre-Requisites
to consume the services validated by Oauth.
1.
geo-key-id :-
Contact the end system and decide upon on a shared key Id and a hashed shared
key value
2.
This hashed
shared key value will be part of all the requests and should be confidential
between end system and consuming system.
3.
geo-username :-The
consuming system should get end system user ids created and need to pass this
value along with the request. This is mainly for user token generation at the
Atomic service level. The user token will be only be generated in case the user
has a valid account /permissions in end system.
4.
geo-target-system-name
:- Some more additional information on the type of grouped services like
Finance /HRMS/OTM etc application that the requester is trying to access.
5.
geo-source-system-name
:- Callers domain name , some more additional information to track the requester.
6.
geo-signature:-The
algorithm that needs to be used for hashing and creating signature is HMAC-SHAxxx.
There are open source utilities available which can be downloaded to sign the
payload using HMAC-SHAxxx algorithm.
7.
geo-nonce:-Nonce
value should be unique and needs to use a unique id generator to populate Nonce
value.
8.
geo-expires-by :- The timestamp
utility to compute the expiration time of the request.
How
to consume the services validated by Oauth.
1.
Identify values
for main parameters
·
geo-username
·
geo-target-system-name
·
geo-source-system-name
·
geo-key-id
·
geo-nonce
·
geo-expires-by
·
geo-signature
geo-key-id
The shared key id will be mapped to a
shared secret hashed value. Will need to fetch that hashed value and use it for
signature creation.
geo-expires-by
This will be a timestamp in
milli seconds created by using current timestamp in milli seconds
Code snippet ::
expiresBy =200
expiresByTime =
System.currentTimeMillis() + (expiresBy * 1000);
geo-nonce
Use a UID generator so that each nonce value is
unique.
geo-signature-algorithm
(FYI)
Use HMAC-SHAxxx algorithm utilities to generate the signature encrypted
in SHAxxx.
How
to create signatureParts
Signature
parts are used to create signature along with the shared Key
1.
For GET - QueryString
Sample businessParameters = transactionId=10&sequenceId=123&status=COMPLETED
Steps:
a.
Concatenate all the business parameters, geo-username,
geo-key-id, geo-source-system-name, geo-target-system-name, geo-expires-by, geo-nonce
Code snippet:
signatureParts =
?businessParameters+"&")+
"geo-username="+userName+
"&geo-key-id="+sharedKey+
"&geo-source-system-name="+source+
"&geo-target-system-name="+target+
"&geo-expires-by="+expiresByLStr
+"&geo-nonce="+nonce;
b.
Use a
HmacSignature Utility to create signature passing in the hashing algorithm
HashingAlgorithm.HMACSHA512, shared key and signature parts.
Code snippet:
signature = HmacSignatureUtil.getSignature(new
HmacSignatureRequest(HashingAlgorithm.512,
(String)secretKeys.get(sharedKey),
signatureParts)
);
c.
Once you create
the signature, always append the geo-signature as the last key /value to the
request.
d.
Once the URL is
created encode the URL using UTF-8 encoding.
Code snippet
encodedURL = serverUrl + "?" +
URLEncoder.encode(signatureParts + "&geo-signature=" + signature,
"UTF-8");
Output:
transactionId%3D10%26sequenceId%3D123%26deliveryStatus%3DCOMPLETED%26geo-username%3Dgeo%26geo-key-id%3DGeoSystem%26geo-source-system-name%3DINT%26geo-target-system-name%3DHRMS%26geo-expires-by%3D1366739410429%26geo-nonce%3Dbb123%26geo-signature%3D8S%2BIbF8DuIChek4ArARBYTIsEY5GIG%2BrbD5CCisw8oY%3D
e.
Final step is to
prepend the service URL to the encoded URL
Output:
https://geo.com:9111/GEOBus/v1/update?transactionId%3D10%26sequenceId%123%26status%3DCOMPLETED%26geo-username%3Dgeo%26geo-key-id%3DSystemX%26geo-source-system-name%3DINT%26geo-target-system-name%3DHRMS%26geo-expires-by%3D1366739410429%26geo-nonce%3Dbb123%26geo-signature%3D8S%2BIbF8DuIChek4ArARBYTIsEY5GIG%2BrbD5CCisw8oY%3D
2.
POST – HttpHeader
Steps:
a.
Concatenate all the business parameters, geo-username,
geo-key-id, geo-expires-by, geo-source-system-name, geo-target-system-name, geo-nonce.
Code snippet:
httpHeader =
"geo-username="+userName+
",geo-key-id="+sharedKey+
",geo-source-system-name="+source+
",geo-target-system-name="+target+
",geo-expires-by="+expiresByLStr+
",geo-nonce="+nonce;
signatureParts = httpHeader + businessParameters;
b.
Use a
HmacSignature Utility to create signature passing in the hashing algorithm
HashingAlgorithm.HMACSHAxxx, shared key and signature parts.
Code snippet:
signature = HmacSignatureUtil.getSignature(new
HmacSignatureRequest(HashingAlgorithm.HMACSHA512,
(String)secretKeys.get(sharedKey),
signatureParts)
);
c.
The request
header should start with “GEO-Auth:“ ,append the signature parts and then append the geo-signature as the last key
/value as the last parameter.
Code
snippet:
Request Header = "GEO-Auth: "+httpHeader+",geo-signature="+signature;
Output:
GEO-Auth: geo-username=geo,geo-key-id=GEOSystem, geo-source-system-name=INT,
geo-target-system-name=HRMS,geo-expires-by=1366736660196,geo-nonce=aa303,geo-signature=nlw2QyHfEmTgti8ZIZRX3rx8utJn3wY2xJsmOiB7Ds8=
That’s it; you can use the same
mechanism in consumer system and end system so that both are in sync.
Implementation
in OSB
For rest services, you will need to call
the service using java callouts in the OSB to recreate the signature and
validate it and for SOAP –OSB/SOA you can do it in Custom OWSM authentication
using OWSM policy.
You are all set to be secure J .
References:-
http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iii-security-architecture/