com.daon.identityx.samplefidoapp.RelyingPartyServerComms.java Source code

Java tutorial

Introduction

Here is the source code for com.daon.identityx.samplefidoapp.RelyingPartyServerComms.java

Source

/*
* Copyright Daon.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.daon.identityx.samplefidoapp;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import com.daon.identityx.controller.model.*;
import com.daon.identityx.controller.model.Error;
import com.daon.identityx.exception.CommunicationsException;
import com.daon.identityx.exception.ServerError;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.net.ssl.TrustManagerFactory;

/***
 * The core class used to communicate with the server.
 *
 * Created by Daon
 */
public class RelyingPartyServerComms implements IRelyingPartyComms {

    private static final int CONNECTION_TIMEOUT = 20000;
    private static final int READ_TIMEOUT = 20000;
    private static final String CONTENT_TYPE_HEADER = "Content-Type";
    private static final String SESSION_IDENTIFIER_HEADER = "Session-Id";
    private static final String CONTENT_TYPE = "application/json";
    private static final String POST_METHOD = "POST";
    private static final String GET_METHOD = "GET";
    private static final String DELETE_METHOD = "DELETE";

    private GsonBuilder builder;
    private Context context;

    protected Context getContext() {
        return this.context;
    }

    public RelyingPartyServerComms(Context context) {
        builder = new GsonBuilder();
        //        builder.registerTypeAdapter(Timestamp.class, new JsonDeserializer<Timestamp>() {
        //            public Timestamp deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        //                return new Timestamp(json.getAsJsonPrimitive().getAsLong());
        //            }
        //        });
        builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
            public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                    throws JsonParseException {
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
                try {
                    String dateAsString = json.getAsJsonPrimitive().getAsString().replaceAll("\"", "");
                    return formatter.parse(dateAsString);
                } catch (Exception ex) {
                    return new Date();
                }
            }
        });

        this.context = context;
    }

    public class HttpResponse {
        private final String payload;
        private final int httpStatusCode;

        public HttpResponse(String payload, int httpStatusCode) {
            this.httpStatusCode = httpStatusCode;
            this.payload = payload;
        }

        public String getPayload() {
            return payload;
        }

        public int getHttpStatusCode() {
            return httpStatusCode;
        }
    }

    public CreateAccountResponse createAccount(CreateAccount createAccount) {

        return this.post("accounts", createAccount, CreateAccountResponse.class);
    }

    public CreateSessionResponse createSession(CreateSession createSession) {

        return this.post("sessions", createSession, CreateSessionResponse.class);
    }

    public ListAuthenticatorsResponse listAuthenticators() {
        return this.get("listAuthenticators", ListAuthenticatorsResponse.class);
    }

    public GetAuthenticatorResponse getAuthenticator(String id) {
        return this.get("authenticators", id, GetAuthenticatorResponse.class);
    }

    public void deleteSession(String id) {

        this.deleteResource("sessions", id, false);
    }

    public DeleteAccountResponse deleteAccount(String sessionId) {
        return this.deleteResource("accounts", sessionId, DeleteAccountResponse.class);
    }

    public String deleteAuthenticator(String authenticatorId) {
        return this.deleteResource("authenticators", authenticatorId, true);
    }

    public CreateAuthRequestResponse createAuthRequest() {

        return this.get("authRequests", CreateAuthRequestResponse.class);
    }

    public CreateAuthRequestResponse createTransactionAuthRequest(
            CreateTransactionAuthRequest createTransactionAuthRequest) {

        return this.post("transactionAuthRequests", createTransactionAuthRequest, CreateAuthRequestResponse.class);
    }

    public ValidateTransactionAuthResponse validateTransactionAuthRequest(
            ValidateTransactionAuth validateTransactionAuth) {

        return this.post("transactionAuthValidation", validateTransactionAuth,
                ValidateTransactionAuthResponse.class);
    }

    public CreateAuthenticatorResponse createAuthenticator(CreateAuthenticator createAuthenticator) {

        return this.post("authenticators", createAuthenticator, CreateAuthenticatorResponse.class);
    }

    public CreateRegRequestResponse createRegRequest() {

        return this.get("regRequests", CreateRegRequestResponse.class);
    }

    protected String deleteResource(String resource, String resourceId, boolean withOutput) {

        HttpResponse response = this.delete(resource, resourceId, withOutput);
        if (response.getHttpStatusCode() == HttpURLConnection.HTTP_OK) {
            if (withOutput) {
                return response.getPayload();
            } else {
                return null;
            }
        } else {
            Gson outputGson = builder.create();
            Error error = outputGson.fromJson(response.getPayload(), Error.class);
            throw new ServerError(error);
        }
    }

    protected <T> T deleteResource(String resource, String resourceId, Class<T> clazz) {

        HttpResponse response = this.delete(resource, resourceId, true);
        if (response.getHttpStatusCode() == HttpURLConnection.HTTP_OK) {
            Gson outputGson = builder.create();
            return outputGson.fromJson(response.getPayload(), clazz);
        } else {
            Gson outputGson = builder.create();
            Error error = outputGson.fromJson(response.getPayload(), Error.class);
            throw new ServerError(error);
        }
    }

    protected <T> T get(String resource, String id, Class<T> clazz) {
        return this.get(resource + "/" + id, clazz);
    }

    protected <T> T get(String resource, Class<T> clazz) {

        HttpResponse response = this.get(resource);
        if (response.getHttpStatusCode() == HttpURLConnection.HTTP_CREATED
                || response.getHttpStatusCode() == HttpURLConnection.HTTP_OK) {
            Gson outputGson = builder.create();
            return outputGson.fromJson(response.getPayload(), clazz);
        } else {
            Gson outputGson = builder.create();
            Error error = outputGson.fromJson(response.getPayload(), Error.class);
            throw new ServerError(error);
        }
    }

    protected <T> T post(String resource, String id, Object object, Class<T> clazz) {
        return this.post(resource + "/" + id, object, clazz);
    }

    protected <T> T post(String resource, Object object, Class<T> clazz) {

        Gson inputGson = builder.create();
        String payload = inputGson.toJson(object);
        HttpResponse response = this.post(resource, payload);
        if (response.getHttpStatusCode() == HttpURLConnection.HTTP_CREATED
                || response.getHttpStatusCode() == HttpURLConnection.HTTP_OK) {
            Gson outputGson = builder.create();
            return outputGson.fromJson(response.getPayload(), clazz);
        } else {
            Gson outputGson = builder.create();
            Error error = outputGson.fromJson(response.getPayload(), Error.class);
            throw new ServerError(error);
        }
    }

    protected String getAbsoluteUrl(String relativeUrl) {
        return getBaseUrl() + relativeUrl;
    }

    protected String getBaseUrl() {
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
        String serverUrl = sharedPref.getString(SettingsActivity.PREF_SERVER_URL, "acme.com");
        if (serverUrl.endsWith("/")) {
            serverUrl = serverUrl.substring(0, serverUrl.length() - 1);
        }
        String port = sharedPref.getString(SettingsActivity.PREF_SERVER_PORT, "8443");

        String scheme = sharedPref.getBoolean(SettingsActivity.PREF_SERVER_SECURE, false) ? "https" : "http";
        return scheme + "://" + serverUrl + ":" + port + "/";
    }

    protected HttpResponse delete(String relativeUrl, String id, boolean withOutput) {
        return this.delete(relativeUrl + "/" + id, withOutput);
    }

    protected HttpResponse delete(String relativeUrl, boolean withOutput) {

        HttpURLConnection urlConnection = null;
        try {
            urlConnection = this.createConnection(relativeUrl, DELETE_METHOD, withOutput);
            int httpResult = urlConnection.getResponseCode();
            String response = null;
            if (httpResult == HttpURLConnection.HTTP_OK) {
                if (withOutput) {
                    response = this.readStream(urlConnection.getInputStream());
                }
                return new HttpResponse(response, httpResult);
            } else {
                response = this.readStream(urlConnection.getErrorStream());
                return new HttpResponse(response, httpResult);
            }

        } catch (MalformedURLException e) {

            Error error = new Error();
            error.setCode(-1);
            error.setMessage("Unable to connect to the server - likely a programming error");
            throw new CommunicationsException(error);
        } catch (IOException e) {

            Error error = new Error();
            error.setCode(-2);
            error.setMessage("Unable to connect to the server.  Is the server running?");
            throw new CommunicationsException(error);
        } catch (GeneralSecurityException e) {
            Error error = new Error();
            error.setCode(-3);
            error.setMessage("Security error initialising HTTPS connection");
            throw new CommunicationsException(error);
        } finally {
            if (urlConnection != null)
                urlConnection.disconnect();
        }
    }

    protected HttpResponse get(String relativeUrl) {

        HttpURLConnection urlConnection = null;
        try {
            urlConnection = this.createConnection(relativeUrl, GET_METHOD, false);

            int httpResult = urlConnection.getResponseCode();
            String response;
            if (httpResult == HttpURLConnection.HTTP_CREATED || httpResult == HttpURLConnection.HTTP_OK) {
                response = this.readStream(urlConnection.getInputStream());
            } else {
                response = this.readStream(urlConnection.getErrorStream());
            }

            return new HttpResponse(response, httpResult);

        } catch (MalformedURLException e) {
            Error error = new Error();
            error.setCode(-1);
            error.setMessage("Unable to connect to the server - likely a programming error");
            throw new CommunicationsException(error);
        } catch (IOException e) {
            Error error = new Error();
            error.setCode(-2);
            error.setMessage("Unable to connect to the server.  Is the server running?");
            throw new CommunicationsException(error);
        } catch (GeneralSecurityException e) {
            Error error = new Error();
            error.setCode(-3);
            error.setMessage("Security error initialising HTTPS connection");
            throw new CommunicationsException(error);
        } finally {
            if (urlConnection != null)
                urlConnection.disconnect();
        }
    }

    protected HttpResponse post(String relativeUrl, String payload) {

        HttpURLConnection urlConnection = null;
        try {
            urlConnection = this.createConnection(relativeUrl, POST_METHOD, true);
            OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream());
            out.write(payload);
            out.close();

            int httpResult = urlConnection.getResponseCode();
            String response;
            if (httpResult == HttpURLConnection.HTTP_CREATED || httpResult == HttpURLConnection.HTTP_OK) {
                response = this.readStream(urlConnection.getInputStream());
            } else {
                response = this.readStream(urlConnection.getErrorStream());
            }

            return new HttpResponse(response, httpResult);

        } catch (MalformedURLException e) {
            Error error = new Error();
            error.setCode(-1);
            error.setMessage("Unable to connect to the server - likely a programming error");
            throw new CommunicationsException(error);
        } catch (IOException e) {
            Error error = new Error();
            error.setCode(-2);
            error.setMessage("Unable to connect to the server.  Is the server running?");
            throw new CommunicationsException(error);
        } catch (GeneralSecurityException e) {
            Error error = new Error();
            error.setCode(-3);
            error.setMessage("Security error initialising HTTPS connection");
            throw new CommunicationsException(error);
        } finally {
            if (urlConnection != null)
                urlConnection.disconnect();
        }
    }

    protected HttpURLConnection createConnection(String relativeUrl, String method, boolean output)
            throws IOException, KeyManagementException, NoSuchAlgorithmException {
        URL url = new URL(getAbsoluteUrl(relativeUrl));
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setDoOutput(output);
        urlConnection.setRequestMethod(method);
        urlConnection.setUseCaches(false);
        urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
        urlConnection.setReadTimeout(READ_TIMEOUT);
        urlConnection.setRequestProperty(CONTENT_TYPE_HEADER, CONTENT_TYPE);
        if (CoreApplication.getSessionId() != null) {
            urlConnection.setRequestProperty(SESSION_IDENTIFIER_HEADER, CoreApplication.getSessionId());
        }
        urlConnection.connect();
        return urlConnection;
    }

    protected String readStream(InputStream stream) throws IOException {

        StringBuilder sb = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(stream, "utf-8"));
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        return sb.toString();
    }

}