[KEYCLOAK-18807] - Fixing claims in JARM responses
This commit is contained in:
parent
13a08362d4
commit
730d4e8ac9
3 changed files with 52 additions and 7 deletions
|
@ -24,6 +24,8 @@ public interface OAuth2Constants {
|
||||||
|
|
||||||
String CODE = "code";
|
String CODE = "code";
|
||||||
|
|
||||||
|
String TOKEN = "token";
|
||||||
|
|
||||||
String CLIENT_ID = "client_id";
|
String CLIENT_ID = "client_id";
|
||||||
|
|
||||||
String CLIENT_SECRET = "client_secret";
|
String CLIENT_SECRET = "client_secret";
|
||||||
|
|
|
@ -17,14 +17,19 @@
|
||||||
|
|
||||||
package org.keycloak.protocol.oidc.utils;
|
package org.keycloak.protocol.oidc.utils;
|
||||||
|
|
||||||
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.common.util.Encode;
|
import org.keycloak.common.util.Encode;
|
||||||
import org.keycloak.common.util.HtmlUtils;
|
import org.keycloak.common.util.HtmlUtils;
|
||||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.KeycloakContext;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
import org.keycloak.representations.AuthorizationResponseToken;
|
import org.keycloak.representations.AuthorizationResponseToken;
|
||||||
|
import org.keycloak.services.Urls;
|
||||||
|
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -183,10 +188,10 @@ public abstract class OIDCRedirectUriBuilder {
|
||||||
// https://openid.net/specs/openid-financial-api-jarm-ID1.html
|
// https://openid.net/specs/openid-financial-api-jarm-ID1.html
|
||||||
private static class JWTRedirectUriBuilder extends OIDCRedirectUriBuilder {
|
private static class JWTRedirectUriBuilder extends OIDCRedirectUriBuilder {
|
||||||
|
|
||||||
private OIDCResponseMode responseMode;
|
private final OIDCResponseMode responseMode;
|
||||||
private AuthorizationResponseToken responseJWT;
|
private final AuthorizationResponseToken responseJWT;
|
||||||
private KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
private AuthenticatedClientSessionModel clientSession;
|
private final AuthenticatedClientSessionModel clientSession;
|
||||||
|
|
||||||
public JWTRedirectUriBuilder(KeycloakUriBuilder uriBuilder, OIDCResponseMode responseMode, KeycloakSession session, AuthenticatedClientSessionModel clientSession) {
|
public JWTRedirectUriBuilder(KeycloakUriBuilder uriBuilder, OIDCResponseMode responseMode, KeycloakSession session, AuthenticatedClientSessionModel clientSession) {
|
||||||
super(uriBuilder);
|
super(uriBuilder);
|
||||||
|
@ -204,12 +209,23 @@ public abstract class OIDCRedirectUriBuilder {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response build() {
|
public Response build() {
|
||||||
|
KeycloakContext context = session.getContext();
|
||||||
|
ClientModel client = context.getClient();
|
||||||
|
RealmModel realm = client.getRealm();
|
||||||
|
|
||||||
|
responseJWT.issuer(Urls.realmIssuer(context.getUri().getBaseUri(), realm.getName()));
|
||||||
|
responseJWT.audience(client.getClientId());
|
||||||
|
responseJWT.exp((long) (Time.currentTime() + realm.getAccessCodeLifespan()));
|
||||||
|
|
||||||
if(clientSession != null) {
|
if(clientSession != null) {
|
||||||
responseJWT.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER));
|
responseJWT.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER));
|
||||||
responseJWT.audience(clientSession.getClient().getClientId());
|
String responseType = clientSession.getNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
|
||||||
responseJWT.setOtherClaims("scope", clientSession.getNote(OIDCLoginProtocol.SCOPE_PARAM));
|
|
||||||
responseJWT.exp((long) (Time.currentTime() + clientSession.getRealm().getAccessCodeLifespan()));
|
if (OAuth2Constants.TOKEN.equals(responseType)) {
|
||||||
|
responseJWT.setOtherClaims(OAuth2Constants.SCOPE, clientSession.getNote(OIDCLoginProtocol.SCOPE_PARAM));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (responseMode) {
|
switch (responseMode) {
|
||||||
case QUERY_JWT:
|
case QUERY_JWT:
|
||||||
return buildQueryResponse();
|
return buildQueryResponse();
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.keycloak.testsuite.oidc;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.OAuthErrorException;
|
import org.keycloak.OAuthErrorException;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
|
@ -38,6 +39,9 @@ import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class AuthorizationTokenResponseModeTest extends AbstractTestRealmKeycloakTest {
|
public class AuthorizationTokenResponseModeTest extends AbstractTestRealmKeycloakTest {
|
||||||
|
@ -76,6 +80,8 @@ public class AuthorizationTokenResponseModeTest extends AbstractTestRealmKeycloa
|
||||||
|
|
||||||
assertEquals("test-app", responseToken.getAudience()[0]);
|
assertEquals("test-app", responseToken.getAudience()[0]);
|
||||||
Assert.assertNotNull(responseToken.getOtherClaims().get("code"));
|
Assert.assertNotNull(responseToken.getOtherClaims().get("code"));
|
||||||
|
// should not return code when response_type not 'token'
|
||||||
|
assertFalse(responseToken.getOtherClaims().containsKey(OAuth2Constants.SCOPE));
|
||||||
assertEquals("OpenIdConnect.AuthenticationProperties=2302984sdlk", responseToken.getOtherClaims().get("state"));
|
assertEquals("OpenIdConnect.AuthenticationProperties=2302984sdlk", responseToken.getOtherClaims().get("state"));
|
||||||
Assert.assertNull(responseToken.getOtherClaims().get("error"));
|
Assert.assertNull(responseToken.getOtherClaims().get("error"));
|
||||||
|
|
||||||
|
@ -212,6 +218,27 @@ public class AuthorizationTokenResponseModeTest extends AbstractTestRealmKeycloa
|
||||||
events.expectLogin().error(Errors.INVALID_REQUEST).user((String) null).session((String) null).clearDetails().assertEvent();
|
events.expectLogin().error(Errors.INVALID_REQUEST).user((String) null).session((String) null).clearDetails().assertEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testErrorObjectExpectedClaims() throws Exception {
|
||||||
|
ClientManager.realm(adminClient.realm("test")).clientId("test-app").implicitFlow(true);
|
||||||
|
oauth.responseMode("query.jwt");
|
||||||
|
oauth.responseType("code id_token");
|
||||||
|
oauth.stateParamHardcoded("OpenIdConnect.AuthenticationProperties=2302984sdlk");
|
||||||
|
oauth.nonce("123456");
|
||||||
|
UriBuilder b = UriBuilder.fromUri(oauth.getLoginFormUrl());
|
||||||
|
driver.navigate().to(b.build().toURL());
|
||||||
|
|
||||||
|
OAuthClient.AuthorizationEndpointResponse errorResponse = new OAuthClient.AuthorizationEndpointResponse(oauth);
|
||||||
|
AuthorizationResponseToken responseToken = oauth.verifyAuthorizationResponseToken(errorResponse.getResponse());
|
||||||
|
|
||||||
|
assertNotNull(responseToken.getIssuer());
|
||||||
|
assertNotNull(responseToken.getExp());
|
||||||
|
assertNotNull(responseToken.getAudience());
|
||||||
|
assertNotEquals(0, responseToken.getAudience().length);
|
||||||
|
assertTrue(responseToken.getOtherClaims().containsKey("error"));
|
||||||
|
assertTrue(responseToken.getOtherClaims().containsKey("error_description"));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configureTestRealm(RealmRepresentation testRealm) {
|
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue