Search in sources :

Example 1 with JWT

use of org.hl7.fhir.r5.elementmodel.SHCParser.JWT in project drug-formulary-ri by HL7-DaVinci.

the class PatientAuthorizationInterceptor method verify.

/**
 * Helper method to verify and decode the access token
 *
 * @param token       - the access token
 * @param fhirBaseUrl - the base url of this FHIR server
 * @return the base interface Patient ID datatype if the jwt token is verified
 *         and contains a patient ID in it claim, otherwise null.
 * @throws SignatureVerificationException
 * @throws TokenExpiredException
 * @throws JWTVerificationException
 */
private IIdType verify(String token, String fhirBaseUrl) throws SignatureVerificationException, TokenExpiredException, JWTVerificationException {
    Algorithm algorithm = Algorithm.RSA256(OauthEndpointController.getPublicKey(), null);
    logger.fine("Verifying JWT token iss and aud is " + fhirBaseUrl);
    JWTVerifier verifier = JWT.require(algorithm).withIssuer(fhirBaseUrl).withAudience(fhirBaseUrl).build();
    DecodedJWT jwt = verifier.verify(token);
    String patientId = jwt.getClaim("patient_id").asString();
    if (patientId != null)
        return new IdType("Patient", patientId);
    return null;
}
Also used : Algorithm(com.auth0.jwt.algorithms.Algorithm) JWTVerifier(com.auth0.jwt.JWTVerifier) DecodedJWT(com.auth0.jwt.interfaces.DecodedJWT) IIdType(org.hl7.fhir.instance.model.api.IIdType) IdType(org.hl7.fhir.r4.model.IdType)

Example 2 with JWT

use of org.hl7.fhir.r5.elementmodel.SHCParser.JWT in project org.hl7.fhir.core by hapifhir.

the class SHCParser method decodeJWT.

public JWT decodeJWT(String jwt) throws IOException, DataFormatException {
    if (jwt.startsWith("shc:/")) {
        jwt = decodeQRCode(jwt);
    }
    if (jwt.length() > MAX_ALLOWED_SHC_LENGTH) {
        logError(-1, -1, "jwt", IssueType.TOOLONG, "JWT Payload limit length is " + MAX_ALLOWED_SHC_LENGTH + " bytes for a single image - this has " + jwt.length() + " bytes", IssueSeverity.ERROR);
    }
    String[] parts = splitToken(jwt);
    byte[] headerJson;
    byte[] payloadJson;
    try {
        headerJson = Base64.getUrlDecoder().decode(parts[0]);
        payloadJson = Base64.getUrlDecoder().decode(parts[1]);
    } catch (NullPointerException e) {
        throw new FHIRException("The UTF-8 Charset isn't initialized.", e);
    } catch (IllegalArgumentException e) {
        throw new FHIRException("The input is not a valid base 64 encoded string.", e);
    }
    JWT res = new JWT();
    res.header = JsonTrackingParser.parseJson(headerJson);
    if ("DEF".equals(JSONUtil.str(res.header, "zip"))) {
        payloadJson = inflate(payloadJson);
    }
    res.payload = JsonTrackingParser.parse(TextFile.bytesToString(payloadJson), res.map, true);
    return res;
}
Also used : FHIRException(org.hl7.fhir.exceptions.FHIRException)

Example 3 with JWT

use of org.hl7.fhir.r5.elementmodel.SHCParser.JWT in project org.hl7.fhir.core by hapifhir.

the class SHCParser method parse.

public List<NamedElement> parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException {
    List<NamedElement> res = new ArrayList<>();
    String src = TextFile.streamToString(stream).trim();
    List<String> list = new ArrayList<>();
    String pfx = null;
    if (src.startsWith("{")) {
        JsonObject json = JsonTrackingParser.parseJson(src);
        if (checkProperty(json, "$", "verifiableCredential", true, "Array")) {
            pfx = "verifiableCredential";
            JsonArray arr = json.getAsJsonArray("verifiableCredential");
            int i = 0;
            for (JsonElement e : arr) {
                if (!(e instanceof JsonPrimitive)) {
                    logError(line(e), col(e), "$.verifiableCredential[" + i + "]", IssueType.STRUCTURE, "Wrong Property verifiableCredential in JSON Payload. Expected : String but found " + JSONUtil.type(e), IssueSeverity.ERROR);
                } else {
                    list.add(e.getAsString());
                }
                i++;
            }
        } else {
            return res;
        }
    } else {
        list.add(src);
    }
    int c = 0;
    for (String ssrc : list) {
        String prefix = pfx == null ? "" : pfx + "[" + Integer.toString(c) + "].";
        c++;
        JWT jwt = null;
        try {
            jwt = decodeJWT(ssrc);
        } catch (Exception e) {
            logError(1, 1, prefix + "JWT", IssueType.INVALID, "Unable to decode JWT token", IssueSeverity.ERROR);
            return res;
        }
        map = jwt.map;
        checkNamedProperties(jwt.getPayload(), prefix + "payload", "iss", "nbf", "vc");
        checkProperty(jwt.getPayload(), prefix + "payload", "iss", true, "String");
        logError(1, 1, prefix + "JWT", IssueType.INFORMATIONAL, "The FHIR Validator does not check the JWT signature " + "(see https://demo-portals.smarthealth.cards/VerifierPortal.html or https://github.com/smart-on-fhir/health-cards-dev-tools) (Issuer = '" + jwt.getPayload().get("iss").getAsString() + "')", IssueSeverity.INFORMATION);
        checkProperty(jwt.getPayload(), prefix + "payload", "nbf", true, "Number");
        JsonObject vc = jwt.getPayload().getAsJsonObject("vc");
        if (vc == null) {
            logError(1, 1, "JWT", IssueType.STRUCTURE, "Unable to find property 'vc' in the payload", IssueSeverity.ERROR);
            return res;
        }
        String path = prefix + "payload.vc";
        checkNamedProperties(vc, path, "type", "credentialSubject");
        if (!checkProperty(vc, path, "type", true, "Array")) {
            return res;
        }
        JsonArray type = vc.getAsJsonArray("type");
        int i = 0;
        for (JsonElement e : type) {
            if (!(e instanceof JsonPrimitive)) {
                logError(line(e), col(e), path + ".type[" + i + "]", IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : String but found " + JSONUtil.type(e), IssueSeverity.ERROR);
            } else {
                types.add(e.getAsString());
            }
            i++;
        }
        if (!types.contains("https://smarthealth.cards#health-card")) {
            logError(line(vc), col(vc), path, IssueType.STRUCTURE, "Card does not claim to be of type https://smarthealth.cards#health-card, cannot validate", IssueSeverity.ERROR);
            return res;
        }
        if (!checkProperty(vc, path, "credentialSubject", true, "Object")) {
            return res;
        }
        JsonObject cs = vc.getAsJsonObject("credentialSubject");
        path = path + ".credentialSubject";
        if (!checkProperty(cs, path, "fhirVersion", true, "String")) {
            return res;
        }
        JsonElement fv = cs.get("fhirVersion");
        if (!VersionUtilities.versionsCompatible(context.getVersion(), fv.getAsString())) {
            logError(line(fv), col(fv), path + ".fhirVersion", IssueType.STRUCTURE, "Card claims to be of version " + fv.getAsString() + ", cannot be validated against version " + context.getVersion(), IssueSeverity.ERROR);
            return res;
        }
        if (!checkProperty(cs, path, "fhirBundle", true, "Object")) {
            return res;
        }
        // ok. all checks passed, we can now validate the bundle
        Element e = jsonParser.parse(cs.getAsJsonObject("fhirBundle"), map);
        if (e != null) {
            res.add(new NamedElement(path, e));
        }
    }
    return res;
}
Also used : JsonPrimitive(com.google.gson.JsonPrimitive) JsonElement(com.google.gson.JsonElement) ArrayList(java.util.ArrayList) JsonObject(com.google.gson.JsonObject) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) DataFormatException(java.util.zip.DataFormatException) IOException(java.io.IOException) FHIRException(org.hl7.fhir.exceptions.FHIRException) JsonArray(com.google.gson.JsonArray) JsonElement(com.google.gson.JsonElement)

Example 4 with JWT

use of org.hl7.fhir.r5.elementmodel.SHCParser.JWT in project org.hl7.fhir.core by hapifhir.

the class ResourceChecker method checkIsResource.

// protected static Manager.FhirFormat checkIsResource(SimpleWorkerContext context, boolean debug, String path) throws IOException {
// 
// if (Utilities.existsInList(ext, "json"))
// return Manager.FhirFormat.JSON;
// if (Utilities.existsInList(ext, "map"))
// return Manager.FhirFormat.TEXT;
// if (Utilities.existsInList(ext, "txt"))
// return Manager.FhirFormat.TEXT;
// if (Utilities.existsInList(ext, "jwt", "jws"))
// return Manager.FhirFormat.SHC;
// 
// return checkIsResource(context, debug, TextFile.fileToBytes(path), path);
// }
public static Manager.FhirFormat checkIsResource(SimpleWorkerContext context, boolean debug, byte[] cnt, String filename, boolean guessFromExtension) {
    System.out.println("   ..Detect format for " + filename);
    if (cnt.length == 0) {
        System.out.println("   " + filename + " is empty");
        return null;
    }
    if (guessFromExtension) {
        String ext = Utilities.getFileExtension(filename);
        if (Utilities.existsInList(ext, "xml")) {
            return FhirFormat.XML;
        }
        if (Utilities.existsInList(ext, "ttl")) {
            return FhirFormat.TURTLE;
        }
        if (Utilities.existsInList(ext, "map")) {
            return Manager.FhirFormat.TEXT;
        }
        if (Utilities.existsInList(ext, "jwt", "jws")) {
            return Manager.FhirFormat.SHC;
        }
        if (Utilities.existsInList(ext, "json")) {
            // no, we have to look inside, and decide.
            try {
                JsonObject json = JsonTrackingParser.parseJson(cnt);
                if (json.has("verifiableCredential")) {
                    return FhirFormat.SHC;
                }
            } catch (Exception e) {
            }
            return FhirFormat.JSON;
        }
        if (Utilities.existsInList(ext, "txt")) {
            try {
                String src = TextFile.bytesToString(cnt);
                if (src.startsWith("shc:/")) {
                    return FhirFormat.SHC;
                }
            } catch (Exception e) {
            }
            return Manager.FhirFormat.TEXT;
        }
    }
    try {
        Manager.parse(context, new ByteArrayInputStream(cnt), Manager.FhirFormat.JSON);
        return Manager.FhirFormat.JSON;
    } catch (Exception e) {
        if (debug) {
            System.out.println("Not JSON: " + e.getMessage());
        }
    }
    try {
        ValidatorUtils.parseXml(cnt);
        return Manager.FhirFormat.XML;
    } catch (Exception e) {
        if (debug) {
            System.out.println("Not XML: " + e.getMessage());
        }
    }
    try {
        Manager.parse(context, new ByteArrayInputStream(cnt), Manager.FhirFormat.TURTLE);
        return Manager.FhirFormat.TURTLE;
    } catch (Exception e) {
        if (debug) {
            System.out.println("Not Turtle: " + e.getMessage());
        }
    }
    try {
        String s = new String(cnt, StandardCharsets.UTF_8);
        if (s.startsWith("shc:/"))
            s = SHCParser.decodeQRCode(s);
        JWT jwt = new SHCParser(context).decodeJWT(s);
        return Manager.FhirFormat.SHC;
    } catch (Exception e) {
        if (debug) {
            System.out.println("Not a smart health card: " + e.getMessage());
        }
    }
    try {
        new StructureMapUtilities(context, null, null).parse(TextFile.bytesToString(cnt), null);
        return Manager.FhirFormat.TEXT;
    } catch (Exception e) {
        if (debug) {
            System.out.println("Not Text: " + e.getMessage());
        }
    }
    if (debug)
        System.out.println("     .. not a resource: " + filename);
    return null;
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) JWT(org.hl7.fhir.r5.elementmodel.SHCParser.JWT) JsonObject(com.google.gson.JsonObject) SHCParser(org.hl7.fhir.r5.elementmodel.SHCParser) IOException(java.io.IOException) StructureMapUtilities(org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities)

Example 5 with JWT

use of org.hl7.fhir.r5.elementmodel.SHCParser.JWT in project org.hl7.fhir.core by hapifhir.

the class SHCParser method decodeJWT.

public JWT decodeJWT(String jwt) throws IOException, DataFormatException {
    if (jwt.startsWith("shc:/")) {
        jwt = decodeQRCode(jwt);
    }
    if (jwt.length() > MAX_ALLOWED_SHC_LENGTH) {
        logError(-1, -1, "jwt", IssueType.TOOLONG, "JWT Payload limit length is " + MAX_ALLOWED_SHC_LENGTH + " bytes for a single image - this has " + jwt.length() + " bytes", IssueSeverity.ERROR);
    }
    String[] parts = splitToken(jwt);
    byte[] headerJson;
    byte[] payloadJson;
    try {
        headerJson = Base64.getUrlDecoder().decode(parts[0]);
        payloadJson = Base64.getUrlDecoder().decode(parts[1]);
    } catch (NullPointerException e) {
        throw new FHIRException("The UTF-8 Charset isn't initialized.", e);
    } catch (IllegalArgumentException e) {
        throw new FHIRException("The input is not a valid base 64 encoded string.", e);
    }
    JWT res = new JWT();
    res.header = JsonTrackingParser.parseJson(headerJson);
    if ("DEF".equals(JSONUtil.str(res.header, "zip"))) {
        payloadJson = inflate(payloadJson);
    }
    res.payload = JsonTrackingParser.parse(TextFile.bytesToString(payloadJson), res.map, true);
    return res;
}
Also used : FHIRException(org.hl7.fhir.exceptions.FHIRException)

Aggregations

IOException (java.io.IOException)4 FHIRException (org.hl7.fhir.exceptions.FHIRException)4 JsonObject (com.google.gson.JsonObject)3 ArrayList (java.util.ArrayList)3 JsonArray (com.google.gson.JsonArray)2 JsonElement (com.google.gson.JsonElement)2 JsonPrimitive (com.google.gson.JsonPrimitive)2 DataFormatException (java.util.zip.DataFormatException)2 DefinitionException (org.hl7.fhir.exceptions.DefinitionException)2 IIdType (org.hl7.fhir.instance.model.api.IIdType)2 IdType (org.hl7.fhir.r4.model.IdType)2 IParser (ca.uhn.fhir.parser.IParser)1 RestOperationTypeEnum (ca.uhn.fhir.rest.api.RestOperationTypeEnum)1 RequestDetails (ca.uhn.fhir.rest.api.server.RequestDetails)1 IGenericClient (ca.uhn.fhir.rest.client.api.IGenericClient)1 AuthenticationException (ca.uhn.fhir.rest.server.exceptions.AuthenticationException)1 AuthorizationInterceptor (ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor)1 IAuthRule (ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule)1 RuleBuilder (ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder)1 JWTVerifier (com.auth0.jwt.JWTVerifier)1