Membrane can act as an OAuth2 authorization server for usage with an OAuth2 compatible client.
In this example we will use Membrane as an authorization server that can authenticate users through a login dialog and a client that communicates with this authentication server on behalf of the user to securely access an unprotected resource.
To run, the example goes to the $MEMBRANE_HOME/exmaples/security/oauth2/implicit folder in the Membrane API Gateway distribution. Complete the following steps:
The following part describes the example in detail.
Authorization serverFor a comprehensive description of the authorization server, please follow to the OAuth2 authorization code example and there to the Details heading.
WebserverThe webserver's only task is to host the JavaScript client. It can be replaced by any other standard hosting software e.g., Tomcat.
Take a look at the proxies.xml
<router>
<api name="Membrane Resource service" port="2000">
<path>/oauth2callback</path>
<groovy>
Response.ok(new File("../JavaScriptClient.html").text).build()
</groovy>
</serviceProxy>
<serviceProxy name="Membrane Resource service" port="2000">
<groovy>
Response.ok(new File("../JavaScriptClient.html").text).build()
</groovy>
</api>
</router>
Listing 1: Webserver configuration in the proxies.xml
The webserver provides 2 endpoints that serve the same file. The file is a sample implementation of an OAuth2 client in JavaScript. It is not ready for production usage. The webserver is available on port 2000. It serves the JavaScript client when called directly or through the OAuth2 callback.
JavaScript client
The JavaScript client implements a typical basic user agent OAuth2 client.
<script>
var redirect = function(){
window.location = 'http://localhost:7007/oauth2/auth?response_type=token&client_id=' + encodeURIComponent('abc') + '&redirect_uri='
+ encodeURIComponent('http://localhost:2000/oauth2callback') + '&scope=' + 'profile';
};
var getParams = function(){
var querysRaw = window.location.search.substring(1).split('&');
var result = new Object();
for(var i = 0; i < querysRaw.length;i++){
var pair = querysRaw[i].split("=");
result[pair[0]] = pair[1];
}
sessionStorage.setItem("auth",result.token_type + " " + result.access_token)
return result;
};
var validateAccessToken = function(auth){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET',"http://localhost:7007/oauth2/userinfo",true);
xmlhttp.setRequestHeader("Authorization", auth);
xmlhttp.send(null);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if ( xmlhttp.status == 200) {
alert("Validation successful.")
}
else {
sessionStorage.clear();
redirect();
}
}
}
}
var accessToken = sessionStorage.getItem("auth");
if(accessToken){
validateAccessToken(accessToken);
}
else if (window.location.pathname == "/oauth2callback") {
getParams();
validateAccessToken( sessionStorage.getItem("auth"));
} else{
redirect();
}
</script>
Listing 2: JavaScript client embedded in an html web page
The JavaScript client starts the OAuth2 implicit flow when there is no access token in the browsers session. It also processes oauth2callback redirects from the authorization server. When the flow is finished the access token is saved. On the following requests the access token is reused for validation.
Do you need any help for this scenario? Email: membrane@predic8.com.