Skip to content

Commit

Permalink
SDK-1162: Add SignedRequestBuilder and SignedRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
MrBurtyyy committed Oct 3, 2019
1 parent 4ecdd22 commit a9d1548
Show file tree
Hide file tree
Showing 17 changed files with 694 additions and 223 deletions.
10 changes: 10 additions & 0 deletions yoti-sdk-impl/findbugs-rules.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
<Class name="com.yoti.api.client.spi.remote.call.Receipt"/>
<Bug pattern="EI_EXPOSE_REP"/>
</Match>

<Match>
<Class name="com.yoti.api.client.spi.remote.call.SignedRequest" />
<Bug pattern="PZLA_PREFER_ZERO_LENGTH_ARRAYS" />
</Match>

<Match>
<Class name="com.yoti.api.client.spi.remote.call.SignedRequestBuilder" />
<Bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR,EI_EXPOSE_REP2" />
</Match>

<Match>
<Package name="com.yoti.api.client.spi.remote.proto"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
package com.yoti.api.client.spi.remote.call;

import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;

import java.util.List;

public class HttpMethod {

public static final String HTTP_GET = "GET";
public static final String HTTP_POST = "POST";
public static final String HTTP_PUT = "PUT";
public static final String HTTP_PATCH = "PATCH";
public static final String HTTP_DELETE = "DELETE";

public static final List<String> SUPPORTED_HTTP_METHODS = unmodifiableList(asList(HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_GET, HTTP_DELETE));

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,17 @@ public static JsonResourceFetcher newInstance() {

@Override
public <T> T fetchResource(UrlConnector urlConnector, Map<String, String> headers, Class<T> resourceClass) throws ResourceException, IOException {
HttpURLConnection httpUrlConnection = openConnection(urlConnector, HTTP_GET, headers);
return parseResponse(httpUrlConnection, resourceClass);
return doRequest(urlConnector, HTTP_GET, null, headers, resourceClass);
}

@Override
public <T> T postResource(UrlConnector urlConnector, byte[] body, Map<String, String> headers, Class<T> resourceClass)
throws ResourceException, IOException {
return doRequest(urlConnector, HTTP_POST, body, headers, resourceClass);
}

HttpURLConnection httpUrlConnection = openConnection(urlConnector, HTTP_POST, headers);
public <T> T doRequest(UrlConnector urlConnector, String httpMethod, byte[] body, Map<String, String> headers, Class<T> resourceClass) throws ResourceException, IOException {
HttpURLConnection httpUrlConnection = openConnection(urlConnector, httpMethod, headers);
sendBody(body, httpUrlConnection);
return parseResponse(httpUrlConnection, resourceClass);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,48 @@

import static com.yoti.api.client.spi.remote.Base64.base64;
import static com.yoti.api.client.spi.remote.call.HttpMethod.HTTP_GET;
import static com.yoti.api.client.spi.remote.call.YotiConstants.AUTH_KEY_HEADER;
import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_YOTI_API_URL;
import static com.yoti.api.client.spi.remote.call.YotiConstants.PROPERTY_YOTI_API_URL;
import static com.yoti.api.client.spi.remote.util.Validation.notNull;

import java.io.IOException;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.Security;
import java.util.Map;

import com.yoti.api.client.ProfileException;
import com.yoti.api.client.spi.remote.call.factory.HeadersFactory;
import com.yoti.api.client.spi.remote.call.factory.PathFactory;
import com.yoti.api.client.spi.remote.call.factory.SignedMessageFactory;
import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class RemoteProfileService implements ProfileService {

private static final Logger LOG = LoggerFactory.getLogger(RemoteProfileService.class);

private final ResourceFetcher resourceFetcher;
private final PathFactory pathFactory;
private final HeadersFactory headersFactory;
private final SignedMessageFactory signedMessageFactory;
private final UnsignedPathFactory unsignedPathFactory;
private final SignedRequestBuilder signedRequestBuilder;
private final String apiUrl;

static {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Security.addProvider(new BouncyCastleProvider());
}

public static RemoteProfileService newInstance() {
return new RemoteProfileService(
JsonResourceFetcher.newInstance(),
new PathFactory(),
new HeadersFactory(),
SignedMessageFactory.newInstance());
new UnsignedPathFactory(),
SignedRequestBuilder.newInstance()
);
}

RemoteProfileService(ResourceFetcher resourceFetcher,
PathFactory profilePathFactory,
HeadersFactory headersFactory,
SignedMessageFactory signedMessageFactory) {
this.resourceFetcher = resourceFetcher;
this.pathFactory = profilePathFactory;
this.headersFactory = headersFactory;
this.signedMessageFactory = signedMessageFactory;
RemoteProfileService(UnsignedPathFactory profilePathFactory,
SignedRequestBuilder signedRequestBuilder) {
this.unsignedPathFactory = profilePathFactory;
this.signedRequestBuilder = signedRequestBuilder;

apiUrl = System.getProperty(PROPERTY_YOTI_API_URL, DEFAULT_YOTI_API_URL);
}

Expand All @@ -62,26 +56,32 @@ public Receipt getReceipt(KeyPair keyPair, String appId, String connectToken) th
notNull(appId, "Application id");
notNull(connectToken, "Connect token");

String path = pathFactory.createProfilePath(appId, connectToken);
String path = unsignedPathFactory.createProfilePath(appId, connectToken);

try {
String digest = signedMessageFactory.create(keyPair.getPrivate(), HTTP_GET, path);
String authKey = base64(keyPair.getPublic().getEncoded());
return fetchReceipt(path, digest, authKey);

SignedRequest signedRequest = this.signedRequestBuilder
.withKeyPair(keyPair)
.withBaseUrl(apiUrl)
.withEndpoint(path)
.withHttpMethod(HTTP_GET)
.withHeader(AUTH_KEY_HEADER, authKey)
.build();
return fetchReceipt(signedRequest);
} catch (GeneralSecurityException gse) {
throw new ProfileException("Cannot sign request", gse);
} catch (URISyntaxException uriSyntaxException) {
throw new ProfileException("Error creating request", uriSyntaxException);
} catch (IOException ioe) {
throw new ProfileException("Error calling service to get profile", ioe);
}
}

private Receipt fetchReceipt(String resourcePath, String digest, String authKey) throws IOException, ProfileException {
LOG.info("Fetching profile from resource at '{}'", resourcePath);
Map<String, String> headers = headersFactory.create(digest, authKey);
UrlConnector urlConnector = UrlConnector.get(apiUrl + resourcePath);

private Receipt fetchReceipt(SignedRequest signedRequest) throws IOException, ProfileException {
LOG.info("Fetching profile from resource at '{}'", signedRequest.getUri());
try {
ProfileResponse response = resourceFetcher.fetchResource(urlConnector, headers, ProfileResponse.class);
ProfileResponse response = signedRequest.execute(ProfileResponse.class);
return response.getReceipt();
} catch (ResourceException re) {
int responseCode = re.getResponseCode();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.yoti.api.client.spi.remote.call;

import java.io.IOException;
import java.net.URI;
import java.util.Map;

public class SignedRequest {

private final URI uri;
private final String method;
private final byte[] data;
private final Map<String, String> headers;
private final JsonResourceFetcher jsonResourceFetcher;

SignedRequest(final URI uri,
final String method,
final byte[] data,
final Map<String, String> headers,
JsonResourceFetcher jsonResourceFetcher) {

this.uri = uri;
this.method = method;
this.data = data;
this.headers = headers;
this.jsonResourceFetcher = jsonResourceFetcher;
}

public URI getUri() {
return uri;
}

public String getMethod() {
return method;
}

public byte[] getData() {
return data != null ? data.clone() : null;
}

public Map<String, String> getHeaders() {
return headers;
}

public <T> T execute(Class<T> clazz) throws ResourceException, IOException {
UrlConnector urlConnector = UrlConnector.get(uri.toString());
return jsonResourceFetcher.doRequest(urlConnector, getMethod(), getData(), getHeaders(), clazz);
}
}
Loading

0 comments on commit a9d1548

Please sign in to comment.