Change perf test to parse accessToken and refreshToken in Servlet. Support for logout
This commit is contained in:
parent
a1d4d8e13f
commit
4ebc575afc
5 changed files with 65 additions and 133 deletions
|
@ -78,7 +78,7 @@ public class KeycloakPerfServer {
|
||||||
deploymentInfo.setContextPath("/perf-app");
|
deploymentInfo.setContextPath("/perf-app");
|
||||||
|
|
||||||
ServletInfo servlet = new ServletInfo("PerfAppServlet", PerfAppServlet.class);
|
ServletInfo servlet = new ServletInfo("PerfAppServlet", PerfAppServlet.class);
|
||||||
servlet.addMapping("/perf-servlet");
|
servlet.addMapping("/perf-servlet/*");
|
||||||
|
|
||||||
deploymentInfo.addServlet(servlet);
|
deploymentInfo.addServlet(servlet);
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,10 @@ import freemarker.cache.ClassTemplateLoader;
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
import freemarker.template.Template;
|
import freemarker.template.Template;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
|
import org.keycloak.adapters.AdapterConstants;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.RefreshToken;
|
import org.keycloak.representations.RefreshToken;
|
||||||
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -43,6 +45,7 @@ public class PerfAppServlet extends HttpServlet {
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
resp.setContentType("text/html");
|
resp.setContentType("text/html");
|
||||||
String action = req.getParameter("action");
|
String action = req.getParameter("action");
|
||||||
|
String actionDone = null;
|
||||||
|
|
||||||
if (action != null) {
|
if (action != null) {
|
||||||
if (action.equals("code")) {
|
if (action.equals("code")) {
|
||||||
|
@ -50,8 +53,10 @@ public class PerfAppServlet extends HttpServlet {
|
||||||
return;
|
return;
|
||||||
} else if (action.equals("exchangeCode")) {
|
} else if (action.equals("exchangeCode")) {
|
||||||
exchangeCodeForToken(req, resp);
|
exchangeCodeForToken(req, resp);
|
||||||
|
actionDone = "Token retrieved";
|
||||||
} else if (action.equals("refresh")) {
|
} else if (action.equals("refresh")) {
|
||||||
refreshToken(req, resp);
|
refreshToken(req, resp);
|
||||||
|
actionDone = "Token refreshed";
|
||||||
} else if (action.equals("logout")) {
|
} else if (action.equals("logout")) {
|
||||||
logoutRedirect(req, resp);
|
logoutRedirect(req, resp);
|
||||||
return;
|
return;
|
||||||
|
@ -61,13 +66,22 @@ public class PerfAppServlet extends HttpServlet {
|
||||||
String code = req.getParameter("code");
|
String code = req.getParameter("code");
|
||||||
if (code != null) {
|
if (code != null) {
|
||||||
req.getSession().setAttribute("code", code);
|
req.getSession().setAttribute("code", code);
|
||||||
|
actionDone = "Code retrieved";
|
||||||
}
|
}
|
||||||
|
|
||||||
String freemarkerRedirect = freemarkerRedirect(req, resp);
|
String freemarkerRedirect = freemarkerRedirect(req, resp, actionDone);
|
||||||
resp.getWriter().println(freemarkerRedirect);
|
resp.getWriter().println(freemarkerRedirect);
|
||||||
resp.getWriter().flush();
|
resp.getWriter().flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
if (req.getRequestURI().endsWith(AdapterConstants.K_LOGOUT)) {
|
||||||
|
// System.out.println("Logout callback triggered");
|
||||||
|
resp.setStatus(204);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void keycloakLoginRedirect(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void keycloakLoginRedirect(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
String loginUrl = oauthClient.getLoginFormUrl();
|
String loginUrl = oauthClient.getLoginFormUrl();
|
||||||
resp.sendRedirect(loginUrl);
|
resp.sendRedirect(loginUrl);
|
||||||
|
@ -77,32 +91,60 @@ public class PerfAppServlet extends HttpServlet {
|
||||||
String code = (String)req.getSession().getAttribute("code");
|
String code = (String)req.getSession().getAttribute("code");
|
||||||
OAuthClient.AccessTokenResponse atResponse = oauthClient.doAccessTokenRequest(code, "password");
|
OAuthClient.AccessTokenResponse atResponse = oauthClient.doAccessTokenRequest(code, "password");
|
||||||
|
|
||||||
String accessToken = atResponse.getAccessToken();
|
updateTokensInSession(req, atResponse);
|
||||||
String refreshToken = atResponse.getRefreshToken();
|
|
||||||
req.getSession().setAttribute("accessToken", accessToken);
|
|
||||||
req.getSession().setAttribute("refreshToken", refreshToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void refreshToken(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void refreshToken(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
String refreshToken = (String)req.getSession().getAttribute("refreshToken");
|
String refreshToken = (String)req.getSession().getAttribute("refreshToken");
|
||||||
OAuthClient.AccessTokenResponse atResponse = oauthClient.doRefreshTokenRequest(refreshToken, "password");
|
OAuthClient.AccessTokenResponse atResponse = oauthClient.doRefreshTokenRequest(refreshToken, "password");
|
||||||
|
|
||||||
|
updateTokensInSession(req, atResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTokensInSession(HttpServletRequest req, OAuthClient.AccessTokenResponse atResponse) {
|
||||||
String accessToken = atResponse.getAccessToken();
|
String accessToken = atResponse.getAccessToken();
|
||||||
refreshToken = atResponse.getRefreshToken();
|
String refreshToken = atResponse.getRefreshToken();
|
||||||
|
AccessToken accessTokenParsed = oauthClient.verifyToken(accessToken);
|
||||||
|
RefreshToken refreshTokenParsed = oauthClient.verifyRefreshToken(refreshToken);
|
||||||
req.getSession().setAttribute("accessToken", accessToken);
|
req.getSession().setAttribute("accessToken", accessToken);
|
||||||
req.getSession().setAttribute("refreshToken", refreshToken);
|
req.getSession().setAttribute("refreshToken", refreshToken);
|
||||||
|
req.getSession().setAttribute("accessTokenParsed", accessTokenParsed);
|
||||||
|
req.getSession().setAttribute("refreshTokenParsed", refreshTokenParsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void logoutRedirect(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
protected void logoutRedirect(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
String sessionState = null;
|
||||||
|
AccessToken accessTokenParsed = (AccessToken)req.getSession().getAttribute("accessTokenParsed");
|
||||||
|
if (accessTokenParsed != null) {
|
||||||
|
sessionState = accessTokenParsed.getSessionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalidate http session
|
||||||
|
req.getSession(false).invalidate();
|
||||||
|
|
||||||
|
String logoutURL = oauthClient.getLogoutUrl(oauthClient.getRedirectUri(), sessionState);
|
||||||
|
resp.sendRedirect(logoutURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String freemarkerRedirect(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
private String freemarkerRedirect(HttpServletRequest req, HttpServletResponse resp, String actionDone) throws ServletException, IOException {
|
||||||
|
AccessToken accessTokenParsed = (AccessToken)req.getSession().getAttribute("accessTokenParsed");
|
||||||
|
RefreshToken refreshTokenParsed = (RefreshToken)req.getSession().getAttribute("refreshTokenParsed");
|
||||||
|
|
||||||
Map<String, Object> attributes = new HashMap<String, Object>();
|
Map<String, Object> attributes = new HashMap<String, Object>();
|
||||||
attributes.put("requestURI", req.getRequestURI());
|
attributes.put("requestURI", req.getRequestURI());
|
||||||
attributes.put("code", req.getSession().getAttribute("code"));
|
attributes.put("code", req.getSession().getAttribute("code"));
|
||||||
attributes.put("accessToken", req.getSession().getAttribute("accessToken"));
|
attributes.put("accessToken", req.getSession().getAttribute("accessToken"));
|
||||||
attributes.put("refreshToken", req.getSession().getAttribute("refreshToken"));
|
attributes.put("refreshToken", req.getSession().getAttribute("refreshToken"));
|
||||||
|
attributes.put("accessTokenParsed", accessTokenParsed);
|
||||||
|
attributes.put("refreshTokenParsed", refreshTokenParsed);
|
||||||
|
attributes.put("actionDone", actionDone);
|
||||||
|
|
||||||
|
if (accessTokenParsed != null) {
|
||||||
|
attributes.put("accessTokenExpiration", Time.toDate(accessTokenParsed.getExpiration()).toString());
|
||||||
|
}
|
||||||
|
if (refreshTokenParsed != null) {
|
||||||
|
attributes.put("refreshTokenExpiration", Time.toDate(refreshTokenParsed.getExpiration()).toString());
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Writer out = new StringWriter();
|
Writer out = new StringWriter();
|
||||||
|
|
|
@ -19,30 +19,30 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<#if code??>
|
<#if code??>
|
||||||
Code: ${code}
|
<b>Code Available</b><br>
|
||||||
|
Code=${code} <br>
|
||||||
<hr />
|
<hr />
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if accessToken??>
|
<#if accessToken??>
|
||||||
<b>accessToken: </b> ${accessToken}
|
<b>Access Token Available</b><br>
|
||||||
<br />
|
AccessToken=${accessToken} <br>
|
||||||
<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px;" id="accessTokenParsed"></pre>
|
Username=${accessTokenParsed.preferredUsername} <br>
|
||||||
|
SessionState=${accessTokenParsed.sessionState} <br>
|
||||||
|
Expiration=${accessTokenExpiration} <br>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<script>
|
|
||||||
updateElementWithToken("${accessToken}", "accessTokenParsed");
|
|
||||||
</script>
|
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if refreshToken??>
|
<#if refreshToken??>
|
||||||
<b>refreshToken: </b> ${refreshToken}
|
<b>Refresh token available</b><br>
|
||||||
<br />
|
RefreshToken=${refreshToken} <br>
|
||||||
<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px;" id="refreshTokenParsed"></pre>
|
Expiration=${refreshTokenExpiration} <br>
|
||||||
<hr />
|
<hr />
|
||||||
|
</#if>
|
||||||
|
|
||||||
<script>
|
<#if actionDone??>
|
||||||
updateElementWithToken("${refreshToken}", "refreshTokenParsed");
|
RequestAction=${actionDone}
|
||||||
</script>
|
<hr />
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script src="/auth/js/keycloak.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button onclick="keycloak.login()">Login</button>
|
|
||||||
<button onclick="keycloak.logout()">Logout</button>
|
|
||||||
<button onclick="refreshToken(9999)">Refresh Token</button>
|
|
||||||
<button onclick="refreshToken(30)">Refresh Token (if <30s validity)</button>
|
|
||||||
<button onclick="loadProfile()">Get Profile</button>
|
|
||||||
<button onclick="output(keycloak.tokenParsed)">Show Token</button>
|
|
||||||
<button onclick="output(keycloak.refreshTokenParsed)">Show Refresh Token</button>
|
|
||||||
<button onclick="showExpires()">Show Expires</button>
|
|
||||||
<button onclick="output(keycloak.idToken)">Show ID Token</button>
|
|
||||||
<button onclick="output(keycloak)">Show Details</button>
|
|
||||||
<button onclick="output(keycloak.createLoginUrl())">Show Login URL</button>
|
|
||||||
<button onclick="output(keycloak.createLogoutUrl())">Show Logout URL</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>Result</h2>
|
|
||||||
<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px;" id="output"></pre>
|
|
||||||
|
|
||||||
<h2>Events</h2>
|
|
||||||
<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px;" id="events"></pre>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function loadProfile() {
|
|
||||||
keycloak.loadUserProfile().success(function(profile) {
|
|
||||||
output(profile);
|
|
||||||
}).error(function() {
|
|
||||||
output('Failed to load profile');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function refreshToken(minValidity) {
|
|
||||||
keycloak.updateToken(minValidity).success(function(refreshed) {
|
|
||||||
if (refreshed) {
|
|
||||||
output(keycloak.tokenParsed);
|
|
||||||
} else {
|
|
||||||
output('Token not refreshed, valid for ' + Math.round(keycloak.tokenParsed.exp - new Date().getTime() / 1000) + ' seconds');
|
|
||||||
}
|
|
||||||
}).error(function() {
|
|
||||||
output('Failed to refresh token');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showExpires() {
|
|
||||||
if (!keycloak.tokenParsed) {
|
|
||||||
output("Not authenticated");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var o = 'Token Expires:\t\t' + new Date(keycloak.tokenParsed.exp * 1000).toLocaleString() + '\n';
|
|
||||||
o += 'Token Expires in:\t' + Math.round(keycloak.tokenParsed.exp - new Date().getTime() / 1000) + ' seconds\n';
|
|
||||||
|
|
||||||
o += 'Refresh Token Expires:\t' + new Date(keycloak.refreshTokenParsed.exp * 1000).toLocaleString() + '\n';
|
|
||||||
o += 'Refresh Expires in:\t' + Math.round(keycloak.refreshTokenParsed.exp - new Date().getTime() / 1000) + ' seconds';
|
|
||||||
output(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
function output(data) {
|
|
||||||
if (typeof data === 'object') {
|
|
||||||
data = JSON.stringify(data, null, ' ');
|
|
||||||
}
|
|
||||||
document.getElementById('output').innerHTML = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function event(event) {
|
|
||||||
var e = document.getElementById('events').innerHTML;
|
|
||||||
document.getElementById('events').innerHTML = new Date().toLocaleString() + "\t" + event + "\n" + e;
|
|
||||||
}
|
|
||||||
|
|
||||||
var keycloak = Keycloak({
|
|
||||||
url: "/auth",
|
|
||||||
realm: "perf-realm",
|
|
||||||
clientId: "perf-app"
|
|
||||||
});
|
|
||||||
|
|
||||||
keycloak.onAuthSuccess = function () {
|
|
||||||
event('Auth Success');
|
|
||||||
};
|
|
||||||
|
|
||||||
keycloak.onAuthError = function () {
|
|
||||||
event('Auth Error');
|
|
||||||
};
|
|
||||||
|
|
||||||
keycloak.onAuthRefreshSuccess = function () {
|
|
||||||
event('Auth Refresh Success');
|
|
||||||
};
|
|
||||||
|
|
||||||
keycloak.onAuthRefreshError = function () {
|
|
||||||
event('Auth Refresh Error');
|
|
||||||
};
|
|
||||||
|
|
||||||
keycloak.onAuthLogout = function () {
|
|
||||||
event('Auth Logout');
|
|
||||||
};
|
|
||||||
|
|
||||||
keycloak.init().success(function(authenticated) {
|
|
||||||
output('Init Success (' + (authenticated ? 'Authenticated' : 'Not Authenticated') + ')');
|
|
||||||
}).error(function() {
|
|
||||||
output('Init Error');
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -59,7 +59,7 @@
|
||||||
"redirectUris": [
|
"redirectUris": [
|
||||||
"http://localhost:8081/perf-app/*"
|
"http://localhost:8081/perf-app/*"
|
||||||
],
|
],
|
||||||
"adminUrl": "http://localhost:8081/perf-app/logout",
|
"adminUrl": "http://localhost:8081/perf-app/perf-servlet",
|
||||||
"secret": "password"
|
"secret": "password"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue