Skip to content

Commit

Permalink
fix: id_token exchange from v24.0.3 onwards
Browse files Browse the repository at this point in the history
  • Loading branch information
klausbetz committed Jun 8, 2024
1 parent 7eb818b commit 0b02dd0
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ plugins {
}

group 'at.klausbetz'
version '1.11.0'
version '1.12.0'
java.sourceCompatibility = JavaVersion.VERSION_11

ext {
keycloakVersion = '23.0.3'
keycloakVersion = '24.0.5'
}

repositories {
Expand Down
51 changes: 49 additions & 2 deletions src/main/java/at/klausbetz/provider/AppleIdentityProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.social.SocialIdentityProvider;
import org.keycloak.common.util.Base64;
Expand Down Expand Up @@ -85,8 +86,8 @@ protected BrokeredIdentityContext exchangeExternalImpl(EventBuilder event, Multi
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "token not set", Response.Status.BAD_REQUEST);
}

if (OAuth2Constants.JWT_TOKEN_TYPE.equals(exchangeParams.getSubjectTokenType()) || OAuth2Constants.ID_TOKEN_TYPE.equals(exchangeParams.getSubjectTokenType())) {
var context = validateJwt(event, exchangeParams.getSubjectToken(), exchangeParams.getSubjectTokenType());
if (OAuth2Constants.ID_TOKEN_TYPE.equals(exchangeParams.getSubjectTokenType())) {
var context = validateAppleIdToken(event, exchangeParams.getSubjectToken());
return exchangeParams.getUserJson() != null ? handleUserJson(context, exchangeParams.getUserJson()) : context;
} else if (APPLE_AUTHZ_CODE.equals(exchangeParams.getSubjectTokenType())) {
return exchangeAuthorizationCode(exchangeParams.getSubjectToken(), exchangeParams.getUserJson(), exchangeParams.getAppIdentifier());
Expand All @@ -97,6 +98,52 @@ protected BrokeredIdentityContext exchangeExternalImpl(EventBuilder event, Multi
}
}

// NOTE: slightly modified version of OIDCIdentityProvider.validateJWT
private BrokeredIdentityContext validateAppleIdToken(EventBuilder event, String subjectToken) {
event.detail("validation_method", "signature");
if (getConfig().isUseJwksUrl()) {
if (getConfig().getJwksUrl() == null) {
event.detail(Details.REASON, "jwks url unset");
event.error(Errors.INVALID_CONFIG);
throw new ErrorResponseException(Errors.INVALID_CONFIG, "Invalid server config", Response.Status.BAD_REQUEST);
}
} else if (getConfig().getPublicKeySignatureVerifier() == null) {
event.detail(Details.REASON, "public key unset");
event.error(Errors.INVALID_CONFIG);
throw new ErrorResponseException(Errors.INVALID_CONFIG, "Invalid server config", Response.Status.BAD_REQUEST);
}

JsonWebToken parsedToken;
try {
parsedToken = validateToken(subjectToken, true);
} catch (IdentityBrokerException e) {
logger.debug("Unable to validate token for exchange", e);
event.detail(Details.REASON, "token validation failure");
event.error(Errors.INVALID_TOKEN);
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "invalid token", Response.Status.BAD_REQUEST);
}

try {
BrokeredIdentityContext context = extractIdentity(null, null, parsedToken);
if (context == null) {
event.detail(Details.REASON, "Failed to extract identity from token");
event.error(Errors.INVALID_TOKEN);
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "invalid token", Response.Status.BAD_REQUEST);
}

context.getContextData().put(VALIDATED_ID_TOKEN, parsedToken);
context.getContextData().put(EXCHANGE_PROVIDER, getConfig().getAlias());
context.setIdp(this);
context.setIdpConfig(getConfig());
return context;
} catch (IOException e) {
logger.debug("Unable to extract identity from identity token", e);
event.detail(Details.REASON, "Unable to extract identity from identity token: " + e.getMessage());
event.error(Errors.INVALID_TOKEN);
throw new ErrorResponseException(OAuthErrorException.INVALID_TOKEN, "invalid token", Response.Status.BAD_REQUEST);
}
}

public void prepareClientSecret(String clientId) {
if (!isValidSecret(getConfig().getClientSecret())) {
getConfig().setClientSecret(generateJWS(
Expand Down

0 comments on commit 0b02dd0

Please sign in to comment.