[KEYCLOAK-17484] OIDC Conformance - Authorization response with Hybrid flow does not contain token_type (#7872)
* [KEYCLOAK-17484] fix oidc conformance for hybrid-flow * [KEYCLOAK-17484] add TokenType & ExpiresIn to OAuth2Constants * [KEYCLOAK-17484] add request validation for oidc-flows automated tests
This commit is contained in:
parent
590ee1b1a2
commit
e10f3b3672
10 changed files with 57 additions and 7 deletions
|
@ -1099,7 +1099,7 @@
|
|||
supportedParams = ['access_token', 'token_type', 'id_token', 'state', 'session_state', 'expires_in', 'kc_action_status'];
|
||||
break;
|
||||
case 'hybrid':
|
||||
supportedParams = ['access_token', 'id_token', 'code', 'state', 'session_state', 'kc_action_status'];
|
||||
supportedParams = ['access_token', 'token_type', 'id_token', 'code', 'state', 'session_state', 'expires_in', 'kc_action_status'];
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,10 @@ public interface OAuth2Constants {
|
|||
|
||||
String ACCESS_TOKEN = "access_token";
|
||||
|
||||
String TOKEN_TYPE = "token_type";
|
||||
|
||||
String EXPIRES_IN = "expires_in";
|
||||
|
||||
String ID_TOKEN = "id_token";
|
||||
|
||||
String REFRESH_TOKEN = "refresh_token";
|
||||
|
|
|
@ -266,10 +266,8 @@ public class OIDCLoginProtocol implements LoginProtocol {
|
|||
|
||||
if (responseType.hasResponseType(OIDCResponseType.TOKEN)) {
|
||||
redirectUri.addParam(OAuth2Constants.ACCESS_TOKEN, res.getToken());
|
||||
if (responseType.isImplicitFlow()) {
|
||||
redirectUri.addParam("token_type", res.getTokenType());
|
||||
redirectUri.addParam("expires_in", String.valueOf(res.getExpiresIn()));
|
||||
}
|
||||
redirectUri.addParam(OAuth2Constants.TOKEN_TYPE, res.getTokenType());
|
||||
redirectUri.addParam(OAuth2Constants.EXPIRES_IN, String.valueOf(res.getExpiresIn()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1359,6 +1359,8 @@ public class OAuthClient {
|
|||
// Just during OIDC implicit or hybrid flow
|
||||
private String accessToken;
|
||||
private String idToken;
|
||||
private String tokenType;
|
||||
private String expiresIn;
|
||||
|
||||
public AuthorizationEndpointResponse(OAuthClient client) {
|
||||
boolean fragment;
|
||||
|
@ -1390,6 +1392,8 @@ public class OAuthClient {
|
|||
sessionState = params.get(OAuth2Constants.SESSION_STATE);
|
||||
accessToken = params.get(OAuth2Constants.ACCESS_TOKEN);
|
||||
idToken = params.get(OAuth2Constants.ID_TOKEN);
|
||||
tokenType = params.get(OAuth2Constants.TOKEN_TYPE);
|
||||
expiresIn = params.get(OAuth2Constants.EXPIRES_IN);
|
||||
}
|
||||
|
||||
public boolean isRedirected() {
|
||||
|
@ -1423,6 +1427,14 @@ public class OAuthClient {
|
|||
public String getIdToken() {
|
||||
return idToken;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public String getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AccessTokenResponse {
|
||||
|
@ -1480,10 +1492,10 @@ public class OAuthClient {
|
|||
case OAuth2Constants.ISSUED_TOKEN_TYPE:
|
||||
issuedTokenType = (String) entry.getValue();
|
||||
break;
|
||||
case "token_type":
|
||||
case OAuth2Constants.TOKEN_TYPE:
|
||||
tokenType = (String) entry.getValue();
|
||||
break;
|
||||
case "expires_in":
|
||||
case OAuth2Constants.EXPIRES_IN:
|
||||
expiresIn = (Integer) entry.getValue();
|
||||
break;
|
||||
case "refresh_expires_in":
|
||||
|
|
|
@ -63,6 +63,12 @@ public class OIDCBasicResponseTypeCodeTest extends AbstractOIDCResponseTypeTest
|
|||
// Validate "at_hash"
|
||||
assertValidAccessTokenHash(idToken2.getAccessTokenHash(), authzResponse2.getAccessToken());
|
||||
|
||||
// Validate if token_type is null
|
||||
Assert.assertNull(authzResponse.getTokenType());
|
||||
|
||||
// Validate if expires_in is null
|
||||
Assert.assertNull(authzResponse.getExpiresIn());
|
||||
|
||||
return Collections.singletonList(idToken2);
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,12 @@ public class OIDCHybridResponseTypeCodeIDTokenTest extends AbstractOIDCResponseT
|
|||
|
||||
Assert.assertEquals(idToken.getStateHash(), HashUtils.oidcHash(getIdTokenSignatureAlgorithm(), authzResponse.getState()));
|
||||
|
||||
// Validate if token_type is null
|
||||
Assert.assertNull(authzResponse.getTokenType());
|
||||
|
||||
// Validate if expires_in is null
|
||||
Assert.assertNull(authzResponse.getExpiresIn());
|
||||
|
||||
// IDToken exchanged for the code
|
||||
IDToken idToken2 = sendTokenRequestAndGetIDToken(loginEvent);
|
||||
|
||||
|
|
|
@ -73,6 +73,12 @@ public class OIDCHybridResponseTypeCodeIDTokenTokenTest extends AbstractOIDCResp
|
|||
|
||||
Assert.assertEquals(idToken.getStateHash(), HashUtils.oidcHash(getIdTokenSignatureAlgorithm(), authzResponse.getState()));
|
||||
|
||||
// Validate if token_type is present
|
||||
Assert.assertNotNull(authzResponse.getTokenType());
|
||||
|
||||
// Validate if expires_in is present
|
||||
Assert.assertNotNull(authzResponse.getExpiresIn());
|
||||
|
||||
// IDToken exchanged for the code
|
||||
IDToken idToken2 = sendTokenRequestAndGetIDToken(loginEvent);
|
||||
|
||||
|
|
|
@ -64,6 +64,12 @@ public class OIDCHybridResponseTypeCodeTokenTest extends AbstractOIDCResponseTyp
|
|||
// Validate "at_hash"
|
||||
assertValidAccessTokenHash(idToken2.getAccessTokenHash(), authzResponse2.getAccessToken());
|
||||
|
||||
// Validate if token_type is present
|
||||
Assert.assertNotNull(authzResponse.getTokenType());
|
||||
|
||||
// Validate if expires_in is present
|
||||
Assert.assertNotNull(authzResponse.getExpiresIn());
|
||||
|
||||
return Collections.singletonList(idToken2);
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,12 @@ public class OIDCImplicitResponseTypeIDTokenTest extends AbstractOIDCResponseTyp
|
|||
Assert.assertNull(idToken.getAccessTokenHash());
|
||||
Assert.assertNull(idToken.getCodeHash());
|
||||
|
||||
// Validate if token_type is null
|
||||
Assert.assertNull(authzResponse.getTokenType());
|
||||
|
||||
// Validate if expires_in is null
|
||||
Assert.assertNull(authzResponse.getExpiresIn());
|
||||
|
||||
return Collections.singletonList(idToken);
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,12 @@ public class OIDCImplicitResponseTypeIDTokenTokenTest extends AbstractOIDCRespon
|
|||
// Validate "c_hash"
|
||||
Assert.assertNull(idToken.getCodeHash());
|
||||
|
||||
// Validate if token_type is present
|
||||
Assert.assertNotNull(authzResponse.getTokenType());
|
||||
|
||||
// Validate if expires_in is present
|
||||
Assert.assertNotNull(authzResponse.getExpiresIn());
|
||||
|
||||
return Collections.singletonList(idToken);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue