KEYCLOAK-181
Link back to application from account management pages
This commit is contained in:
parent
2059283e99
commit
85eeb415e1
25 changed files with 256 additions and 148 deletions
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -31,6 +31,8 @@ public class ApplicationEntity implements Serializable {
|
|||
private boolean surrogateAuthRequired;
|
||||
@AttributeValue
|
||||
private String managementUrl;
|
||||
@AttributeValue
|
||||
private String baseUrl;
|
||||
|
||||
@AttributeValue
|
||||
private String[] defaultRoles;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
{
|
||||
"name": "test-app",
|
||||
"enabled": true,
|
||||
"baseUrl": "http://localhost:8081/app",
|
||||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"credentials": [
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue