curl code, detailed instructions

This commit is contained in:
Alfredo Oliviero 2024-03-05 18:04:16 +01:00
parent 1a956b4e25
commit 7a57ca9a95
4 changed files with 401 additions and 73 deletions

View File

@ -3,6 +3,10 @@
## [v1.2.0] - 2023-03-20
- Decode Button
- Updatet layout
- Added refresh token
- Added expiration
- Button for decode on https://jwt.io/
## [v1.0.1] - 2022-05-25

View File

@ -13,12 +13,15 @@ import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Base64;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.oidc.rest.JWTToken;
import org.gcube.oidc.rest.OpenIdConnectConfiguration;
import org.gcube.oidc.rest.OpenIdConnectRESTHelper;
import org.gcube.oidc.rest.OpenIdConnectRESTHelperException;
import org.gcube.portal.oidc.lr62.JWTCacheProxy;
import org.gcube.portal.oidc.lr62.LiferayOpenIdConnectConfiguration;
import org.gcube.vomanagement.usermanagement.GroupManager;
@ -27,6 +30,7 @@ import org.gcube.vomanagement.usermanagement.model.GCubeGroup;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.model.User;
@ -78,9 +82,16 @@ public class RPTTokenReader extends MVCPortlet {
System.out.println("Selected context="+context);
HttpServletRequest httpReq = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(resourceRequest));
JWTToken umaToken = null;
resourceResponse.setContentType("application/json");
JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
try {
User theUser = PortalUtil.getUser(resourceRequest);
OpenIdConnectConfiguration configuration = LiferayOpenIdConnectConfiguration.getConfiguration(httpReq);
jsonObject.put("token_url", configuration.getTokenURL().toString());
JWTCacheProxy jwtCacheProxy = JWTCacheProxy.getInstance();
String sessionId = httpReq.getSession().getId();
String urlEncodedContext = null;
@ -93,19 +104,51 @@ public class RPTTokenReader extends MVCPortlet {
JWTToken authToken = jwtCacheProxy.getOIDCToken(theUser, sessionId);
umaToken = OpenIdConnectRESTHelper.queryUMAToken(configuration.getTokenURL(), authToken.getAccessTokenAsBearer(), urlEncodedContext, null);
log.debug("Got a new UMA token " + umaToken.getTokenEssentials());
} catch (Exception e) {
} catch (OpenIdConnectRESTHelperException e) {
resourceResponse.setProperty(ResourceResponse.HTTP_STATUS_CODE, "" + e.getStatus());
e.printStackTrace();
JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
jsonObject.put("success", false);
jsonObject.put("comment", e.getMessage());
resourceResponse.getWriter().println(jsonObject);
super.serveResource(resourceRequest, resourceResponse);
return;
} catch (Exception e) {
e.printStackTrace();
jsonObject.put("success", false);
jsonObject.put("comment", e.getMessage());
resourceResponse.getWriter().println(jsonObject);
super.serveResource(resourceRequest, resourceResponse);
return;
}
String toReturn = umaToken.getAccessTokenString();
resourceResponse.setContentType("application/json");
JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
// } catch (Exception e) {
// e.printStackTrace();
// JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
// jsonObject.put("success", false);
// jsonObject.put("comment", e.getMessage());
// resourceResponse.getWriter().println(jsonObject);
// super.serveResource(resourceRequest, resourceResponse);
// }
jsonObject.put("success", true);
jsonObject.put("comment", toReturn);
jsonObject.put("access_token", umaToken.getAccessTokenString());
jsonObject.put("refresh_token", umaToken.getRefreshTokenString());
jsonObject.put("raw_token", umaToken.getRaw());
jsonObject.put("access_token_exp", umaToken.getExp());
jsonObject.put("essential", umaToken.getTokenEssentials());
jsonObject.put("client_id", umaToken.getAzp());
JSONArray audiences = JSONFactoryUtil.createJSONArray();
List<String> list_audiences = umaToken.getAud();
for (int i = 0; i < list_audiences.size(); i++) {
audiences.put((String) list_audiences.get(i));
}
jsonObject.put("audience", audiences);
resourceResponse.getWriter().println(jsonObject);
super.serveResource(resourceRequest, resourceResponse);
}

View File

@ -0,0 +1,11 @@
code.wraptext {
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
.bg_white {
background-color: white !important;
}

View File

@ -1,67 +1,196 @@
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<%@include file="../init.jsp"%>
<%@ page import="org.gcube.vomanagement.usermanagement.model.GCubeGroup"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@include file="../init.jsp" %>
<%@ page import="org.gcube.vomanagement.usermanagement.model.GCubeGroup" %>
<portlet:defineObjects />
<portlet:resourceURL var="resourceURL">
</portlet:resourceURL>
<%
List<GCubeGroup> userGroups = (List<GCubeGroup>) request.getAttribute("userGroups");
<% List<GCubeGroup> userGroups = (List<GCubeGroup>) request.getAttribute("userGroups");
pageContext.setAttribute("userGroups", userGroups);
List<String> userContexts = (List<String>) request.getAttribute("userContexts");
pageContext.setAttribute("userContexts", userContexts);
%>
<script type="text/javascript">
function decodeFunction(token) {
var token = $("#tokenResult").val();
var global_token_response = {};
$('#txt_name').val();
function formatDuration(seconds) {
console.log("seconds", seconds);
window.open(
"https://jwt.io/#id_token=" + token,
'_blank' // <- This is what makes it open in a new window.
);
if (!seconds) {
return "";
}
if (seconds < 0) seconds *= seconds;
var intervals = {
day: Math.floor(seconds / (60 * 60 * 24)),
hour: Math.floor(seconds / (60 * 60)) % 24,
minute: Math.floor(seconds / 60) % 60,
second: Math.floor(seconds / 1) % 60
};
return Object.entries(intervals)
.filter(val => val[1] !== 0)
.map(([key, val]) => "" + val + " " + key + (val != 1 ? 's' : ''))
.join(', ');
}
function initForm() {
$('#response_group').hide();
$('#error_msg').hide();
$('#rawTokenResult').hide();
console.log("hided response_group")
}
function resetResults() {
// $('#buttonCopy').hide();
// $('#buttonDecode').hide();
$('#tokenResult').text('');
$('#tokenResultDetails').text('');
$('#refreshTokenResult').text('');
$('#refreshTokenResultDetails').text('');
$('#rawTokenResult').text('');
$('#error_msg').html("")
$('#refresh_token_url').html('');
$('#client_id').html('');
}
function setResults(resultObject) {
global_token_response = resultObject;
$('#tokenResult').text(resultObject.access_token);
$('#refreshTokenResult').text(resultObject.refresh_token);
$('#refresh_token_url').text(resultObject.token_url);
$('#client_id').text(resultObject.client_id);
$('#refresh_usage_info').html(generateRefreshCurl("[CLIENT_ID]", "[REFRESH_TOKEN]", "[REFRESH_URL]"))
var raw = JSON.parse(resultObject.raw_token)
var expires_in = raw.expires_in;
if (expires_in) {
$('#tokenResultDetails').html('expires in <b>' + formatDuration(expires_in) + '</b>');
}
var refresh_expires_in = raw.refresh_expires_in;
if (expires_in) {
$('#refreshTokenResultDetails').html('expires in <b>' + formatDuration(refresh_expires_in) + '</b>');
}
var not_before_policy = raw["not-before-policy"];
console.log("expires_in", expires_in);
console.log("refresh_expires_in", refresh_expires_in);
console.log("not-before-policy", not_before_policy);
$('#rawTokenResult').html(JSON.stringify(raw, undefined, 4));
$('#response_group').show();
console.log("resultObject", resultObject)
}
function setError(error_comment) {
$('response_group').hide();
$('#error_msg').show();
$('#error_msg').html(error_comment);
}
function getUMAToken(endpoint) {
console.log("getUMAToken:" + endpoint);
$('#umaButton').attr("disabled", true);
$('#buttonCopy').hide();
$('#div_decode').hide();
resetResults();
var selectedContext = $("#myselect").val();
$('#tokenResult').text('');
console.log("selected context: ", selectedContext);
$.ajax({
url : endpoint,
type : 'POST',
datatype : 'json',
data : {
context : selectedContext
url: endpoint,
type: 'POST',
datatype: 'json',
data: {
context: selectedContext
},
success : function(data) {
var resultObject = JSON.parse(JSON.stringify(data));
success: function (data) {
$("#intro").hide();
var raw = JSON.stringify(data)
var resultObject = JSON.parse(raw);
if (resultObject.success) {
$('#tokenResult').text(resultObject.comment);
$('#buttonCopy').show();
$('#div_decode').show();
//console.log("resultObject", resultObject)
$('jsonresp').html(resultObject)
setResults(resultObject);
} else {
$('#tokenResult').text(resultObject.comment);
$('#tokenResult').css('color', 'red');
setError(resultObject.comment)
}
$('#umaButton').attr("disabled", false);
},
error: function (xhr, status, error) {
console.error("error", xhr, status, error);
setError("Server error, cannot obtain the token");
$('#umaButton').attr("disabled", false);
}
});
}
function copyFunction() {
function toggleInfo(destination_id) {
$("#" + destination_id).toggle();
}
function decodeFunction(text_id) {
var decode_text = $("#" + text_id).val();
window.open(
"https://jwt.io/#id_token=" + encodeURIComponent(decode_text),
'_blank'
);
}
function generateRefreshCurl(client_id, refresh_token, refresh_url) {
return "curl --location '" + refresh_url + "' \\\n" +
"\t--header 'Content-Type: application/x-www-form-urlencoded' \\\n" +
"\t--data-urlencode 'grant_type=refresh_token' \\\n" +
"\t--data-urlencode 'client_id=" + client_id + "' \\\n" +
"\t--data-urlencode 'refresh_token=" + refresh_token + "' "
// return "curl --request POST " +
// "--data " +
// "'refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJjOTk5YmVjNC1iNDc4LTQ4Y2YtYmI5OS0wMWMxODY5NzcwNGIifQ.eyJleHAiOjE3MTA5NDMyNzcsImlhdCI6MTcwOTczMzY3NywianRpIjoiYTEyNWNkNjUtYTJlYi00OTM3LWEwODAtNzZkYjMxNThlZGU0IiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5kZXYuZDRzY2llbmNlLm9yZy9hdXRoL3JlYWxtcy9kNHNjaWVuY2UiLCJhdWQiOiJodHRwczovL2FjY291bnRzLmRldi5kNHNjaWVuY2Uub3JnL2F1dGgvcmVhbG1zL2Q0c2NpZW5jZSIsInN1YiI6ImI5OTY5YjUxLTU3OGYtNGI2OS1hNTNmLTJjOGFkZjllZmNjNyIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJuZXh0LmRldi5kNHNjaWVuY2Uub3JnIiwic2Vzc2lvbl9zdGF0ZSI6IjczMzVjZGY5LTFlMjUtNGU5OC1iNjg2LWM1ZTg1NGU2MmQ4OCIsImF1dGhvcml6YXRpb24iOnsicGVybWlzc2lvbnMiOlt7InJzaWQiOiI1NzI4NTUxMC0zOTM5LTRkZTctOGZjMS1lM2E5ZDNjY2UyODEiLCJyc25hbWUiOiJEZWZhdWx0IFJlc291cmNlIn1dfSwic2NvcGUiOiJlbWFpbCBwcm9maWxlIiwic2lkIjoiNzMzNWNkZjktMWUyNS00ZTk4LWI2ODYtYzVlODU0ZTYyZDg4In0.q6T2tVSvMXJzxaxRGavGaghRB9myk4CSjhO_-mvOXxY" +
// "&client_id=next.dev.d4science.org" +
// "&grant_type=refresh_token' " +
// "https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token"
}
function copyText(text) {
var listener = function (ev) {
ev.clipboardData.setData("text/plain", text);
ev.preventDefault();
};
document.addEventListener("copy", listener);
document.execCommand("copy");
document.removeEventListener("copy", listener);
}
function copyRefreshCurl() {
var curl = generateRefreshCurl(
global_token_response.client_id,
global_token_response.refresh_token,
global_token_response.token_url);
copyText(curl);
}
function copyFunction(text_id) {
/* Get the text field */
var copyText = document.getElementById("tokenResult");
var copyText = document.getElementById(text_id);
/* Select the text field */
copyText.select();
@ -70,36 +199,177 @@ pageContext.setAttribute("userContexts", userContexts);
/* Copy the text inside the text field */
document.execCommand("copy");
}
</script>
<c:if test = "${userContexts.size() > 1}">
<p>Select the context:</p>
</c:if>
<div>
<select style="width: 100%;" name="contexts" id="myselect">
<c:forEach var="context" items="${userContexts}">
<option value="${context}">${context}</option>
</c:forEach>
</select>
</div>
<div style="margin-bottom: 15px;">
<button name="umaButton" id="umaButton" type="button"
class="btn btn-primary" onClick="getUMAToken('${resourceURL}')">Get
Token</button>
</div>
<div>
<button id="buttonCopy" class="btn btn-mini" onclick="copyFunction()">
<i class="icon-copy"></i> Copy
</button>
<textarea style="width: 90%;" 300px; margin: 10px;" id="tokenResult"></textarea>
</div>
<div id="div_decode">
You can use <a href="https://jwt.io/#debugger-io" target="blank">https://jwt.io/</a>
to <button id="buttonDecode" class="btn btn-mini" onclick="decodeFunction()">
<i class="icon-repository"></i> Decode
</button>
</div>
<script>
$('#buttonCopy').hide();
$('#div_decode').hide();
</script>
<c:if test="${userContexts.size() == 0}">
<div class="alert alert-error">
Configuration error, no context available
</div>
</c:if>
<div>
<c:if test="${userContexts.size() == 1}">
<p>Current context: ${userContexts[0]}</p>
<input type="hidden" name="contexts" id="myselect" value="${userContexts[0]}">
</c:if>
<c:if test="${userContexts.size() > 1}">
<p>Select the context:</p>
<div>
<select style="width: 100%;" name="contexts" id="myselect">
<c:forEach var="context" items="${userContexts}">
<option value="${context}">${context}</option>
</c:forEach>
</select>
</div>
</c:if>
<div class="row">
<div>
<c:if test="${userContexts.size() >= 1}">
<button name="umaButton" id="umaButton" type="button"
class="btn btn-primary" onClick="getUMAToken('${resourceURL}')">Get
Token</button>
</c:if>
<button id="buttonInfo" class="btn btn-small pull-right"
onclick="toggleInfo('intro')" title="Toggle infos" alt="Toggle infos">
<i class="icon-info"></i>
</button>
</div>
</div>
<br>
<div id="intro" class="well well-small">
Obtain your personal OAuth2 Access and Refresh Tokens, to be used for
programmatic
interaction with the services.
<br> Do not use this token to authenticate services but only for personal access
</div>
</div>
<div id="response_group">
<div id="response_group_token" class="well well-small bg_white">
<div class="row">
<div class="control-label span9">OAuth Access Token (Bearer Authorization)
</div>
<button id="buttonInfo" data-toggle="tooltip" class="btn btn-small pull-right"
onclick="toggleInfo('tokenResultInfo')" title="Toggle infos"
alt="Toggle infos">
<i class="icon-info"></i>
</button>
</div>
<textarea rows="2" id="tokenResult" class="disabled span12" readonly></textarea>
<div class="row">
<span class="help-block span9" id='tokenResultDetails'></span>
<div class="btn-group btn-group span2">
<button id="buttonDecode" data-toggle="tooltip" class="btn btn-small"
onclick="decodeFunction('tokenResult')" title="Decode" alt="Decode">
<i class="icon-list"></i>
</button>
<button id="buttonCopy" data-toggle="tooltip" class="btn btn-small"
onclick="copyFunction('tokenResult')" title="Copy" alt="Copy">
<i class="icon-copy"></i>
</button>
</div>
</div>
<div id="tokenResultInfo" style="display: none;" class="well well-small">
<p>Personal Token used to access protected resources</p>
<p>The token has a limited lifespan and must be included as a Bearer token
in the Authorization header of the request"</p>
<p>usage:<br>
<code
class="wraptext">curl -H "Authorization: Bearer [ACCESS_TOKEN] " \<br>&emsp;https://api.esempio.com/userinfo</code>
</p>
ref: <a
href="https://oauth.net/2/access-tokens">https://oauth.net/2/access-tokens/
</a>
</div>
</div>
<div id="response_group_refreshToken" class="well well-small bg_white">
<div class="row">
<div class="control-label span9">Oauth2 Refresh Token
</div>
<button id="buttonInfo" data-toggle="tooltip" class="btn btn-small pull-right"
onclick="toggleInfo('refreshTokenResultInfo')" title="Toggle infos"
alt="Toggle infos">
<i class="icon-info"></i>
</button>
</div>
<textarea rows="2" id="refreshTokenResult" class="disabled span12" readonly></textarea>
<div class="row">
<span class="help-block span9" id='refreshTokenResultDetails'></span>
<div class="btn-group btn-group span2">
<button id="buttonDecode" data-toggle="tooltip" class="btn btn-small"
onclick="decodeFunction('refreshTokenResult')" title="Decode"
alt="Decode">
<i class="icon-list"></i>
</button>
<button id="buttonCopy" data-toggle="tooltip" class="btn btn-small"
onclick="copyFunction('refreshTokenResult')" title="Copy" alt="Copy">
<i class="icon-copy"></i>
</button>
</div>
</div>
<div id="refreshTokenResultInfo" style="display: none;" class="well well-small">
<p>Use this token to programmaticaly refresh the Access token.</p>
<p>usage:<br>
<code class="wraptext" id="refresh_usage_info"></code>
</p>
ref: <a href="https: //oauth.net/2/refresh-tokens/">
https://oauth.net/2/refresh-tokens/</a>
</div>
</div>
<div id="parameters" class="well well-small bg_white">
<div class="control-label ">Refresh parameters</div>
<div class="row">
refresh token url: <code class="wraptext" id="refresh_token_url"></code>
<button id="refresh_token_url_copy" data-toggle="tooltip"
class="btn btn-small pull-right"
onclick="copyText(global_token_response.token_url)"
title="copy refresh token url" alt="copy refresh token url">
<i class="icon-copy"></i>
</button>
</div>
<div class="row">
client_id: <code class="wraptext" id="client_id"></code> <button
id="client_id_copy" data-toggle="tooltip" class="btn btn-small pull-right"
onclick="copyText(global_token_response.client_id)"
title="copy refresh token url" alt="copy refresh token url">
<i class="icon-copy"></i>
</button><br>
</div>
<div class="row">
curl refresh request (copy): <button id="buttonGenerateRefreshCurl"
data-toggle="tooltip" class="btn btn-small pull-right" onclick="copyRefreshCurl()"
title="geneate refresh curl" alt="Generate refresh curl">
<i class="icon-copy"></i>
</button>
</div>
</div>
<div id="div_decode">
You can decode the tokens using <a href="https://jwt.io/#debugger-io" target="blank">https://jwt.io/</a>
</div>
</div>
<div id="error_msg" class="alert alert-error">
Configuration error, no context available
</div>
<script>
initForm();
</script>