Fixes to account referrer to allow configurable referrer uri based on app redirect uri
This commit is contained in:
parent
b5bdeae2a2
commit
702ae0307e
10 changed files with 55 additions and 53 deletions
|
@ -42,6 +42,7 @@
|
||||||
<div>
|
<div>
|
||||||
<button onclick="keycloak.logout()">Log out</button>
|
<button onclick="keycloak.logout()">Log out</button>
|
||||||
<button onclick="keycloak.updateToken()">Refresh token</button>
|
<button onclick="keycloak.updateToken()">Refresh token</button>
|
||||||
|
<button onclick="keycloak.accountManagement()">Manage account</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<table>
|
<table>
|
||||||
|
|
|
@ -25,6 +25,6 @@ public interface Account {
|
||||||
|
|
||||||
public Account setRealm(RealmModel realm);
|
public Account setRealm(RealmModel realm);
|
||||||
|
|
||||||
public Account setReferrer(String referrer);
|
public Account setReferrer(String[] referrer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class FreeMarkerAccount implements Account {
|
||||||
private UserModel user;
|
private UserModel user;
|
||||||
private Response.Status status = Response.Status.OK;
|
private Response.Status status = Response.Status.OK;
|
||||||
private RealmModel realm;
|
private RealmModel realm;
|
||||||
private String referrer;
|
private String[] referrer;
|
||||||
|
|
||||||
public static enum MessageType {SUCCESS, WARNING, ERROR}
|
public static enum MessageType {SUCCESS, WARNING, ERROR}
|
||||||
|
|
||||||
|
@ -82,9 +82,8 @@ public class FreeMarkerAccount implements Account {
|
||||||
attributes.put("message", new MessageBean(messages.containsKey(message) ? messages.getProperty(message) : message, messageType));
|
attributes.put("message", new MessageBean(messages.containsKey(message) ? messages.getProperty(message) : message, messageType));
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationModel referrerApp = getReferrer();
|
if (referrer != null) {
|
||||||
if (referrerApp != null) {
|
attributes.put("referrer", new ReferrerBean(referrer));
|
||||||
attributes.put("referrer", new ReferrerBean(referrerApp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes.put("url", new UrlBean(realm, theme, baseUri));
|
attributes.put("url", new UrlBean(realm, theme, baseUri));
|
||||||
|
@ -114,16 +113,6 @@ public class FreeMarkerAccount implements Account {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApplicationModel getReferrer() {
|
|
||||||
if (referrer != null) {
|
|
||||||
ApplicationModel app = realm.getApplicationByName(referrer);
|
|
||||||
if (app != null) {
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Account setError(String message) {
|
public Account setError(String message) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
@ -164,7 +153,7 @@ public class FreeMarkerAccount implements Account {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Account setReferrer(String referrer) {
|
public Account setReferrer(String[] referrer) {
|
||||||
this.referrer = referrer;
|
this.referrer = referrer;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,22 @@
|
||||||
package org.keycloak.account.freemarker.model;
|
package org.keycloak.account.freemarker.model;
|
||||||
|
|
||||||
import org.keycloak.models.ApplicationModel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
public class ReferrerBean {
|
public class ReferrerBean {
|
||||||
|
|
||||||
private ApplicationModel referrer;
|
private String[] referrer;
|
||||||
|
|
||||||
public ReferrerBean(ApplicationModel referrer) {
|
public ReferrerBean(String[] referrer) {
|
||||||
this.referrer = referrer;
|
this.referrer = referrer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return referrer.getName();
|
return referrer[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBaseUrl() {
|
public String getUrl() {
|
||||||
return referrer.getBaseUrl();
|
return referrer[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<div class="navbar-collapse navbar-collapse-1">
|
<div class="navbar-collapse navbar-collapse-1">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<ul class="nav navbar-nav navbar-utility">
|
<ul class="nav navbar-nav navbar-utility">
|
||||||
<#if referrer?has_content && referrer.baseUrl?has_content><li><a href="${referrer.baseUrl}">Back to ${referrer.name}</a></li></#if>
|
<#if referrer?has_content && referrer.url?has_content><li><a href="${referrer.url}" id="referrer">Back to ${referrer.name}</a></li></#if>
|
||||||
<li><a href="${url.logoutUrl}">Sign Out</a></li>
|
<li><a href="${url.logoutUrl}">Sign Out</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -103,10 +103,11 @@ var Keycloak = function (config) {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
kc.createAccountUrl = function() {
|
kc.createAccountUrl = function(options) {
|
||||||
var url = getRealmUrl()
|
var url = getRealmUrl()
|
||||||
+ '/account'
|
+ '/account'
|
||||||
+ '?referrer=' + kc.clientId;
|
+ '?referrer=' + kc.clientId
|
||||||
|
+ '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options));
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class AccountService {
|
||||||
|
|
||||||
Account account = AccountLoader.load().createAccount(uriInfo).setRealm(realm).setUser(auth.getUser());
|
Account account = AccountLoader.load().createAccount(uriInfo).setRealm(realm).setUser(auth.getUser());
|
||||||
|
|
||||||
String referrer = getReferrer();
|
String[] referrer = getReferrer();
|
||||||
if (referrer != null) {
|
if (referrer != null) {
|
||||||
account.setReferrer(referrer);
|
account.setReferrer(referrer);
|
||||||
}
|
}
|
||||||
|
@ -377,13 +377,17 @@ public class AccountService {
|
||||||
uriBuilder.queryParam("path", path);
|
uriBuilder.queryParam("path", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
String referrer = getReferrer();
|
String referrer = uriInfo.getQueryParameters().getFirst("referrer");
|
||||||
if (referrer != null) {
|
if (referrer != null) {
|
||||||
uriBuilder.queryParam("referrer", referrer);
|
uriBuilder.queryParam("referrer", referrer);
|
||||||
}
|
}
|
||||||
|
|
||||||
URI accountUri = uriBuilder.build(realm.getName());
|
String referrerUri = uriInfo.getQueryParameters().getFirst("referrer_uri");
|
||||||
|
if (referrerUri != null) {
|
||||||
|
uriBuilder.queryParam("referrer_uri", referrerUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
URI accountUri = uriBuilder.build(realm.getName());
|
||||||
|
|
||||||
oauth.setStateCookiePath(accountUri.getRawPath());
|
oauth.setStateCookiePath(accountUri.getRawPath());
|
||||||
return oauth.redirect(uriInfo, accountUri.toString());
|
return oauth.redirect(uriInfo, accountUri.toString());
|
||||||
|
@ -397,20 +401,34 @@ public class AccountService {
|
||||||
return auth;
|
return auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getReferrer() {
|
private String[] getReferrer() {
|
||||||
String referrer = uriInfo.getQueryParameters().getFirst("referrer");
|
String referrer = uriInfo.getQueryParameters().getFirst("referrer");
|
||||||
if (referrer != null) {
|
if (referrer == null) {
|
||||||
return referrer;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String referrerUrl = headers.getHeaderString("Referer");
|
String referrerUri = uriInfo.getQueryParameters().getFirst("referrer_uri");
|
||||||
if (referrerUrl != null) {
|
|
||||||
for (ApplicationModel a : realm.getApplications()) {
|
ApplicationModel application = realm.getApplicationByName(referrer);
|
||||||
if (a.getBaseUrl() != null && referrerUrl.startsWith(a.getBaseUrl())) {
|
if (application != null) {
|
||||||
return a.getName();
|
if (referrerUri != null) {
|
||||||
|
referrerUri = TokenService.verifyRedirectUri(referrerUri, application);
|
||||||
|
} else {
|
||||||
|
referrerUri = application.getBaseUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (referrerUri != null) {
|
||||||
|
return new String[] { referrer, referrerUri };
|
||||||
|
}
|
||||||
|
} else if (referrerUri != null) {
|
||||||
|
ClientModel client = realm.getOAuthClient(referrer);
|
||||||
|
if (client != null) {
|
||||||
|
referrerUri = TokenService.verifyRedirectUri(referrerUri, application);
|
||||||
|
|
||||||
|
if (referrerUri != null) {
|
||||||
|
return new String[] { referrer, referrerUri };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -107,19 +107,7 @@ public class AccountTest {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
public void returnToAppFromHeader() {
|
|
||||||
appPage.open();
|
|
||||||
appPage.openAccount();
|
|
||||||
loginPage.login("test-user@localhost", "password");
|
|
||||||
|
|
||||||
Assert.assertTrue(profilePage.isCurrent());
|
|
||||||
profilePage.backToApplication();
|
|
||||||
|
|
||||||
Assert.assertTrue(appPage.isCurrent());
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Test
|
|
||||||
public void returnToAppFromQueryParam() {
|
public void returnToAppFromQueryParam() {
|
||||||
driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app");
|
driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app");
|
||||||
loginPage.login("test-user@localhost", "password");
|
loginPage.login("test-user@localhost", "password");
|
||||||
|
@ -127,6 +115,13 @@ public class AccountTest {
|
||||||
profilePage.backToApplication();
|
profilePage.backToApplication();
|
||||||
|
|
||||||
Assert.assertTrue(appPage.isCurrent());
|
Assert.assertTrue(appPage.isCurrent());
|
||||||
|
|
||||||
|
driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app&referrer_uri=http://localhost:8081/app?test");
|
||||||
|
Assert.assertTrue(profilePage.isCurrent());
|
||||||
|
profilePage.backToApplication();
|
||||||
|
|
||||||
|
Assert.assertTrue(appPage.isCurrent());
|
||||||
|
Assert.assertEquals(appPage.baseUrl + "?test", driver.getCurrentUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
|
||||||
private WebElement emailInput;
|
private WebElement emailInput;
|
||||||
|
|
||||||
|
|
||||||
@FindBy(linkText = "Back to application")
|
@FindBy(id = "referrer")
|
||||||
private WebElement backToApplicationLink;
|
private WebElement backToApplicationLink;
|
||||||
|
|
||||||
@FindBy(css = "button[type=\"submit\"]")
|
@FindBy(css = "button[type=\"submit\"]")
|
||||||
|
|
|
@ -30,7 +30,7 @@ import org.openqa.selenium.support.FindBy;
|
||||||
*/
|
*/
|
||||||
public class AppPage extends AbstractPage {
|
public class AppPage extends AbstractPage {
|
||||||
|
|
||||||
private String baseUrl = "http://localhost:8081/app";
|
public static final String baseUrl = "http://localhost:8081/app";
|
||||||
|
|
||||||
@FindBy(id = "account")
|
@FindBy(id = "account")
|
||||||
private WebElement accountLink;
|
private WebElement accountLink;
|
||||||
|
|
Loading…
Reference in a new issue