All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yubico.u2f.data.messages.ClientData Maven / Gradle / Ivy

There is a newer version: 0.19.12
Show newest version
package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.yubico.u2f.data.messages.key.util.U2fB64Encoding;
import com.yubico.u2f.exceptions.U2fBadInputException;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;

public class ClientData {

    private static final String TYPE_PARAM = "typ";
    private static final String CHALLENGE_PARAM = "challenge";
    private static final String ORIGIN_PARAM = "origin";

    private final String type;
    private final String challenge;
    private final String origin;
    private final String rawClientData;
    private final JsonNode data;

    public String asJson() {
        return rawClientData;
    }

    public ClientData(String clientData) throws U2fBadInputException {
        rawClientData = new String(U2fB64Encoding.decode(clientData));
        try {
            data = new ObjectMapper().readTree(rawClientData);
            type = getString(TYPE_PARAM);
            challenge = getString(CHALLENGE_PARAM);
            origin = getString(ORIGIN_PARAM);
        } catch (IOException e) {
            throw new U2fBadInputException("Malformed ClientData", e);
        }
    }

    @Override
    public String toString() {
        return rawClientData;
    }

    public String getChallenge() {
        return challenge;
    }

    public String getString(String key) {
        return data.get(key).asText();
    }

    public void checkContent(String type, String challenge, Optional> facets) throws U2fBadInputException {
        if (!type.equals(this.type)) {
            throw new U2fBadInputException("Bad clientData: wrong type " + this.type);
        }
        if (!challenge.equals(this.challenge)) {
            throw new U2fBadInputException("Bad clientData: wrong challenge");
        }
        if (facets.isPresent()) {
            Set allowedFacets = canonicalizeOrigins(facets.get());
            String canonicalOrigin;
            try {
                canonicalOrigin = canonicalizeOrigin(origin);
            } catch (RuntimeException e) {
                throw new U2fBadInputException("Bad clientData: Malformed origin", e);
            }
            verifyOrigin(canonicalOrigin, allowedFacets);
        }
    }

    private static void verifyOrigin(String origin, Set allowedOrigins) throws U2fBadInputException {
        if (!allowedOrigins.contains(origin)) {
            throw new U2fBadInputException(origin +
                    " is not a recognized facet for this application");
        }
    }

    public static Set canonicalizeOrigins(Set origins) {
        ImmutableSet.Builder result = ImmutableSet.builder();
        for (String origin : origins) {
            result.add(canonicalizeOrigin(origin));
        }
        return result.build();
    }

    public static String canonicalizeOrigin(String url) {
        try {
            URI uri = new URI(url);
            if (uri.getAuthority() == null) {
                return url;
            }
            return uri.getScheme() + "://" + uri.getAuthority();
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException("specified bad origin", e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy