OAuth 2.0 has become very popular within the mobile development community mainly because it is simple to implement and the tokens are fairly compact. There are various implementation patterns to choose from and it is very important to choose the right one to make sure that the solution is secure. In this blog post I want to describe how mobile clients can get access tokens from Oracle Identity Cloud Service securely so that the identity service protected APIs can be consumed.
If you are not aware of OAuth 2.0 standard and various grant types like implicit or authorization code, I highly recommend to go through the core specification -
https://tools.ietf.org/html/rfc6749
One of the roles Oracle Identity Cloud Service plays is that of an OAuth 2.0 authorization server with support for 2 different application types -
I want to focus on the first client type in this post. So in Oracle Identity Cloud Service, the allowed grant types for a public client are “implicit” and “authorization code”.
In short, “implicit” grant type instructs an authorization server (AS) to return an access token to a client via user’s agent (over HTTPS) in a successful response to the authorize request. It is not secure and not recommended unless there is no way to use authorization code grant.
A public client will not have a secret as it can not be kept confidential and without a client secret, the authorization code flow would also be insecure as it becomes susceptible to the authorization code interception attack.
Authorization code interception attack happens when a “malicious” app uses the same uri scheme (handler) as an “authentic” app and receives authorization code from the authorization server ( which was only meant for the authentic app), it then calls the token endpoint to get a token back and gains access to user’s resources.
PKCE (proof of key code exchange) aims to resolve this and when implemented by both a client app and the authorization server ensures that the client which requested an authorization code is the same one which is exchanging it for a token.
In depth details about PKCE are available here - https://tools.ietf.org/html/rfc7636#section-7.3
PKCE is an OAuth 2.0 specification extension which adds a layer of security to the public client authorization code flow.
A public client generates a cryptographic highly random string called code_verifier and applies a code_challenge_method to compute code_challenge from code_verifier.
There are two supported challenge methods - "S256" and "plain"
code verifier correlates to code_challenge like this,
when challenge_method is “S256" -
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
when challenge_method is “plain”-
code_challenge=code_verifier
Then code_challenge and code_challenge_method are sent in the authorization request where as the code_verifier is sent in the token request. The authorization server(AS) follows the same formula to compute code_challenge value from code_verifier and compares it with the one sent in the authorization request. This provides enough assurance to the AS that a token request is coming from the same client which initiated the corresponding authorization request.
An important point to note is that salting is not required as code_verifier has high entropy (randomness).
We don't need to do anything additional to enable PKCE in IDCS, it's supported OOTB and as long as a public client sends PKCE parameters in the requests, IDCS will validate the PKCE parameters.
Login to IDCS admin console and create a new mobile application
Note the auto generated Client ID.
Make sure to check authorization code grant type in the allowed grant types section
Add additional scopes as required and save your configuration.
Any OAuth 2.0 library which supports PKCE can be used to develop your native app. I tested IDCS-PKCE support using an open source project available here - https://github.com/openid/AppAuth-iOS
Assuming you have a library and a sample app ready to connect to IDCS you will need 3 parameters at a minimum -
1. IDCS URL - IDCS url for your tenant.
2. Mobile client id - configured in step 1
3. App redirect uri - configured in step 1
a) Obtain authorization serve configuration.
b) Send authorization request via browser and process the response sent to the app’s handler(redirect uri).
c) Make a direct call to token endpoint and process the response.
https://IDCS_Host:IDCS_Port/oauth2/v1/authorize?client_id=a67adbbf841a4e94b1547a9447d7d95b&response_type=code&code_challenge=e5I_XqXj7eY34Msxr4S1wSuTWgyZh_BUBOyTggrzfjM&code_challenge_method=S256&state=797335&scope=openid&redirect_uri=com.oracle.sample:/oauth2callback
IDCS login page will be shown and user will be asked to authenticate -
Once authenticated, the native app will receive a response on a callback url-
com.oracle.sample:/oauth2callback?code=AQIDBAWK-lPwl8Kfg97qJUh3xr3CPeZrydyiv5_1cXgGmxNDRBrz_XkBVZ1TmjhFILSdPrHn-NCCaDlpp0QEdQPN4K58MTEgRU5DUllQVElPTl9LRVkxNCB7djF9NCA=&state=797335
2. Token Request - backend call , an additional parameter (code_verifier) is sent
https://IDCS_Host:IDCS_Port/oauth2/v1/token?code=AQIDBAUpMp5Xdn3ngvd-9EN18ZgsyV3eWJZ0W1gyoVyhD8Rfv3TleItzMDt0aXWBvYzRtym7zdkNsZRxCFlmlOqHVqHgMTEgRU5DUllQVElPTl9LRVkxNCB7djF9NCA=&grant_type=authorization_code&redirect_uri=com.oracle.sample:/oauth2callback&code_verifier=yKGnWqs~vAdQnOZ3b63Lqg5NSdcPYV8YThe6lar1v.hegJz3XVBB5ShZguxjg3&client_id=a67adbbf841a4e94b1547a9447d7d95b
Receives an access token if code_challenge was validated successfully otherwise returns an error.
Troubleshooting tip - IDCS server side diagnostics can be enabled to see incoming requests and troubleshoot further.
In this post I explained some basics like OAuth 2.0 mobile/public client and PKCE, how to configure a mobile client with Oracle Identity Cloud Service and how to test Oracle Identity Cloud Service support for PKCE.
Previous Post