Guided Approach Towards Implementing Client Initiated Back-channel Authentication
Episode 05 — New Approach towards CIBA
Time has answers; Answers everything and everyone. It answers your pains. It answers your failures. It answers your falls. It answers your tears that only your pillow knows of. Time has an answer for the broken YOU. Time has an answer for people who broke you. Time answers your will and wit. Time answers your appetite for victory. Time answers your evolution. Time assist in evolution.
Time evolves — Time allows everything to evolve.
We had several concerns, ended up in architecture for POC of CIBA [Episode 03]. Our main concern was the load on IS[Identity Server] because of polling and have a minimized patch over the existing architecture of WSO2-IS.With that particular Proxy approach, we implemented a POC and had a demonstration as well [Episode 04].
But discussions and design reviews improve our thoughts and made us realize that it would be better if we stay as a monolithic architecture so that we can render more secured feature and we could satisfy the deployment pattern of WSO2-IS.
Though it is painful to drop the architecture approach V1.0 as described in Episode 03 , the evolution of architecture makes working more interesting and we had a drift: towards architecture approach V2.0.
Why this Approach??
It is to adhere to the standard deployment pattern of the WSO2 -IS.
The Approach
While the features and functionality remain the same as in V1.0, approach 2.0 pulls Ciba proxy as a component inside IS. Hence we need to partition proxy to several pieces and add them to the existing core architecture of WSO2-IS.
Hence, we have partitioned the Proxy into two main components
- CIBA Endpoint [Top left corner of Identity Server]
- CIBA Component [The violet box]
The Flow
Since the architecture had a drift, the flow of the feature also faced some changes. Though the high-level concept of decoupled authentication and polling mechanism for tokens remains unchanged we are forced to do adapt the changes that architecture has brought. But still, the flow will follow the preaching of the specifications.
The Di-section of FLOW
It would be good to consider the flow mentioned in Fig.2. into three phases.
- Phase — 1 [2 - 6]
- Phase — 2 [7 -13]
- Phase — 3 [#1 - #4]
Phase — 1 [ Authentication Requests & Responses]
- EndPoint receives the CIBA AuthenticationRequest [Step 2 of Fig.2.]
- Consumes("application/x-www-form-urlencoded")
- Produces("application/json")
- The request has to be made to https://localhost:9443/oauth2/ciba endpoint. Find here the sample PostMan Request Collection .
- Sample Request :
{
"name": "https://localhost:9443/oauth2/ciba",
"request": {
"method": "POST",
"header": [
{"key": "Content-Type",
"name": "Content-Type",
"value": "application/x-www-form-urlencoded"
}
],
"body": {
"mode": "urlencoded",
"urlencoded": [
{
"key": "request",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJaenhtRHFxSzhZWWZqdGxPaDl2dzg1cW5OVm9hIiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6OTQ0My9vYXV0aDIvY2liYSIsInNjb3BlIjoib3BlbmlkIiwiYmluZGluZ19tZXNzYWdlIjoiMTkwODE5OTUiLCJsb2dpbl9oaW50Ijoidml2ZWsiLCJpYXQiOjE1NzE2MzExODUsImV4cCI6MTU3MTY0MDM3OSwibmJmIjoxNTcxNjMxMTg1LCJqdGkiOiI5ZmY4NDViOS0yMGJmLTQwMzMtOWVkMy0zY2NjNjNmNTIwNGMiLCJ0cmFuc2FjdGlvbl9jb250ZXh0IjoiUnN4eHgueHgifQ.50Lv_27ptjCgDvsEQ-bFhnAjJ6k77B4jcttLvnTnonc"
}
]
}
2. Validation Process [Step 3 of Fig.2.]
- isValidClient — This is to check whether the client who is initiating the request exists [registered] in Identity Server.
- isValidUser — This is to check whether the user denoted by hints exists [registered] in identity Server.
- isValidUserCode — This is to verify the usercode against the user for whom the authentication request is made [WSO2 IS hasn’t planned to provide the support for this at the first release. But given as an extensible point where a developer can implement logic accordingly]
- isValidRequest— This is to check for the presence of mandatory parameters and whether values given are proper and valid.
3. Persist required parameters [Step 3 of Fig.2.]
Here parameters required for the functioning of the flow will be stored.
4. Create auth_req_id
- auth_req_id will be a signed JWT
auth_req_id => eyJ4NXQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJraWQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJaenhtRHFxSzhZWWZqdGxPaDl2dzg1cW5OVm9hIiwibmJmIjoxNTcxNjM2MDY1MjMyLCJ0cmFuc2FjdGlvbl9jb250ZXh0IjoiUnN4eHgueHgiLCJzY29wZSI6Im9wZW5pZCIsImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0M1wvb2F1dGgyXC9jaWJhIiwiYmluZGluZ19tZXNzYWdlIjoiMTkwODE5OTUiLCJleHAiOjE1NzE2Mzk2NjMyMzIsInVzZXJfaGludCI6InZpdmVrIiwiaWF0IjoxNTcxNjM2MDYzMjMyLCJqdGkiOiIwM2U3ODBiMy00NGZhLTQyMjYtOWE0OS04OGZiZjJkNjMxNTQifQ.VqDM8Y_sxSbUu0NiRupR0OznNKm4jgNCel5WidDeB-GPvFQoX_jgu9Oh6tvbvvQfMwIzDa3-nUTKW67cftzoYFwo3e8Knz-NAfGZMOU-CUAyVq1EsLDXXaJ6ykkq_vt3Q9iIg6FJ8PRFEcWPOG3VO-ASGT3bmKHWieCDtUFZec2b0gFvQq7lmOcJEcv98F0Un8xaFtQgTn_fdTK_KXXavHIWrPLiapu2-rjEvD3I8KUJKcHbtMBtruY56P5DwjssEHPamKu_bPO7Cw6vlLqz1IVHBmoONmAi8DZrCZ8-4H8F8ZVZ5B19xuZ6uxk0G3bLZBJxiB2q-AhtI_1XNPBGqQ
5. Return Authentication Response [Step 5 of Fig.2.]
HTTP/1.1 200 OK
Content-Type: application/json{
"expiresIn":3600,
"interval":2,
"auth_req_id":"eyJ4NXQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJraWQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJaenhtRHFxSzhZWWZqdGxPaDl2dzg1cW5OVm9hIiwibmJmIjoxNTcxNjM2MDY1MjMyLCJ0cmFuc2FjdGlvbl9jb250ZXh0IjoiUnN4eHgueHgiLCJzY29wZSI6Im9wZW5pZCIsImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0M1wvb2F1dGgyXC9jaWJhIiwiYmluZGluZ19tZXNzYWdlIjoiMTkwODE5OTUiLCJleHAiOjE1NzE2Mzk2NjMyMzIsInVzZXJfaGludCI6InZpdmVrIiwiaWF0IjoxNTcxNjM2MDYzMjMyLCJqdGkiOiIwM2U3ODBiMy00NGZhLTQyMjYtOWE0OS04OGZiZjJkNjMxNTQifQ.VqDM8Y_sxSbUu0NiRupR0OznNKm4jgNCel5WidDeB-GPvFQoX_jgu9Oh6tvbvvQfMwIzDa3-nUTKW67cftzoYFwo3e8Knz-NAfGZMOU-CUAyVq1EsLDXXaJ6ykkq_vt3Q9iIg6FJ8PRFEcWPOG3VO-ASGT3bmKHWieCDtUFZec2b0gFvQq7lmOcJEcv98F0Un8xaFtQgTn_fdTK_KXXavHIWrPLiapu2-rjEvD3I8KUJKcHbtMBtruY56P5DwjssEHPamKu_bPO7Cw6vlLqz1IVHBmoONmAi8DZrCZ8-4H8F8ZVZ5B19xuZ6uxk0G3bLZBJxiB2q-AhtI_1XNPBGqQ"
}
- Error Response[if parameters missing]:
HTTP/1.1 400 Bad Request
Content-Type: application/json{
"error" : "invalid_request"
"error_description" : "parameters_missing"
}
- Error Response [if unauthorized client]
HTTP/1.1 401 UnAuthorized
Content-Type: application/json{
"error" : "unauthorized"
"error_description" : "unknown_client"
}
6. Fire Authorization Request [Step 6 of Fig.2.]
- This will be an async HTTP call to the authorize endpoint of WSO2 -IS with required parameters.
https://localhost:9443/oauth2/authorize?response_type=ciba&redirect_uri=http://localhost/CibaResponse&client_id=ZzxmDqqK8YYfjtlOh9vw85qnNVoa&user=vivek
Note :
* We will discuss in detail about the requests, responses, validations, parameters involved in a later episode.
* And also we will sooner discuss about the components,packages and the classes and the methods involved in the flow.
Phase — 2 [ Authentication & Authorization]
- This phase is almost controlled by the authentication framework, local/outbound authenticators of WSO2 -IS
- Inbound-OAuth-Auth component receives the authorization request.
- Inbound-OAuth-Auth triggers the Authentication Framework to continue authorization process [step 7 in Fig.2.].
- Authenticators and Authentication framework take care of multistep authentication [steps 8–11 in Fig.2.].
- Once properly authenticated & authorized by giving the consent, the control is again given to Ciba Component [step 12 in Fig.2.].
- Ciba Component update Authentication/Authorization responses in the storage [step 13 in Fig.2.].
Phase — 3 [Token Request, Token Response & Polling]
In this last phase of the flow, clients will be polling for a token at the token endpoint of WSO2-IS.
- Token Request has to be made towards the Token endpoint of WSO2-IS [Step #1 of Fig.2.]
https://localhost:9443/oauth2/token
- Sample TokenRequest
{
"name": "https://localhost:9443/oauth2/token",
"request": {
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "ZzxmDqqK8YYfjtlOh9vw85qnNVoa",
"type": "string"
},
{
"key": "password",
"value": "ZkaeWpAW3RztIm4hKAgmf251LdAa",
"type": "string"
}
]
},
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/x-www-form-urlencoded"
}
],
"body": {
"mode": "urlencoded",
"urlencoded": [
{
"key": "grant_type",
"value": "urn:openid:params:grant-type:ciba",
"type": "text"
},
{
"key": "auth_req_id",
"value": "eyJ4NXQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJraWQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJaenhtRHFxSzhZWWZqdGxPaDl2dzg1cW5OVm9hIiwibmJmIjoxNTcxNjM2MDY1MjMyLCJ0cmFuc2FjdGlvbl9jb250ZXh0IjoiUnN4eHgueHgiLCJzY29wZSI6Im9wZW5pZCIsImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTQ0M1wvb2F1dGgyXC9jaWJhIiwiYmluZGluZ19tZXNzYWdlIjoiMTkwODE5OTUiLCJleHAiOjE1NzE2Mzk2NjMyMzIsInVzZXJfaGludCI6InZpdmVrIiwiaWF0IjoxNTcxNjM2MDYzMjMyLCJqdGkiOiIwM2U3ODBiMy00NGZhLTQyMjYtOWE0OS04OGZiZjJkNjMxNTQifQ.VqDM8Y_sxSbUu0NiRupR0OznNKm4jgNCel5WidDeB-GPvFQoX_jgu9Oh6tvbvvQfMwIzDa3-nUTKW67cftzoYFwo3e8Knz-NAfGZMOU-CUAyVq1EsLDXXaJ6ykkq_vt3Q9iIg6FJ8PRFEcWPOG3VO-ASGT3bmKHWieCDtUFZec2b0gFvQq7lmOcJEcv98F0Un8xaFtQgTn_fdTK_KXXavHIWrPLiapu2-rjEvD3I8KUJKcHbtMBtruY56P5DwjssEHPamKu_bPO7Cw6vlLqz1IVHBmoONmAi8DZrCZ8-4H8F8ZVZ5B19xuZ6uxk0G3bLZBJxiB2q-AhtI_1XNPBGqQ",
"type": "text"
},
{
"key": "redirect_uri",
"value": "http://localhost/CibaResponse",
"type": "text"
}
]
},
"url": {
"raw": "https://localhost:9443/oauth2/token",
"protocol": "https",
"host": [
"localhost"
],
"port": "9443",
"path": [
"oauth2",
"token"
]
}
}
2. Identity Server then validates the request [Step #2 of Fig.2.]
- isValidGrant — This is to check whether the granType mentioned in the request is registered and authorized for the client who made the request.
- isValidClient — This is to check whether the client who is initiating the request exists [registered] in Identity Server.
- isPollingAllowed— This is to check whether the client who is polling at the token endpoint is authorized to poll. For the first release, has not been planned to support ‘Ping Flow’, but given as an extensible point for the implementers to extend support.
- ActiveAuthReqID — This is to confirm whether the auth_req_id with which the request is made is active and be provided by IS itself.
- CorrectPollingFrequency — This is to confirm the correct polling frequency of the token request
3. Identity Server checks for Authentication status [Step #3 of Fig.2.]
- isUserAuthenticated— This is to check whether the user specified by the auth_req_id has been authenticated and authorized.
4. Provide Tokens [Step #4 of Fig.2.]
- If steps #2,#3 are affirmative return proper token response.
HTTP/1.1 200 OK
Content-Type: application/json{
"access_token":"01e51139-a7e6-302a-97b9-325c0e2b53bd",
"refresh_token":"26b17e0b-8d4e-332b-840c-cf3f63eb5c1d",
"scope":"openid",
"token_type":"Bearer",
"expires_in":3600",
"id_token":"eyJ4NXQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJraWQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiSjFScUhvSFRLN2ctS3dLOXFZVGY0dyIsImF1ZCI6Ilp6eG1EcXFLOFlZZmp0bE9oOXZ3ODVxbk5Wb2EiLCJzdWIiOiJ2aXZlayIsIm5iZiI6MTU3MTczODAwMCwiYXpwIjoiWnp4bURxcUs4WVlmanRsT2g5dnc4NXFuTlZvYSIsImFtciI6WyJ1cm46b3BlbmlkOnBhcmFtczpncmFudC10eXBlOmNpYmEiXSwiaXNzIjoiaHR0cHM6XC9cL2xvY2FsaG9zdDo5NDQzXC9vYXV0aDJcL3Rva2VuIiwiZXhwIjoxNTcxNzQxNjAwLCJpYXQiOjE1NzE3MzgwMDB9.JCjTzmZRNk5yllEX7R7NLDwybzjvP0H7xPVTInapiw44BJPM-VodXDDYE5lK1gu01-0XmfOwlUMjK1ir5I3R85lvXNsbPjCzspJVr8s5Z9UcrB9jF9gEfwkkz5V3uxh6GMrUqfxDhfftLkWkmEn3hbFVcNCQZo8gupnFQAFNpwipcEZVSXukeCgupCRmLqbGLZH6NyX8K5fui7qLzodcHXqbJYwRYk5WZ_aFWk8tXGYA8EGOEA9tDf31THqE1w8b6ZtsuEns1XyMbZcbzvBp-sEmEeAQV1FleGIC8EFv99WMqWd2xkPmYw-OoQl9xPeX13oXqI5uEnx-TiNK1M5HJg"
}
- Return error response if validations failed [The error descriptions vary according to the validations that the token had failed across].
HTTP/1.1 400 BadRequest
Content-Type: application/json{
"error_description": "authoization_pending",
"error": "invalid_grant"
}
- Eg: ErrorResponse when polling frequency is improper.
HTTP/1.1 400 BadRequest
Content-Type: application/json{
"error_description": "slow_down",
"error": "invalid_grant"
}
In this episode of CIBA series, we have seen our new approach to implement CIBA support for WSO2 IS. We have implemented the logic for the full functioning flow of CIBA. From below repositories, one can find the implementation of the components
We love breaking Ciba architecture further into bits and pieces so that everyone can understand the view of us on implementing Ciba. You’ve heard of 4+1 view? The next episode is going to be picturesque. Keep waiting !.
Happy Learning.