KEYCLOAK-6700 Financial API Read and Write API Security Profile : state hash value (s_hash) to protect state parameter
This commit is contained in:
parent
871ecf83fb
commit
e72756d01a
5 changed files with 51 additions and 2 deletions
|
@ -51,6 +51,10 @@ public class IDToken extends JsonWebToken {
|
|||
public static final String CLAIMS_LOCALES = "claims_locales";
|
||||
public static final String ACR = "acr";
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
public static final String S_HASH = "s_hash";
|
||||
|
||||
// NOTE!!! WE used to use @JsonUnwrapped on a UserClaimSet object. This screws up otherClaims and the won't work
|
||||
// anymore. So don't have any @JsonUnwrapped!
|
||||
@JsonProperty(NONCE)
|
||||
|
@ -131,6 +135,11 @@ public class IDToken extends JsonWebToken {
|
|||
@JsonProperty(ACR)
|
||||
protected String acr;
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
@JsonProperty(S_HASH)
|
||||
protected String stateHash;
|
||||
|
||||
public String getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
@ -338,4 +347,14 @@ public class IDToken extends JsonWebToken {
|
|||
public void setAcr(String acr) {
|
||||
this.acr = acr;
|
||||
}
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
public String getStateHash() {
|
||||
return stateHash;
|
||||
}
|
||||
|
||||
public void setStateHash(String stateHash) {
|
||||
this.stateHash = stateHash;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,7 +218,11 @@ public class OIDCLoginProtocol implements LoginProtocol {
|
|||
if (responseType.hasResponseType(OIDCResponseType.CODE)) {
|
||||
responseBuilder.generateCodeHash(code);
|
||||
}
|
||||
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
if (state != null)
|
||||
responseBuilder.generateStateHash(state);
|
||||
}
|
||||
|
||||
AccessTokenResponse res = responseBuilder.build();
|
||||
|
|
|
@ -718,6 +718,10 @@ public class TokenManager {
|
|||
boolean generateAccessTokenHash = false;
|
||||
String codeHash;
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
String stateHash;
|
||||
|
||||
public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, AuthenticatedClientSessionModel clientSession) {
|
||||
this.realm = realm;
|
||||
this.client = client;
|
||||
|
@ -819,6 +823,12 @@ public class TokenManager {
|
|||
return this;
|
||||
}
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
public AccessTokenResponseBuilder generateStateHash(String state) {
|
||||
stateHash = HashProvider.oidcHash(jwsAlgorithm, state);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccessTokenResponse build() {
|
||||
KeyManager.ActiveRsaKey activeRsaKey = session.keys().getActiveRsaKey(realm);
|
||||
|
@ -854,7 +864,11 @@ public class TokenManager {
|
|||
if (codeHash != null) {
|
||||
idToken.setCodeHash(codeHash);
|
||||
}
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
if (stateHash != null) {
|
||||
idToken.setStateHash(stateHash);
|
||||
}
|
||||
if (idToken != null) {
|
||||
String encodedToken = new JWSBuilder().type(JWT).kid(activeRsaKey.getKid()).jsonContent(idToken).sign(jwsAlgorithm, activeRsaKey.getPrivateKey());
|
||||
res.setIdToken(encodedToken);
|
||||
|
|
|
@ -65,6 +65,12 @@ public class OIDCHybridResponseTypeCodeIDTokenTest extends AbstractOIDCResponseT
|
|||
Assert.assertNotNull(idToken.getCodeHash());
|
||||
Assert.assertEquals(idToken.getCodeHash(), HashProvider.oidcHash(jwsAlgorithm, authzResponse.getCode()));
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
// Validate "s_hash"
|
||||
Assert.assertNotNull(idToken.getStateHash());
|
||||
Assert.assertEquals(idToken.getStateHash(), HashProvider.oidcHash(jwsAlgorithm, authzResponse.getState()));
|
||||
|
||||
// IDToken exchanged for the code
|
||||
IDToken idToken2 = sendTokenRequestAndGetIDToken(loginEvent);
|
||||
|
||||
|
|
|
@ -66,6 +66,12 @@ public class OIDCHybridResponseTypeCodeIDTokenTokenTest extends AbstractOIDCResp
|
|||
Assert.assertNotNull(idToken.getCodeHash());
|
||||
Assert.assertEquals(idToken.getCodeHash(), HashProvider.oidcHash(jwsAlgorithm, authzResponse.getCode()));
|
||||
|
||||
// Financial API - Part 2: Read and Write API Security Profile
|
||||
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
|
||||
// Validate "s_hash"
|
||||
Assert.assertNotNull(idToken.getStateHash());
|
||||
Assert.assertEquals(idToken.getStateHash(), HashProvider.oidcHash(jwsAlgorithm, authzResponse.getState()));
|
||||
|
||||
// IDToken exchanged for the code
|
||||
IDToken idToken2 = sendTokenRequestAndGetIDToken(loginEvent);
|
||||
|
||||
|
|
Loading…
Reference in a new issue