Merge pull request #3028 from mposolda/KEYCLOAK-3219
KEYCLOAK-3219 Added claims info to OIDCWellKnownProvider. More tests
This commit is contained in:
commit
912bc8464e
6 changed files with 95 additions and 4 deletions
|
@ -104,6 +104,11 @@ public class OIDCLoginProtocolService {
|
|||
return uriBuilder.path(OIDCLoginProtocolService.class, "certs");
|
||||
}
|
||||
|
||||
public static UriBuilder userInfoUrl(UriBuilder baseUriBuilder) {
|
||||
UriBuilder uriBuilder = tokenServiceBaseUrl(baseUriBuilder);
|
||||
return uriBuilder.path(OIDCLoginProtocolService.class, "issueUserInfo");
|
||||
}
|
||||
|
||||
public static UriBuilder tokenIntrospectionUrl(UriBuilder baseUriBuilder) {
|
||||
return tokenUrl(baseUriBuilder).path(TokenEndpoint.class, "introspect");
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.protocol.oidc.endpoints.TokenEndpoint;
|
||||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
||||
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.services.clientregistration.ClientRegistrationService;
|
||||
import org.keycloak.services.clientregistration.oidc.OIDCClientRegistrationProviderFactory;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
|
@ -55,6 +56,11 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
|||
|
||||
public static final List<String> DEFAULT_CLIENT_AUTH_SIGNING_ALG_VALUES_SUPPORTED = list(Algorithm.RS256.toString());
|
||||
|
||||
// The exact list depends on protocolMappers
|
||||
public static final List<String> DEFAULT_CLAIMS_SUPPORTED= list("sub", "iss", IDToken.AUTH_TIME, IDToken.NAME, IDToken.GIVEN_NAME, IDToken.FAMILY_NAME, IDToken.PREFERRED_USERNAME, IDToken.EMAIL);
|
||||
|
||||
public static final List<String> DEFAULT_CLAIM_TYPES_SUPPORTED= list("normal");
|
||||
|
||||
private KeycloakSession session;
|
||||
|
||||
public OIDCWellKnownProvider(KeycloakSession session) {
|
||||
|
@ -87,6 +93,10 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
|
|||
config.setTokenEndpointAuthMethodsSupported(DEFAULT_CLIENT_AUTH_METHODS_SUPPORTED);
|
||||
config.setTokenEndpointAuthSigningAlgValuesSupported(DEFAULT_CLIENT_AUTH_SIGNING_ALG_VALUES_SUPPORTED);
|
||||
|
||||
config.setClaimsSupported(DEFAULT_CLAIMS_SUPPORTED);
|
||||
config.setClaimTypesSupported(DEFAULT_CLAIM_TYPES_SUPPORTED);
|
||||
config.setClaimsParameterSupported(false);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,15 @@ public class OIDCConfigurationRepresentation {
|
|||
@JsonProperty("token_endpoint_auth_signing_alg_values_supported")
|
||||
private List<String> tokenEndpointAuthSigningAlgValuesSupported;
|
||||
|
||||
@JsonProperty("claims_supported")
|
||||
private List<String> claimsSupported;
|
||||
|
||||
@JsonProperty("claim_types_supported")
|
||||
private List<String> claimTypesSupported;
|
||||
|
||||
@JsonProperty("claims_parameter_supported")
|
||||
private Boolean claimsParameterSupported;
|
||||
|
||||
protected Map<String, Object> otherClaims = new HashMap<String, Object>();
|
||||
|
||||
public String getIssuer() {
|
||||
|
@ -198,6 +207,30 @@ public class OIDCConfigurationRepresentation {
|
|||
this.tokenEndpointAuthSigningAlgValuesSupported = tokenEndpointAuthSigningAlgValuesSupported;
|
||||
}
|
||||
|
||||
public List<String> getClaimsSupported() {
|
||||
return claimsSupported;
|
||||
}
|
||||
|
||||
public void setClaimsSupported(List<String> claimsSupported) {
|
||||
this.claimsSupported = claimsSupported;
|
||||
}
|
||||
|
||||
public List<String> getClaimTypesSupported() {
|
||||
return claimTypesSupported;
|
||||
}
|
||||
|
||||
public void setClaimTypesSupported(List<String> claimTypesSupported) {
|
||||
this.claimTypesSupported = claimTypesSupported;
|
||||
}
|
||||
|
||||
public Boolean getClaimsParameterSupported() {
|
||||
return claimsParameterSupported;
|
||||
}
|
||||
|
||||
public void setClaimsParameterSupported(Boolean claimsParameterSupported) {
|
||||
this.claimsParameterSupported = claimsParameterSupported;
|
||||
}
|
||||
|
||||
@JsonAnyGetter
|
||||
public Map<String, Object> getOtherClaims() {
|
||||
return otherClaims;
|
||||
|
|
|
@ -485,7 +485,7 @@ public class OAuthClient {
|
|||
}
|
||||
|
||||
public String getLoginFormUrl() {
|
||||
UriBuilder b = OIDCLoginProtocolService.authUrl(UriBuilder.fromUri(SERVER_ROOT + "/auth"));
|
||||
UriBuilder b = OIDCLoginProtocolService.authUrl(UriBuilder.fromUri(AUTH_SERVER_ROOT));
|
||||
b.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE);
|
||||
if (clientId != null) {
|
||||
b.queryParam(OAuth2Constants.CLIENT_ID, clientId);
|
||||
|
|
|
@ -44,8 +44,8 @@ public class UserInfoClientUtil {
|
|||
|
||||
public static WebTarget getUserInfoWebTarget(Client client) {
|
||||
UriBuilder builder = UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT);
|
||||
UriBuilder uriBuilder = OIDCLoginProtocolService.tokenServiceBaseUrl(builder);
|
||||
URI userInfoUri = uriBuilder.path(OIDCLoginProtocolService.class, "issueUserInfo").build("test");
|
||||
UriBuilder uriBuilder = OIDCLoginProtocolService.userInfoUrl(builder);
|
||||
URI userInfoUri = uriBuilder.build("test");
|
||||
return client.target(userInfoUri);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,17 +26,21 @@ import javax.ws.rs.client.WebTarget;
|
|||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.jose.jws.Algorithm;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.protocol.oidc.OIDCWellKnownProviderFactory;
|
||||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
||||
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.admin.AbstractAdminTest;
|
||||
import org.keycloak.testsuite.util.ClientManager;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
|
||||
/**
|
||||
|
@ -50,6 +54,18 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
|
|||
testRealms.add(realm);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void clientConfiguration() {
|
||||
ClientManager.realm(adminClient.realm("test")).clientId("test-app").directAccessGrant(true);
|
||||
/*
|
||||
* Configure the default client ID. Seems like OAuthClient is keeping the state of clientID
|
||||
* For example: If some test case configure oauth.clientId("sample-public-client"), other tests
|
||||
* will faile and the clientID will always be "sample-public-client
|
||||
* @see AccessTokenTest#testAuthorizationNegotiateHeaderIgnored()
|
||||
*/
|
||||
oauth.clientId("test-app");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDiscovery() {
|
||||
|
@ -57,6 +73,12 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
|
|||
try {
|
||||
OIDCConfigurationRepresentation oidcConfig = getOIDCDiscoveryConfiguration(client);
|
||||
|
||||
// URIs are filled
|
||||
Assert.assertEquals(oidcConfig.getAuthorizationEndpoint(), OIDCLoginProtocolService.authUrl(UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT)).build("test").toString());
|
||||
Assert.assertEquals(oidcConfig.getTokenEndpoint(), oauth.getAccessTokenUrl());
|
||||
Assert.assertEquals(oidcConfig.getUserinfoEndpoint(), OIDCLoginProtocolService.userInfoUrl(UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT)).build("test").toString());
|
||||
Assert.assertEquals(oidcConfig.getJwksUri(), oauth.getCertsUrl("test"));
|
||||
|
||||
// Support standard + implicit + hybrid flow
|
||||
assertContains(oidcConfig.getResponseTypesSupported(), OAuth2Constants.CODE, OIDCResponseType.ID_TOKEN, "id_token token", "code id_token", "code token", "code id_token token");
|
||||
assertContains(oidcConfig.getGrantTypesSupported(), OAuth2Constants.AUTHORIZATION_CODE, OAuth2Constants.IMPLICIT);
|
||||
|
@ -68,7 +90,28 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
|
|||
// Client authentication
|
||||
Assert.assertNames(oidcConfig.getTokenEndpointAuthMethodsSupported(), "client_secret_basic", "client_secret_post", "private_key_jwt");
|
||||
Assert.assertNames(oidcConfig.getTokenEndpointAuthSigningAlgValuesSupported(), Algorithm.RS256.toString());
|
||||
System.out.println("Fopo");
|
||||
|
||||
// Claims
|
||||
assertContains(oidcConfig.getClaimsSupported(), IDToken.NAME, IDToken.EMAIL, IDToken.PREFERRED_USERNAME, IDToken.FAMILY_NAME);
|
||||
Assert.assertNames(oidcConfig.getClaimTypesSupported(), "normal");
|
||||
Assert.assertFalse(oidcConfig.getClaimsParameterSupported());
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssuerMatches() throws Exception {
|
||||
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
|
||||
Assert.assertEquals(200, response.getStatusCode());
|
||||
IDToken idToken = oauth.verifyIDToken(response.getIdToken());
|
||||
|
||||
Client client = ClientBuilder.newClient();
|
||||
try {
|
||||
OIDCConfigurationRepresentation oidcConfig = getOIDCDiscoveryConfiguration(client);
|
||||
|
||||
// assert issuer matches
|
||||
Assert.assertEquals(idToken.getIssuer(), oidcConfig.getIssuer());
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue