Skip to content

Commit

Permalink
feat: added at_hash_update module
Browse files Browse the repository at this point in the history
  • Loading branch information
mattebit committed Mar 6, 2024
1 parent 06badc4 commit c0635bd
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
* Module used to check the correctness of the at_hash parameter inside of the id_token wrt to the released access_token
* https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
*/
public class At_Hash extends Module {
public class At_Hash_check extends Module {

public At_Hash() {
public At_Hash_check() {
}

@Override
Expand Down
131 changes: 131 additions & 0 deletions tool/src/main/java/migt/At_Hash_update.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package migt;

import org.apache.commons.codec.binary.Base64;
import org.json.JSONException;
import org.json.JSONObject;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
* Module used to check the correctness of the at_hash parameter inside of the id_token wrt to the released access_token
* https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
*/
public class At_Hash_update extends Module {
String sign_key = "";

public At_Hash_update(JSONObject o) {
sign_key = o.getString("sign key");
}

@Override
public void loader(API api) {
if (!(api instanceof Operation_API)) {
throw new RuntimeException("Tried to load an api not supported in At_Hash module");
}
imported_api = api;
}

@Override
public void execute() {
if (imported_api == null) {
throw new RuntimeException("imported API is null in module At_Hash");
}

if (((Operation_API) imported_api).is_request) {
throw new RuntimeException("Expecting a response got request in At_Hash module");
}

// parse message body and take id_token and access_token values
String body = new String(((Operation_API) imported_api).message.getBody(false));

String id_token = "";
String access_token = "";

JSONObject o = null;

try {
o = new JSONObject(body);
id_token = o.getString("id_token");
access_token = o.getString("access_token");
} catch (JSONException e) {
throw new RuntimeException("Invalid JSON in body");
}

// parse id_token jwt taking alg and at_hash parameters
String alg = "";
JWT j = new JWT();
try {
j.parse(id_token);
JSONObject oo = new JSONObject(j.header);
alg = oo.getString("alg");

} catch (ParsingException | JSONException e) {
System.out.println(e);
result = false;
return;
}

// select the hashing algorithm based on the ID_TOKEN alg header parameter
String hash_alg = alg.substring(1);
byte[] hashed;
try {
switch (hash_alg) {
case "S256":
hashed = MessageDigest.getInstance("SHA-256").digest(access_token.getBytes());
break;
case "S384":
hashed = MessageDigest.getInstance("SHA-384").digest(access_token.getBytes());
break;
case "S512":
hashed = MessageDigest.getInstance("SHA-512").digest(access_token.getBytes());
break;
default:
System.out.println("At_Hash module: unsupported hashing alg: " + alg);
result = false;
return;
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("At_Hash: Invalid algorithm selected to hash content");
}

// select the first 128 bits of the hash of the access token
byte[] left = Arrays.copyOfRange(hashed, 0, 16);

// base64url encode the previous value
String at_hash_generated = Base64.encodeBase64URLSafeString(left);

// remove "=" characters
at_hash_generated = at_hash_generated.replaceAll("=", "");

j.payload = Tools.editJson(
EditOperation.Jwt_action.EDIT,
j.payload,
"$.at_hash",
null,
"",
at_hash_generated);

String new_id_token = "";
try {
j.sign = true;
j.private_key_pem = sign_key;
new_id_token = j.build();
} catch (ParsingException e) {
applicable = false;
return;
}

o.put("id_token", new_id_token);

((Operation_API) imported_api).message.setBody(false, o.toString());

applicable = true; // this means that all the steps that precedes the check were accomplished correctly
result = true;
}

public Operation_API exporter() {
return (Operation_API) this.imported_api;
}
}
20 changes: 18 additions & 2 deletions tool/src/main/java/migt/Operation.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class Operation extends Module {
private SessionOperation.SessionAction sessionAction;
// submodules
private boolean at_hash_verify;
private At_Hash_update at_hash_update;

/**
* Instantiate an operation
Expand Down Expand Up @@ -152,6 +153,10 @@ public Operation(JSONObject operation_json,
if (operation_json.has("at_hash_verify")) {
at_hash_verify = operation_json.getBoolean("at_hash_verify");
}

if (operation_json.has("at_hash_update")) {
at_hash_update = new At_Hash_update(operation_json.getJSONObject("at_hash_update"));
}
}

private void init() {
Expand Down Expand Up @@ -451,7 +456,8 @@ public void execute() {
}
}

// execute the message operations and the decode ops
// Execute other modules
// The order of execution is very important
try {
applicable = true;
executeMessageOperations(this);
Expand All @@ -468,7 +474,7 @@ public void execute() {
return;

if (at_hash_verify) {
At_Hash at = new At_Hash();
At_Hash_check at = new At_Hash_check();
at.loader(api);
at.execute();
setResult(at);
Expand All @@ -477,6 +483,16 @@ public void execute() {
}
}

if (at_hash_update != null) {
at_hash_update.loader(api);
at_hash_update.execute();
this.setAPI(at_hash_update.exporter());
setResult(at_hash_update);
if (!applicable | !result) {
return;
}
}

// TODO: move this here instead of Execute Actives
//executeSessionOps(, api.vars);
//if (!applicable | !result)
Expand Down
4 changes: 2 additions & 2 deletions tool/src/test/java/At_Hash_Test.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import migt.At_Hash;
import migt.At_Hash_check;
import migt.HTTPReqRes;
import migt.Operation_API;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -48,7 +48,7 @@ public HTTPReqRes init_message_token_resp() {
public void test_At_Hash() throws NoSuchAlgorithmException {
HTTPReqRes test_message = init_message_token_resp();

At_Hash ah = new At_Hash();
At_Hash_check ah = new At_Hash_check();

Operation_API o = new Operation_API(test_message, false);

Expand Down

0 comments on commit c0635bd

Please sign in to comment.