michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.browserid.verifier; michael@0: michael@0: import java.io.IOException; michael@0: import java.io.UnsupportedEncodingException; michael@0: import java.net.URI; michael@0: import java.net.URISyntaxException; michael@0: import java.security.GeneralSecurityException; michael@0: import java.util.Arrays; michael@0: import java.util.List; michael@0: michael@0: import org.mozilla.gecko.background.common.log.Logger; michael@0: import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierErrorResponseException; michael@0: import org.mozilla.gecko.browserid.verifier.BrowserIDVerifierException.BrowserIDVerifierMalformedResponseException; michael@0: import org.mozilla.gecko.sync.ExtendedJSONObject; michael@0: import org.mozilla.gecko.sync.net.BaseResource; michael@0: import org.mozilla.gecko.sync.net.BaseResourceDelegate; michael@0: import org.mozilla.gecko.sync.net.Resource; michael@0: import org.mozilla.gecko.sync.net.SyncResponse; michael@0: michael@0: import ch.boye.httpclientandroidlib.HttpResponse; michael@0: import ch.boye.httpclientandroidlib.NameValuePair; michael@0: import ch.boye.httpclientandroidlib.client.ClientProtocolException; michael@0: import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity; michael@0: import ch.boye.httpclientandroidlib.message.BasicNameValuePair; michael@0: michael@0: public class BrowserIDRemoteVerifierClient implements BrowserIDVerifierClient { michael@0: protected static class RemoteVerifierResourceDelegate extends BaseResourceDelegate { michael@0: private final BrowserIDVerifierDelegate delegate; michael@0: michael@0: protected RemoteVerifierResourceDelegate(Resource resource, BrowserIDVerifierDelegate delegate) { michael@0: super(resource); michael@0: this.delegate = delegate; michael@0: } michael@0: michael@0: @Override michael@0: public String getUserAgent() { michael@0: return null; michael@0: } michael@0: michael@0: @Override michael@0: public void handleHttpResponse(HttpResponse response) { michael@0: SyncResponse res = new SyncResponse(response); michael@0: int statusCode = res.getStatusCode(); michael@0: Logger.debug(LOG_TAG, "Got response with status code " + statusCode + "."); michael@0: michael@0: if (statusCode != 200) { michael@0: delegate.handleError(new BrowserIDVerifierErrorResponseException("Expected status code 200.")); michael@0: return; michael@0: } michael@0: michael@0: ExtendedJSONObject o = null; michael@0: try { michael@0: o = res.jsonObjectBody(); michael@0: } catch (Exception e) { michael@0: delegate.handleError(new BrowserIDVerifierMalformedResponseException(e)); michael@0: return; michael@0: } michael@0: michael@0: String status = o.getString("status"); michael@0: if ("failure".equals(status)) { michael@0: delegate.handleFailure(o); michael@0: return; michael@0: } michael@0: michael@0: if (!("okay".equals(status))) { michael@0: delegate.handleError(new BrowserIDVerifierMalformedResponseException("Expected status okay, got '" + status + "'.")); michael@0: return; michael@0: } michael@0: michael@0: delegate.handleSuccess(o); michael@0: } michael@0: michael@0: @Override michael@0: public void handleTransportException(GeneralSecurityException e) { michael@0: Logger.warn(LOG_TAG, "Got transport exception.", e); michael@0: delegate.handleError(e); michael@0: } michael@0: michael@0: @Override michael@0: public void handleHttpProtocolException(ClientProtocolException e) { michael@0: Logger.warn(LOG_TAG, "Got protocol exception.", e); michael@0: delegate.handleError(e); michael@0: } michael@0: michael@0: @Override michael@0: public void handleHttpIOException(IOException e) { michael@0: Logger.warn(LOG_TAG, "Got IO exception.", e); michael@0: delegate.handleError(e); michael@0: } michael@0: } michael@0: michael@0: public static final String LOG_TAG = "BrowserIDRemoteVerifierClient"; michael@0: michael@0: public static final String DEFAULT_VERIFIER_URL = "https://verifier.login.persona.org/verify"; michael@0: michael@0: protected final URI verifierUri; michael@0: michael@0: public BrowserIDRemoteVerifierClient(URI verifierUri) { michael@0: this.verifierUri = verifierUri; michael@0: } michael@0: michael@0: public BrowserIDRemoteVerifierClient() throws URISyntaxException { michael@0: this.verifierUri = new URI(DEFAULT_VERIFIER_URL); michael@0: } michael@0: michael@0: @Override michael@0: public void verify(String audience, String assertion, final BrowserIDVerifierDelegate delegate) { michael@0: if (audience == null) { michael@0: throw new IllegalArgumentException("audience cannot be null."); michael@0: } michael@0: if (assertion == null) { michael@0: throw new IllegalArgumentException("assertion cannot be null."); michael@0: } michael@0: if (delegate == null) { michael@0: throw new IllegalArgumentException("delegate cannot be null."); michael@0: } michael@0: michael@0: BaseResource r = new BaseResource(verifierUri); michael@0: michael@0: r.delegate = new RemoteVerifierResourceDelegate(r, delegate); michael@0: michael@0: List nvps = Arrays.asList(new NameValuePair[] { michael@0: new BasicNameValuePair("audience", audience), michael@0: new BasicNameValuePair("assertion", assertion) }); michael@0: michael@0: try { michael@0: r.post(new UrlEncodedFormEntity(nvps, "UTF-8")); michael@0: } catch (UnsupportedEncodingException e) { michael@0: delegate.handleError(e); michael@0: } michael@0: } michael@0: }