[KEYCLOAK-14346] Base URL for applications is broken
This commit is contained in:
parent
76717134ba
commit
1434f14663
5 changed files with 56 additions and 10 deletions
|
@ -10,7 +10,9 @@ public class ClientRepresentation {
|
|||
private boolean userConsentRequired;
|
||||
private boolean inUse;
|
||||
private boolean offlineAccess;
|
||||
private String rootUrl;
|
||||
private String baseUrl;
|
||||
private String effectiveUrl;
|
||||
private ConsentRepresentation consent;
|
||||
|
||||
public String getClientId() {
|
||||
|
@ -61,6 +63,14 @@ public class ClientRepresentation {
|
|||
this.offlineAccess = offlineAccess;
|
||||
}
|
||||
|
||||
public String getRootUrl() {
|
||||
return rootUrl;
|
||||
}
|
||||
|
||||
public void setRootUrl(String rootUrl) {
|
||||
this.rootUrl = rootUrl;
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return baseUrl;
|
||||
}
|
||||
|
@ -69,6 +79,14 @@ public class ClientRepresentation {
|
|||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public String getEffectiveUrl() {
|
||||
return effectiveUrl;
|
||||
}
|
||||
|
||||
public void setEffectiveUrl(String effectiveUrl) {
|
||||
this.effectiveUrl = effectiveUrl;
|
||||
}
|
||||
|
||||
public ConsentRepresentation getConsent() {
|
||||
return consent;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.keycloak.services.managers.Auth;
|
|||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.services.resources.Cors;
|
||||
import org.keycloak.services.resources.account.resources.ResourcesService;
|
||||
import org.keycloak.services.util.ResolveRelative;
|
||||
import org.keycloak.storage.ReadOnlyException;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
|
@ -291,7 +292,9 @@ public class AccountRestService {
|
|||
representation.setUserConsentRequired(model.isConsentRequired());
|
||||
representation.setInUse(inUseClients.contains(model.getClientId()));
|
||||
representation.setOfflineAccess(offlineClients.contains(model.getClientId()));
|
||||
representation.setRootUrl(model.getRootUrl());
|
||||
representation.setBaseUrl(model.getBaseUrl());
|
||||
representation.setEffectiveUrl(ResolveRelative.resolveRelativeUri(session, model.getRootUrl(), model.getBaseUrl()));
|
||||
UserConsentModel consentModel = consents.get(model.getClientId());
|
||||
if(consentModel != null) {
|
||||
representation.setConsent(modelToRepresentation(consentModel));
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.keycloak.representations.idm.RequiredActionProviderSimpleRepresentati
|
|||
import org.keycloak.services.messages.Messages;
|
||||
import org.keycloak.services.resources.account.AccountCredentialResource;
|
||||
import org.keycloak.services.resources.account.AccountCredentialResource.PasswordUpdate;
|
||||
import org.keycloak.services.util.ResolveRelative;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.admin.authentication.AbstractAuthenticationTest;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
||||
|
@ -643,8 +644,8 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
|
||||
Assert.assertThat(apps.keySet(), containsInAnyOrder("in-use-client", "always-display-client"));
|
||||
|
||||
assertClientRep(apps.get("in-use-client"), "In Use Client", null, false, true, false, inUseClientAppUri);
|
||||
assertClientRep(apps.get("always-display-client"), "Always Display Client", null, false, false, false, alwaysDisplayClientAppUri);
|
||||
assertClientRep(apps.get("in-use-client"), "In Use Client", null, false, true, false, null, inUseClientAppUri);
|
||||
assertClientRep(apps.get("always-display-client"), "Always Display Client", null, false, false, false, null, alwaysDisplayClientAppUri);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -666,7 +667,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
|
||||
Assert.assertThat(apps.keySet(), containsInAnyOrder("offline-client", "always-display-client"));
|
||||
|
||||
assertClientRep(apps.get("offline-client"), "Offline Client", null, false, true, true, offlineClientAppUri);
|
||||
assertClientRep(apps.get("offline-client"), "Offline Client", null, false, true, true, null, offlineClientAppUri);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -705,21 +706,44 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
Assert.assertThat(apps.keySet(), containsInAnyOrder(appId, "always-display-client"));
|
||||
|
||||
ClientRepresentation app = apps.get(appId);
|
||||
assertClientRep(app, null, "A third party application", true, false, false, "http://localhost:8180/auth/realms/master/app/auth");
|
||||
assertClientRep(app, null, "A third party application", true, false, false, null, "http://localhost:8180/auth/realms/master/app/auth");
|
||||
assertFalse(app.getConsent().getGrantedScopes().isEmpty());
|
||||
ConsentScopeRepresentation grantedScope = app.getConsent().getGrantedScopes().get(0);
|
||||
assertEquals(clientScopeRepresentation.getId(), grantedScope.getId());
|
||||
assertEquals(clientScopeRepresentation.getName(), grantedScope.getName());
|
||||
}
|
||||
|
||||
private void assertClientRep(ClientRepresentation clientRep, String name, String description, boolean userConsentRequired, boolean inUse, boolean offlineAccess, String baseUrl) {
|
||||
@Test
|
||||
public void listApplicationsWithRootUrl() throws Exception {
|
||||
oauth.clientId("root-url-client");
|
||||
OAuthClient.AccessTokenResponse tokenResponse = oauth.doGrantAccessTokenRequest("password", "view-applications-access", "password");
|
||||
Assert.assertNull(tokenResponse.getErrorDescription());
|
||||
|
||||
TokenUtil token = new TokenUtil("view-applications-access", "password");
|
||||
List<ClientRepresentation> applications = SimpleHttp
|
||||
.doGet(getAccountUrl("applications"), httpClient)
|
||||
.header("Accept", "application/json")
|
||||
.auth(token.getToken())
|
||||
.asJson(new TypeReference<List<ClientRepresentation>>() {
|
||||
});
|
||||
assertFalse(applications.isEmpty());
|
||||
|
||||
Map<String, ClientRepresentation> apps = applications.stream().collect(Collectors.toMap(x -> x.getClientId(), x -> x));
|
||||
Assert.assertThat(apps.keySet(), containsInAnyOrder("root-url-client", "always-display-client"));
|
||||
|
||||
assertClientRep(apps.get("root-url-client"), null, null, false, true, false, "http://localhost:8180/foo/bar", "/baz");
|
||||
}
|
||||
|
||||
private void assertClientRep(ClientRepresentation clientRep, String name, String description, boolean userConsentRequired, boolean inUse, boolean offlineAccess, String rootUrl, String baseUrl) {
|
||||
assertNotNull(clientRep);
|
||||
assertEquals(name, clientRep.getClientName());
|
||||
assertEquals(description, clientRep.getDescription());
|
||||
assertEquals(userConsentRequired, clientRep.isUserConsentRequired());
|
||||
assertEquals(inUse, clientRep.isInUse());
|
||||
assertEquals(offlineAccess, clientRep.isOfflineAccess());
|
||||
assertEquals(rootUrl, clientRep.getRootUrl());
|
||||
assertEquals(baseUrl, clientRep.getBaseUrl());
|
||||
assertEquals(ResolveRelative.resolveRelativeUri(null, null, rootUrl, baseUrl), clientRep.getEffectiveUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -200,6 +200,7 @@
|
|||
"http://localhost:8180/foo/bar/*",
|
||||
"https://localhost:8543/foo/bar/*"
|
||||
],
|
||||
"directAccessGrantsEnabled": true,
|
||||
"secret": "password"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -58,7 +58,7 @@ export interface Consent {
|
|||
}
|
||||
|
||||
interface Application {
|
||||
baseUrl: string;
|
||||
effectiveUrl: string;
|
||||
clientId: string;
|
||||
clientName: string;
|
||||
consent: Consent;
|
||||
|
@ -117,7 +117,7 @@ export class ApplicationsPage extends React.Component<ApplicationsPageProps, App
|
|||
<ContentPage title={Msg.localize('applicationsPageTitle')}>
|
||||
<DataList id="applications-list" aria-label={Msg.localize('applicationsPageTitle')}>
|
||||
{this.state.applications.map((application: Application, appIndex: number) => {
|
||||
const appUrl: string = application.userConsentRequired ? application.baseUrl : '/auth' + application.baseUrl;
|
||||
const appUrl: string = application.effectiveUrl;
|
||||
|
||||
return (
|
||||
<DataListItem id={this.elementId("client-id", application)} key={'application-' + appIndex} aria-labelledby="applications-list" isExpanded={this.state.isRowOpen[appIndex]}>
|
||||
|
@ -140,11 +140,11 @@ export class ApplicationsPage extends React.Component<ApplicationsPageProps, App
|
|||
<DataListCell id={this.elementId('status', application)} width={2} key={'status-' + appIndex}>
|
||||
{application.inUse ? Msg.localize('inUse') : Msg.localize('notInUse')}
|
||||
</DataListCell>,
|
||||
<DataListCell id={this.elementId('baseurl', application)} width={4} key={'baseUrl-' + appIndex}>
|
||||
<DataListCell id={this.elementId('effectiveurl', application)} width={4} key={'effectiveUrl-' + appIndex}>
|
||||
<button className="pf-c-button pf-m-link" type="button" onClick={() => window.open(appUrl)}>
|
||||
<span className="pf-c-button__icon">
|
||||
<i className="fas fa-link" aria-hidden="true"></i>
|
||||
</span>{application.baseUrl}</button>
|
||||
</span>{application.effectiveUrl}</button>
|
||||
</DataListCell>,
|
||||
]}
|
||||
/>
|
||||
|
@ -161,7 +161,7 @@ export class ApplicationsPage extends React.Component<ApplicationsPageProps, App
|
|||
{application.description &&
|
||||
<GridItem><strong>{Msg.localize('description') + ': '}</strong> {application.description}</GridItem>
|
||||
}
|
||||
<GridItem><strong>{Msg.localize('baseUrl') + ': '}</strong> {application.baseUrl}</GridItem>
|
||||
<GridItem><strong>{Msg.localize('effectiveUrl') + ': '}</strong> {application.effectiveUrl}</GridItem>
|
||||
{application.consent &&
|
||||
<React.Fragment>
|
||||
<GridItem span={12}>
|
||||
|
|
Loading…
Reference in a new issue