KEYCLOAK-181

Link back to application from account management pages
This commit is contained in:
Stian Thorgersen 2013-11-28 13:48:30 +00:00
parent 2059283e99
commit 85eeb415e1
25 changed files with 256 additions and 148 deletions

View file

@ -46,6 +46,14 @@
<label for="enabled" class="control-label">Enabled</label>
<input ng-model="application.enabled" name="enabled" id="enabled" onoffswitch />
</div>
<div class="form-group">
<label for="baseUrl" class="control-label">Base URL</label>
<div class="controls">
<input class="input-small" type="text" name="baseUrl" id="baseUrl"
data-ng-model="application.baseUrl">
</div>
</div>
<div class="form-group">
<label for="adminUrl" class="control-label">Admin URL</label>

View file

@ -36,11 +36,12 @@
<tr data-ng-show="applications.length > 0">
<th>Application Name</th>
<th>Enabled</th>
<th>Base URL</th>
</tr>
</thead>
<tfoot data-ng-show="applications && applications.length > 5"> <!-- todo -->
<tr>
<td colspan="2">
<td colspan="3">
<div class="table-nav">
<a href="#" class="first disabled">First page</a><a href="#" class="prev disabled">Previous
page</a><span><strong>1-8</strong> of <strong>10</strong></span><a href="#"
@ -54,6 +55,7 @@
<tr ng-repeat="app in applications">
<td><a href="#/realms/{{realm.id}}/applications/{{app.id}}">{{app.name}}</a></td>
<td>{{app.enabled}}</td>
<td ng-class="{'text-muted': !app.baseUrl}">{{app.baseUrl || "Not defined"}}</td>
</tr>
</tbody>
</table>

View file

@ -12,6 +12,7 @@ public class ApplicationRepresentation {
protected String id;
protected String name;
protected String adminUrl;
protected String baseUrl;
protected boolean surrogateAuthRequired;
protected boolean enabled;
protected List<CredentialRepresentation> credentials;
@ -89,6 +90,14 @@ public class ApplicationRepresentation {
this.adminUrl = adminUrl;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public List<CredentialRepresentation> getCredentials() {
return credentials;
}

View file

@ -10,6 +10,7 @@ import java.util.List;
public class OAuthClientRepresentation {
protected String id;
protected String name;
protected String baseUrl;
protected List<String> redirectUris;
protected List<String> webOrigins;
protected boolean enabled;
@ -39,6 +40,14 @@ public class OAuthClientRepresentation {
this.enabled = enabled;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public List<String> getRedirectUris() {
return redirectUris;
}

View file

@ -36,6 +36,8 @@ public class UrlBean {
private boolean socialRegistration;
private String referrerURI;
public boolean isSocialRegistration() {
return socialRegistration;
}
@ -44,9 +46,10 @@ public class UrlBean {
this.socialRegistration = socialRegistration;
}
public UrlBean(RealmBean realm, URI baseURI){
public UrlBean(RealmBean realm, URI baseURI, String referrerURI){
this.realm = realm;
this.baseURI = baseURI;
this.referrerURI = referrerURI;
}
public RealmBean getRealm() {
@ -136,4 +139,8 @@ public class UrlBean {
return Urls.loginActionEmailVerification(baseURI, realm.getId()).toString();
}
public String getReferrerURI() {
return referrerURI;
}
}

View file

@ -35,6 +35,7 @@ import org.keycloak.forms.TemplateBean;
import org.keycloak.forms.TotpBean;
import org.keycloak.forms.UrlBean;
import org.keycloak.forms.UserBean;
import org.keycloak.models.ApplicationModel;
import org.keycloak.services.FormService;
import org.keycloak.services.resources.flows.Pages;
@ -54,22 +55,22 @@ public class FormServiceImpl implements FormService {
private static final String ID = "FormServiceId";
private static final String BUNDLE = "org.keycloak.forms.messages";
private final Map<String, Command> commandMap = new HashMap<String,Command>();
private final Map<String, CommandCommon> commandMap = new HashMap<String, CommandCommon>();
public FormServiceImpl(){
commandMap.put(Pages.LOGIN, new CommandLogin());
commandMap.put(Pages.REGISTER, new CommandRegister());
commandMap.put(Pages.ACCOUNT, new CommandAccount());
commandMap.put(Pages.LOGIN_UPDATE_PROFILE, new CommandPassword());
commandMap.put(Pages.PASSWORD, new CommandPassword());
commandMap.put(Pages.LOGIN_RESET_PASSWORD, new CommandPassword());
commandMap.put(Pages.LOGIN_UPDATE_PASSWORD, new CommandPassword());
commandMap.put(Pages.ACCESS, new CommandAccess());
commandMap.put(Pages.SOCIAL, new CommandSocial());
commandMap.put(Pages.ACCOUNT, new CommandCommon());
commandMap.put(Pages.LOGIN_UPDATE_PROFILE, new CommandCommon());
commandMap.put(Pages.PASSWORD, new CommandCommon());
commandMap.put(Pages.LOGIN_RESET_PASSWORD, new CommandCommon());
commandMap.put(Pages.LOGIN_UPDATE_PASSWORD, new CommandCommon());
commandMap.put(Pages.ACCESS, new CommandCommon());
commandMap.put(Pages.SOCIAL, new CommandCommon());
commandMap.put(Pages.TOTP, new CommandTotp());
commandMap.put(Pages.LOGIN_CONFIG_TOTP, new CommandTotp());
commandMap.put(Pages.LOGIN_TOTP, new CommandLoginTotp());
commandMap.put(Pages.LOGIN_VERIFY_EMAIL, new CommandVerifyEmail());
commandMap.put(Pages.LOGIN_VERIFY_EMAIL, new CommandCommon());
commandMap.put(Pages.OAUTH_GRANT, new CommandOAuthGrant());
}
@ -117,121 +118,69 @@ public class FormServiceImpl implements FormService {
return out.toString();
}
private class CommandTotp implements Command {
private class CommandCommon {
protected RealmBean realm;
protected UrlBean url;
protected UserBean user;
protected LoginBean login;
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
realm = new RealmBean(dataBean.getRealm());
String referrer = dataBean.getQueryParam("referrer");
String referrerUri = null;
if (referrer != null) {
for (ApplicationModel a : dataBean.getRealm().getApplications()) {
if (a.getName().equals(referrer)) {
referrerUri = a.getBaseUrl();
break;
}
}
}
url = new UrlBean(realm, dataBean.getBaseURI(), referrerUri);
url.setSocialRegistration(dataBean.getSocialRegistration());
user = new UserBean(dataBean.getUserModel());
login = new LoginBean(realm, dataBean.getFormData());
attributes.put("realm", realm);
attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
UserBean user = new UserBean(dataBean.getUserModel());
attributes.put("url", url);
attributes.put("user", user);
TotpBean totp = new TotpBean(user, dataBean.getContextPath());
attributes.put("totp", totp);
attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
attributes.put("login", login);
}
}
private class CommandSocial implements Command {
private class CommandTotp extends CommandCommon {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
attributes.put("user", new UserBean(dataBean.getUserModel()));
attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
super.exec(attributes, dataBean);
attributes.put("totp", new TotpBean(user, dataBean.getContextPath()));
}
}
private class CommandEmail implements Command {
private class CommandLoginTotp extends CommandCommon {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
}
}
private class CommandPassword implements Command {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
attributes.put("realm", realm);
attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
attributes.put("user", new UserBean(dataBean.getUserModel()));
attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
}
}
private class CommandLoginTotp implements Command {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
attributes.put("realm", realm);
UrlBean url = new UrlBean(realm, dataBean.getBaseURI());
url.setSocialRegistration(dataBean.getSocialRegistration());
attributes.put("url", url);
attributes.put("user", new UserBean(dataBean.getUserModel()));
attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
super.exec(attributes, dataBean);
RegisterBean register = new RegisterBean(dataBean.getFormData(), dataBean.getSocialRegistration());
SocialBean social = new SocialBean(realm, dataBean.getSocialProviders(), register, url);
attributes.put("social", social);
}
}
private class CommandAccess implements Command {
private class CommandLogin extends CommandCommon {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
attributes.put("realm", realm);
attributes.put("user", new UserBean(dataBean.getUserModel()));
attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
}
}
private class CommandAccount implements Command {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
attributes.put("realm", realm);
attributes.put("url", new UrlBean(realm, dataBean.getBaseURI()));
attributes.put("user", new UserBean(dataBean.getUserModel()));
attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
}
}
private class CommandLogin implements Command {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
attributes.put("realm", realm);
UrlBean url = new UrlBean(realm, dataBean.getBaseURI());
url.setSocialRegistration(dataBean.getSocialRegistration());
attributes.put("url", url);
attributes.put("user", new UserBean(dataBean.getUserModel()));
attributes.put("login", new LoginBean(realm, dataBean.getFormData()));
super.exec(attributes, dataBean);
RegisterBean register = new RegisterBean(dataBean.getFormData(), dataBean.getSocialRegistration());
SocialBean social = new SocialBean(realm, dataBean.getSocialProviders(), register, url);
attributes.put("social", social);
}
}
private class CommandRegister implements Command {
private class CommandRegister extends CommandCommon {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
attributes.put("realm", realm);
UrlBean url = new UrlBean(realm, dataBean.getBaseURI());
url.setSocialRegistration(dataBean.getSocialRegistration());
attributes.put("url", url);
attributes.put("user", new UserBean(dataBean.getUserModel()));
super.exec(attributes, dataBean);
RegisterBean register = new RegisterBean(dataBean.getFormData(), dataBean.getSocialRegistration());
attributes.put("register", register);
@ -241,8 +190,9 @@ public class FormServiceImpl implements FormService {
}
}
private class CommandOAuthGrant implements Command {
private class CommandOAuthGrant extends CommandCommon {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
super.exec(attributes, dataBean);
OAuthGrantBean oauth = new OAuthGrantBean();
oauth.setAction(dataBean.getOAuthAction());
@ -255,22 +205,4 @@ public class FormServiceImpl implements FormService {
}
}
private class CommandVerifyEmail implements Command {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
RealmBean realm = new RealmBean(dataBean.getRealm());
attributes.put("realm", realm);
UrlBean url = new UrlBean(realm, dataBean.getBaseURI());
url.setSocialRegistration(dataBean.getSocialRegistration());
attributes.put("url", url);
}
}
private interface Command {
public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean);
}
}

View file

@ -27,7 +27,7 @@
</div>
</fieldset>
<div class="form-actions">
<#--a href="#">« Back to my application</a-->
<#if url.referrerURI??><a href="${url.referrerURI}">Back to application</a></#if>
<button type="submit" class="primary">Save</button>
<button type="submit">Cancel</button>
</div>

View file

@ -23,7 +23,7 @@
</div>
</fieldset>
<div class="form-actions">
<#--a href="#">« Back to my application</a-->
<#if url.referrerURI??><a href="${url.referrerURI}">Back to application</a></#if>
<button type="submit" class="primary">Save</button>
<button type="submit">Cancel</button>
</div>

View file

@ -54,6 +54,7 @@
<input type="hidden" id="totpSecret" name="totpSecret" value="${totp.totpSecret}" />
</div>
<div class="form-actions">
<#if url.referrerURI??><a href="${url.referrerURI}">Back to application</a></#if>
<button type="submit" class="primary">Submit</button>
</div>
</form>

View file

@ -29,6 +29,10 @@ public interface ApplicationModel extends RoleContainerModel, RoleMapperModel, S
void setManagementUrl(String url);
String getBaseUrl();
void setBaseUrl(String url);
List<String> getDefaultRoles();
void addDefaultRole(String name);

View file

@ -82,6 +82,16 @@ public class ApplicationAdapter implements ApplicationModel {
application.setManagementUrl(url);
}
@Override
public String getBaseUrl() {
return application.getBaseUrl();
}
@Override
public void setBaseUrl(String url) {
application.setBaseUrl(url);
}
@Override
public RoleModel getRole(String name) {
Collection<RoleEntity> roles = application.getRoles();

View file

@ -25,6 +25,7 @@ public class ApplicationEntity {
private String name;
private boolean enabled;
private boolean surrogateAuthRequired;
private String baseUrl;
private String managementUrl;
@OneToOne(fetch = FetchType.EAGER)
@ -58,6 +59,14 @@ public class ApplicationEntity {
this.surrogateAuthRequired = surrogateAuthRequired;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getManagementUrl() {
return managementUrl;
}

View file

@ -105,6 +105,17 @@ public class ApplicationAdapter implements ApplicationModel {
updateApplication();
}
@Override
public String getBaseUrl() {
return applicationData.getBaseUrl();
}
@Override
public void setBaseUrl(String url) {
applicationData.setBaseUrl(url);
updateApplication();
}
@Override
public RoleAdapter getRole(String name) {
Role role = SampleModel.getRole(getIdm(), name);

View file

@ -13,6 +13,7 @@ public class ApplicationData extends AbstractPartition {
private boolean enabled;
private boolean surrogateAuthRequired;
private String managementUrl;
private String baseUrl;
private User resourceUser;
private String[] defaultRoles;
@ -58,6 +59,15 @@ public class ApplicationData extends AbstractPartition {
this.surrogateAuthRequired = surrogateAuthRequired;
}
@AttributeProperty
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
@AttributeProperty
public String getManagementUrl() {
return managementUrl;

View file

@ -31,6 +31,8 @@ public class ApplicationEntity implements Serializable {
private boolean surrogateAuthRequired;
@AttributeValue
private String managementUrl;
@AttributeValue
private String baseUrl;
@AttributeValue
private String[] defaultRoles;

View file

@ -53,6 +53,7 @@ public interface FormService {
private FormFlows.MessageType messageType;
private MultivaluedMap<String, String> formData;
private Map<String, String> queryParams;
private URI baseURI;
private List<SocialProvider> socialProviders;
@ -87,10 +88,11 @@ public interface FormService {
private String contextPath;
public FormServiceDataBean(RealmModel realm, UserModel userModel, MultivaluedMap<String, String> formData, String message) {
public FormServiceDataBean(RealmModel realm, UserModel userModel, MultivaluedMap<String, String> formData, Map<String, String> queryParams, String message) {
this.realm = realm;
this.userModel = userModel;
this.formData = formData;
this.queryParams = queryParams;
this.message = message;
socialProviders = new LinkedList<SocialProvider>();
@ -125,6 +127,16 @@ public interface FormService {
return formData;
}
public Map<String, String> getQueryParams() {
return queryParams;
}
public String getQueryParam(String key) {
return queryParams != null ? queryParams.get(key) : null;
}
public void setFormData(MultivaluedMap<String, String> formData) {
this.formData = formData;
}

View file

@ -50,6 +50,7 @@ public class ApplicationManager {
applicationModel.setEnabled(resourceRep.isEnabled());
applicationModel.setManagementUrl(resourceRep.getAdminUrl());
applicationModel.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
applicationModel.updateApplication();
UserModel resourceUser = applicationModel.getApplicationUser();
@ -128,6 +129,7 @@ public class ApplicationManager {
resource.setName(rep.getName());
resource.setEnabled(rep.isEnabled());
resource.setManagementUrl(rep.getAdminUrl());
resource.setBaseUrl(rep.getBaseUrl());
resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
resource.updateApplication();
@ -153,6 +155,7 @@ public class ApplicationManager {
rep.setEnabled(applicationModel.isEnabled());
rep.setAdminUrl(applicationModel.getManagementUrl());
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
rep.setBaseUrl(applicationModel.getBaseUrl());
Set<String> redirectUris = applicationModel.getApplicationUser().getRedirectUris();
if (redirectUris != null) {

View file

@ -46,6 +46,7 @@ import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.Providers;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
/**
@ -89,7 +90,15 @@ public class AccountService {
if (!hasAccess(auth)) {
return noAccess();
}
return Flows.forms(realm, request, uriInfo).setUser(auth.getUser()).forwardToForm(template);
FormFlows forms = Flows.forms(realm, request, uriInfo).setUser(auth.getUser());
String referrer = getReferrer();
if (referrer != null) {
forms.setQueryParam("referrer", referrer);
}
return forms.forwardToForm(template);
} else {
return login(path);
}
@ -321,11 +330,8 @@ public class AccountService {
throw new BadRequestException();
}
UriBuilder redirectBuilder = Urls.accountBase(uriInfo.getBaseUri());
if (path != null) {
redirectBuilder.path(path);
}
URI redirectUri = redirectBuilder.build(realm.getId());
URI accountUri = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getId());
URI redirectUri = path != null ? accountUri.resolve(path) : accountUri;
NewCookie cookie = authManager.createAccountIdentityCookie(realm, accessCode.getUser(), client, Urls.accountBase(uriInfo.getBaseUri()).build(realm.getId()));
return Response.status(302).cookie(cookie).location(redirectUri).build();
@ -353,6 +359,11 @@ public class AccountService {
URI accountUri = Urls.accountPageBuilder(uriInfo.getBaseUri()).path(AccountService.class, "loginRedirect").build(realm.getId());
String referrer = getReferrer();
if (referrer != null) {
path = (path != null ? path : "") + "?referrer=" + referrer;
}
oauth.setStateCookiePath(accountUri.getPath());
return oauth.redirect(uriInfo, accountUri.toString(), path);
}
@ -393,4 +404,23 @@ public class AccountService {
return application.hasRole(user, role);
}
private String getReferrer() {
String referrer = uriInfo.getQueryParameters().getFirst("referrer");
if (referrer != null) {
return referrer;
}
String referrerUrl = headers.getHeaderString("Referer");
if (referrerUrl != null) {
for (ApplicationModel a : realm.getApplications()) {
if (a.getBaseUrl() != null && referrerUrl.startsWith(a.getBaseUrl())) {
return a.getName();
}
}
return null;
}
return null;
}
}

View file

@ -39,18 +39,16 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class FormFlows {
public static final String DATA = "KEYCLOAK_FORMS_DATA";
public static final String ERROR_MESSAGE = "KEYCLOAK_FORMS_ERROR_MESSAGE";
public static final String USER = UserModel.class.getName();
public static final String SOCIAL_REGISTRATION = "socialRegistration";
public static final String CODE = "code";
// TODO refactor/rename "error" to "message" everywhere where it makes sense
@ -61,6 +59,8 @@ public class FormFlows {
private MultivaluedMap<String, String> formData;
private Map<String, String> queryParams;
private RealmModel realm;
private HttpRequest request;
@ -118,6 +118,12 @@ public class FormFlows {
uriBuilder.queryParam(CODE, accessCode.getCode());
}
if (queryParams != null) {
for (Map.Entry<String, String> q : queryParams.entrySet()) {
uriBuilder.replaceQueryParam(q.getKey(), q.getValue());
}
}
URI baseURI = uriBuilder.build();
formDataBean.setBaseURI(baseURI);
@ -140,7 +146,7 @@ public class FormFlows {
public Response forwardToForm(String template) {
FormService.FormServiceDataBean formDataBean = new FormService.FormServiceDataBean(realm, userModel, formData, error);
FormService.FormServiceDataBean formDataBean = new FormService.FormServiceDataBean(realm, userModel, formData, queryParams, error);
formDataBean.setMessageType(messageType);
return forwardToForm(template, formDataBean);
@ -192,7 +198,7 @@ public class FormFlows {
public Response forwardToOAuthGrant(){
FormService.FormServiceDataBean formDataBean = new FormService.FormServiceDataBean(realm, userModel, formData, error);
FormService.FormServiceDataBean formDataBean = new FormService.FormServiceDataBean(realm, userModel, formData, queryParams, error);
formDataBean.setOAuthRealmRolesRequested((List<RoleModel>) request.getAttribute("realmRolesRequested"));
formDataBean.setOAuthResourceRolesRequested((MultivaluedMap<String, RoleModel>) request.getAttribute("resourceRolesRequested"));
@ -208,6 +214,14 @@ public class FormFlows {
return this;
}
public FormFlows setQueryParam(String key, String value) {
if (queryParams == null) {
queryParams = new HashMap<String, String>();
}
queryParams.put(key, value);
return this;
}
public FormFlows setError(String error) {
this.error = error;
return this;

View file

@ -40,6 +40,7 @@ public class ApplicationModelTest extends AbstractKeycloakServerTest {
realm = manager.createRealm("original");
application = realm.addApplication("application");
application.setBaseUrl("http://base");
application.setManagementUrl("http://management");
application.setName("app-name");
application.addRole("role-1");
@ -82,6 +83,7 @@ public class ApplicationModelTest extends AbstractKeycloakServerTest {
public static void assertEquals(ApplicationModel expected, ApplicationModel actual) {
Assert.assertEquals(expected.getName(), actual.getName());
Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl());
Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl());
Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());

View file

@ -39,23 +39,11 @@ import java.util.List;
*/
public class ApplicationServlet extends HttpServlet {
private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String title = "";
String body = "";
StringBuffer sb = req.getRequestURL();
sb.append("?");
sb.append(req.getQueryString());
List<NameValuePair> query = null;
try {
query = URLEncodedUtils.parse(new URI(sb.toString()), "UTF-8");
} catch (URISyntaxException e) {
throw new ServletException(e);
}
if (req.getRequestURI().endsWith("auth")) {
title = "AUTH_RESPONSE";
} else if (req.getRequestURI().endsWith("logout")) {
@ -65,7 +53,11 @@ public class ApplicationServlet extends HttpServlet {
}
PrintWriter pw = resp.getWriter();
pw.printf("<html><head><title>%s</title></head><body>%s</body>", title, body);
pw.printf("<html><head><title>%s</title></head><body>", title);
pw.printf(LINK, "http://localhost:8081/auth-server/rest/realms/test/account", "account", "account");
pw.print("</body></html>");
pw.flush();
}

View file

@ -111,6 +111,28 @@ public class AccountTest {
});
}
@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() {
driver.navigate().to(AccountUpdateProfilePage.PATH + "?referrer=test-app");
loginPage.login("test-user@localhost", "password");
Assert.assertTrue(profilePage.isCurrent());
profilePage.backToApplication();
Assert.assertTrue(appPage.isCurrent());
}
@Test
public void changePassword() {
changePasswordPage.open();

View file

@ -30,7 +30,7 @@ import org.openqa.selenium.support.FindBy;
*/
public class AccountUpdateProfilePage extends AbstractAccountPage {
private static String PATH = Constants.AUTH_SERVER_ROOT + "/rest/realms/test/account";
public static String PATH = Constants.AUTH_SERVER_ROOT + "/rest/realms/test/account";
@FindBy(id = "firstName")
private WebElement firstNameInput;
@ -41,6 +41,10 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
@FindBy(id = "email")
private WebElement emailInput;
@FindBy(linkText = "Back to application")
private WebElement backToApplicationLink;
@FindBy(css = "button[type=\"submit\"]")
private WebElement submitButton;
@ -78,6 +82,10 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
driver.navigate().to(PATH);
}
public void backToApplication() {
backToApplicationLink.click();
}
public boolean isSuccess(){
return feedbackMessage != null && "Success!".equals(feedbackMessage.getText());
}

View file

@ -22,6 +22,9 @@
package org.keycloak.testsuite.pages;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@ -29,6 +32,9 @@ public class AppPage extends AbstractPage {
private String baseUrl = "http://localhost:8081/app";
@FindBy(id = "account")
private WebElement accountLink;
@Override
public void open() {
driver.navigate().to(baseUrl);
@ -43,6 +49,10 @@ public class AppPage extends AbstractPage {
return RequestType.valueOf(driver.getTitle());
}
public void openAccount() {
accountLink.click();
}
public enum RequestType {
AUTH_RESPONSE, LOGOUT_REQUEST, APP_REQUEST
}

View file

@ -72,6 +72,7 @@
{
"name": "test-app",
"enabled": true,
"baseUrl": "http://localhost:8081/app",
"adminUrl": "http://localhost:8081/app/logout",
"credentials": [
{