Hi,
Thanks for the suggestion. I have modified the existing
DefaultRequestCoordinator and removed ConditionalRequestCoordinator since
there are no functional level changes in DefaultRequestCoordinator.
Following is a sample script to enforce conditional authentication based on
the HTTP context.
function(context) {
executeStep({
id: '1',
on: {
success: function (context) {
if (context.request.cookies.testcookie) {
log.info("--------------- cookie testcookie found in
request.");
log.info("--------------- cookie testcookie.value: " +
context.request.cookies.testcookie.value);
log.info("--------------- cookie testcookie.domain: " +
context.request.cookies.testcookie.domain);
log.info("--------------- cookie testcookie.max-age: "
+ context.request.cookies.testcookie["max-age"]);
log.info("--------------- cookie testcookie.path: " +
context.request.cookies.testcookie.path);
log.info("--------------- cookie testcookie.secure: " +
context.request.cookies.testcookie.secure);
log.info("--------------- cookie testcookie.version: "
+ context.request.cookies.testcookie.version);
log.info("--------------- cookie testcookie.httpOnly: "
+ context.request.cookies.testcookie.httpOnly);
} else {
executeStep({
id: '2',
on: {
success: function (context)
{
log.info("--------------- setting cookie :
testcookie");
context.response.headers["Set-Cookie"] = "testcookie=1FD36B269C61;
Path=/; Secure; HttpOnly; Expires=Wed, 21 Jan 2018 07:28:00 GMT"
}
}
});
}
}
}
});
}
In the above script, we define a cookie called *testcookie*. At the initial
authentication stage, the user has to go through both step 1 and step 2. If
authentication is successful, we will set a cookie (testcookie) in the
user's browser. At the next login session, if this cookie is found in the
authentication request, user will be authenticated from the first step
itself and the second authentication step will get skipped.
Thanks,
Sathya
On Wed, Jan 17, 2018 at 6:56 PM, Ruwan Abeykoon <[email protected]> wrote:
> Hi Sathya,
>
> We can enhance the DefaultRequestCoordinator itself, rather than
> extending and creating new coordinator, as there is no functional change
> done by adding the "request" and "response" to authentication context.
>
> Cheers,
> Ruwan
>
> On Wed, Jan 17, 2018 at 10:40 AM, Sathya Bandara <[email protected]> wrote:
>
>> Hi all,
>>
>> We are currently working on improving the conditional authentication
>> support using JavaScript feature [1] to be able to handle authentication
>> conditions based on HTTP context.
>>
>> Following is the approach taken to achieve this requirement.
>>
>> In order to store the HTTP request and response I have modified the
>> default AuthenticationContext class to have additional state variables for
>> the authentication request and response(current request and response).
>> These variables are declared as transient such that they will not be used
>> for the object state at serialization. Furthermore, an additional variable
>> will be used to keep a reference to the initial authentication request
>> (initialRequest). When the second request comes, we will only update the
>> current request and response variables.
>>
>> The DefaultRequestCoordinator will be replaced with
>> ConditionalRequestCoordinator. In ConditionalRequestCordinator, inside
>> initializeFlow() method which gets called for the initial authentication
>> request, we instantiate an AuthenticationContext object. To this object, I
>> will set the current request, current response and initial request which is
>> the same as current request for the initial case. From the second request
>> for the ConditionalRequestCoordinator, only the current request and
>> response will be updated.
>>
>> In addition to the changes in the authentication framework, I have
>> implemented JavaScript wrapper classes for the HttpServletRequest and
>> HttpServletResponse Java classes in order to provide access to the
>> request/response state variables within JavaScript. Following are some
>> examples.
>>
>> *Request headers (context.request.headers)*
>>
>> context.request.headers.Authorization - this will give the value of the
>> Authorization header.
>>
>> *Request parameters (context.request.params)*
>>
>> context.request.params.redirect_uri - this will give the value of the
>> request parameter redirect_uri
>>
>> *Cookies in request (context.request.cookies)*
>>
>> context.cookies.commonAuthId - this will create a JavaScript wrapper for
>> the Cookie Java Class. We can access individual cookie attributes using
>> this wrapper as follows.
>>
>> context.request.cookies.commonAuthId.domain
>> context.request.cookies.commonAuthId.value
>>
>> In request, we can only query existing attributes (headers and request
>> parameters). cannot add or modify existing values.
>>
>> Similar approach was used for the HttpServletResponse class as well.
>> However in HttpServletResponse, we have the capability to add new headers
>> to the response.
>>
>> *Adding headers to the response*
>>
>> In order to wrap the setHeader() in JavaScript, I used the following
>> implementation.
>>
>> public class JsHeaders extends AbstractJSObject {
>>
>> private Map wrapped;
>> private HttpServletResponse response;
>>
>> public JsHeaders(Map wrapped, HttpServletResponse response) {
>>
>> this.wrapped = wrapped;
>> this.response = response;
>> }
>>
>> @Override
>> public void setMember(String name, Object value) {
>>
>> if (wrapped == null) {
>> super.setMember(name, value);
>> } else {
>> wrapped.put(name, value);
>> response.setHeader(name, (String) value); //replaces the
>> value if the name exists.
>> }
>> }
>> }
>>
>> Here, I keep the existing headers in a map. Whenever
>> context.response.headers is called , an instance of the JsHeaders wrapper
>> is returned which contains the header map and a reference to the response.
>> Once a new header is added as in example
>> context.response.headers.Authorization
>> = "sample_value", the setMember() function is called. It will add the
>> header (header name and value) to the referenced response.
>>
>> e.g. context.response.headers["Content-Type"] = 'application/json'
>>
>>
>> *Adding cookies to the response *
>>
>> Similarly, when adding a new cookie to the response, we will add a new
>> header to the response with the header name 'set-cookie'. This is similar
>> to the approach used in nodejs [2].
>>
>> response.headers["set-cookie"] or response.headers.set-cookie can be used.
>>
>> An example would be as follows.
>>
>> response.headers.["Set-Cookie"] = ['crsftoken=xxxxxssometokenxxxxx',
>> 'language=javascript']
>>
>> Highly appreciate your thoughts and suggestions.
>>
>> [1] [Architecture] Conditional Authentication Support on WSO2 Identity
>> Server
>> [2] https://nodejs.org/api/http.html#http_response_setheader_name_value
>> <https://nodejs.org/docs/v0.4.0/api/http.html#response.setHeader>
>>
>> Thanks,
>> Sathya
>>
>> --
>> Sathya Bandara
>> Software Engineer
>> WSO2 Inc. http://wso2.com
>> Mobile: (+94) 715 360 421 <+94%2071%20411%205032>
>>
>> <+94%2071%20411%205032>
>>
>
>
>
>
--
Sathya Bandara
Software Engineer
WSO2 Inc. http://wso2.com
Mobile: (+94) 715 360 421 <+94%2071%20411%205032>
<+94%2071%20411%205032>
_______________________________________________
Architecture mailing list
[email protected]
https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture