OPA integration with wso2 identity server using script based adaptive authentication.

Nimasha fernando
4 min readFeb 28, 2020

--

WSO2 identity server, The leader in open-source identity and access management currently using XACML to write policies. But, what do you think about using OPA (open policy agent) as well as XACML to enforce wso2 IS policies ? let’s talk about this.

OPA is an open source, general-purpose policy engine that unifies policy enforcement across the tested and scalable stack and it is one of a practical solution for the critical security and policy challenges of the cloud-native ecosystems.

So via this entry, I am going to discuss with you about the steps should be followed to integrate OPA with wso2 identity sever using script based adaptive authentication. To do so here I have used the role based authorization scenario. Here we go….!

step 1: Configuring a Service Provider for Adaptive Authentication

First of all you should configure a service provider for adaptive authentication.To configure a service provider follow the steps in wso2 identity server documentation.

step 2: Configuring Role-Based Adaptive Authentication

To configure a role base adaptive authentication follow the steps in wso2 identity server documentation.

While you are configuring the sample scenario, use the following script instead of using the given script in the documentation , and set the authentication step two as Demo HardwareKey Authentication and step three as Basic Authentication.

In this script we have used “httpPost” function -wso2 identity server auth function, to call OPA end point ‘http://localhost:8181/v1/data/play/policy' while passing the user attributes as the input to OPA.Then get the response back and based on that response -'secondstep', we decide which step should be the next.

But when you are writing scrips keep this in mind that , httpPost method is asynchronous as Ajax calls in JSON. This means, while executing the httpPost method it will stop and other code will be able to execute until the call returns (successfully or otherwise), at which point the callback will run synchronously. No other code will be running at this point. It won’t interrupt any other code that’s currently running.

var attribute = null;function get_user_attributes(user){

attribute = user.localClaims['http://wso2.org/claims/role'];
Log.info('user_attribute'+ attribute );

}
function next_step_from_opa_response(permit_or_deny,secondstep){
//you can see the values os OPA response via command line
Log.info('permit_or_deny '+ permit_or_deny);
Log.info('secondstep '+ secondstep);


if (secondstep == "Demo HardwareKey Authenticator") {
//Log.info(user.username + ' Has one of Roles: ' + rolesToStepUp.toString());
executeStep(2);
}else{
executeStep(3);
}
}
var onLoginRequest = function(context) {
executeStep(1, {
onSuccess: function (context) {

// Extracting authenticated subject from the first step
var user = context.currentKnownSubject;
get_user_attributes(user);


//send user attributes to OPA
httpPost('http://localhost:8181/v1/data/play/policy', {"input":{"attribute" : attribute}}, {
onSuccess : function(context, data) {

var permit_or_deny = null;
var secondstep = null;
permit_or_deny = data.result.allow;
secondstep = data.result.finally[0];

//choose the next step next_step_from_opa_response(permit_or_deny,secondstep );

}, onFail : function(context) {
Log.info("Failed to post data");
}
});
}
});
};

step 3: Download OPA

To get started download an OPA binary for your platform from GitHub releases you can use curl command.

On macOS (64-bit):

curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_darwin_amd64

On Linux (64-bit):

curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64

Windows users can obtain the OPA executable from GitHub Releases. The steps below are the same for Windows users except the executable name will be different.

Set permissions on the OPA executable:

chmod 755 ./opa

You can also download and run OPA via Docker. The latest stable image tag is,

openpolicyagent/opa:latest.

step 4: Run OPA engine.

After downloading the binary, open the command prompt & start the OPA service by issuing the command:

./opa run --server

step 5: Write and upload the OPA policy to OPA engine .

If you have data , first you should upload the data file into OPA using the following curl command : (In this case we don’t have data so you don’t need to execute this command . But you can use data files as your needs.)

curl -X PUT http://localhost:8181/v1/data/myapi/acl --data-binary @myapi-acl.json

You can write down the policy as shown bellow and upload it :

OPA’s “split” build in function gives the output as an array[string] representing elements of string separated by delimiter .So we can access the user’s each attribute.

Furthermore If the “allow” function returns “true” , the “finally” function will returns a message as “Demo HardwareKey Authenticator”,and if the “allow” function returns as “false” , then the “ finally” function will returns a message as “Basic Authentication” .

package play.policyimport inputdefault allow = falseallow = true{
output := split(input.attribute, ",")
role = ["admin", "manager"]
onerole := output[_]
onerole == role[_]
}
finally[msg]{
allow
msg := ("Demo HardwareKey Authenticator")
}
finally[msg]{
allow == false
msg := ("Basic Authentication")
}

Then upload the above policy file ispolicy.rego into OPA by using following curl command:

curl -X PUT http://localhost:8181/v1/policies/myapi --data-binary @ispolicy.rego

step 6: Try out OPA policy using your sample app.

To check it via the sample app, access the following sample PickUp application URL: http://localhost.com:8080/saml2-web-app-pickup-dispatch.com.

Click Login and enter admin/admin credentials. You are prompted to use the hardware key after basic authentication according to the authentication step defined in the JavaScript above. Or click Login and enter another registered username and password. You can log in only with the basic authentication step.

You also can issue our query using curl command and test whether OPA is working correctly or not.

If you log as an 'admin';$ curl -X POST http://localhost:8181/v1/data/play/policy --data-binary '{ "input": { "attribute": "Application/saml2-web-app-pickup-dispatch,Internal/everyone,admin" } }' | jqoutput :{
"result": {
"allow": true,
"finally": [
"Demo HardwareKey Authenticator"
]
}
}

--

--