<commit_before>/*
 * AuthenticationAPIClientTest.java
 *
 * Copyright (c) 2015 Auth0 (http://auth0.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.auth0.android.authentication;


import android.content.Context;
import android.content.res.Resources;

import com.auth0.android.Auth0;
import com.auth0.android.request.internal.OkHttpClientFactory;
import com.auth0.android.request.internal.RequestFactory;
import com.auth0.android.result.Authentication;
import com.auth0.android.result.Credentials;
import com.auth0.android.result.DatabaseUser;
import com.auth0.android.result.Delegation;
import com.auth0.android.result.UserProfile;
import com.auth0.android.util.AuthenticationAPI;
import com.auth0.android.util.MockAuthenticationCallback;
import com.auth0.android.util.Telemetry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.squareup.okhttp.HttpUrl;
import com.squareup.okhttp.mockwebserver.RecordedRequest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import java.lang.reflect.Type;
import java.security.PublicKey;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import static com.auth0.android.util.AuthenticationAPI.GENERIC_TOKEN;
import static com.auth0.android.util.AuthenticationAPI.ID_TOKEN;
import static com.auth0.android.util.AuthenticationAPI.REFRESH_TOKEN;
import static com.auth0.android.util.AuthenticationCallbackMatcher.hasError;
import static com.auth0.android.util.AuthenticationCallbackMatcher.hasNoError;
import static com.auth0.android.util.AuthenticationCallbackMatcher.hasPayload;
import static com.auth0.android.util.AuthenticationCallbackMatcher.hasPayloadOfType;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(RobolectricTestRunner.class)
@Config(sdk = 21)
public class AuthenticationAPIClientTest {

    private static final String CLIENT_ID = "CLIENTID";
    private static final String DOMAIN = "samples.auth0.com";
    private static final String PASSWORD = "<PASSWORD>";
    private static final String SUPPORT_AUTH0_COM = "<EMAIL>";
    private static final String SUPPORT = "support";
    private static final String MY_CONNECTION = "MyConnection";
    private static final String FIRST_NAME = "John";
    private static final String LAST_NAME = "Doe";
    private static final String COMPANY = "Auth0";
    private static final String OPENID = "openid";

    private AuthenticationAPIClient client;
    private Gson gson;

    private AuthenticationAPI mockAPI;

    @Before
    public void setUp() throws Exception {
        mockAPI = new AuthenticationAPI();
        final String domain = mockAPI.getDomain();
        Auth0 auth0 = new Auth0(CLIENT_ID, domain, domain);
        client = new AuthenticationAPIClient(auth0);
        gson = new GsonBuilder().serializeNulls().create();
    }

    @After
    public void tearDown() throws Exception {
        mockAPI.shutdown();
    }

    @Test
    public void shouldSetUserAgent() {
        Auth0 account = mock(Auth0.class);
        RequestFactory factory = mock(RequestFactory.class);
        OkHttpClientFactory clientFactory = mock(OkHttpClientFactory.class);
        AuthenticationAPIClient client = new AuthenticationAPIClient(account, factory, clientFactory);
        client.setUserAgent("nexus-5x");
        verify(factory).setUserAgent("nexus-5x");
    }

    @Test
    public void shouldSetTelemetryIfPresent() {
        final Telemetry telemetry = mock(Telemetry.class);
        when(telemetry.getValue()).thenReturn("the-telemetry-data");
        RequestFactory factory = mock(RequestFactory.class);
        OkHttpClientFactory clientFactory = mock(OkHttpClientFactory.class);
        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN);
        auth0.setTelemetry(telemetry);
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0, factory, clientFactory);
        verify(factory).setClientInfo("the-telemetry-data");
    }

    @Test
    public void shouldNotSetTelemetryIfMissing() {
        RequestFactory factory = mock(RequestFactory.class);
        OkHttpClientFactory clientFactory = mock(OkHttpClientFactory.class);
        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN);
        auth0.doNotSendTelemetry();
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0, factory, clientFactory);
        verify(factory, never()).setClientInfo(any(String.class));
    }

    @Test
    public void shouldCreateClientWithAccountInfo() {
        AuthenticationAPIClient client = new AuthenticationAPIClient(new Auth0(CLIENT_ID, DOMAIN));
        assertThat(client, is(notNullValue()));
        assertThat(client.getClientId(), equalTo(CLIENT_ID));
        assertThat(HttpUrl.parse(client.getBaseURL()), notNullValue());
        assertThat(HttpUrl.parse(client.getBaseURL()).scheme(), equalTo("https"));
        assertThat(HttpUrl.parse(client.getBaseURL()).host(), equalTo(DOMAIN));
        assertThat(HttpUrl.parse(client.getBaseURL()).pathSize(), is(1));
        assertThat(HttpUrl.parse(client.getBaseURL()).encodedPath(), is("/"));
    }

    @Test
    public void shouldCreateClientWithContextInfo() {
        Context context = Mockito.mock(Context.class);
        Resources resources = Mockito.mock(Resources.class);
        when(context.getResources()).thenReturn(resources);
        when(resources.getIdentifier(eq("com_auth0_client_id"), eq("string"), anyString())).thenReturn(222);
        when(resources.getIdentifier(eq("com_auth0_domain"), eq("string"), anyString())).thenReturn(333);

        when(context.getString(eq(222))).thenReturn(CLIENT_ID);
        when(context.getString(eq(333))).thenReturn(DOMAIN);

        AuthenticationAPIClient client = new AuthenticationAPIClient(context);

        assertThat(client, is(notNullValue()));
        assertThat(client.getClientId(), is(CLIENT_ID));
        assertThat(client.getBaseURL(), equalTo("https://" + DOMAIN + "/"));
    }

    @Test
    public void shouldLoginWithMFAOTPCode() throws Exception {
        mockAPI.willReturnSuccessfulLogin();
        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();

        Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
        auth0.setOIDCConformant(true);
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0);
        client.loginWithOTP("<PASSWORD>-mfa-token.<PASSWORD>", "<PASSWORD>")
                .start(callback);
        assertThat(callback, hasPayloadOfType(Credentials.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);

        assertThat(request.getPath(), equalTo("/oauth/token"));
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", "http://auth0.com/oauth/grant-type/mfa-otp"));
        assertThat(body, hasEntry("mfa_token", "<PASSWORD>"));
        assertThat(body, hasEntry("otp", "123456"));
        assertThat(body, not(hasKey("username")));
        assertThat(body, not(hasKey("password")));
        assertThat(body, not(hasKey("connection")));
    }

    @Test
    public void shouldLoginWithUserAndPassword() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();

        client.login(SUPPORT_AUTH0_COM, "<PASSWORD>", MY_CONNECTION)
                .start(callback);

        assertThat(callback, hasPayloadOfType(Credentials.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("connection", MY_CONNECTION));
        assertThat(body, not(hasKey("realm")));
    }

    @Test
    public void shouldLoginWithUserAndPasswordSync() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final Credentials credentials = client
                .login(SUPPORT_AUTH0_COM, "<PASSWORD>", MY_CONNECTION)
                .execute();

        assertThat(credentials, is(notNullValue()));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("connection", MY_CONNECTION));
        assertThat(body, not(hasKey("realm")));
    }

    @Test
    public void shouldLoginWithPasswordRealmGrant() throws Exception {
        mockAPI.willReturnSuccessfulLogin();
        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();

        Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
        auth0.setOIDCConformant(true);
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0);
        client.login(SUPPORT_AUTH0_COM, "some-password", MY_CONNECTION)
                .start(callback);
        assertThat(callback, hasPayloadOfType(Credentials.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);

        assertThat(request.getPath(), equalTo("/oauth/token"));
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", "http://auth0.com/oauth/grant-type/password-realm"));
        assertThat(body, hasEntry("username", SUPPORT_AUTH0_COM));
        assertThat(body, hasEntry("password", "<PASSWORD>"));
        assertThat(body, hasEntry("realm", MY_CONNECTION));
        assertThat(body, not(hasKey("connection")));
        assertThat(body, not(hasKey("scope")));
        assertThat(body, not(hasKey("audience")));
    }

    @Test
    public void shouldLoginWithUserAndPasswordUsingOAuthTokenEndpoint() throws Exception {
        mockAPI.willReturnSuccessfulLogin();
        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();

        client.login(SUPPORT_AUTH0_COM, "<PASSWORD>-password")
                .start(callback);
        assertThat(callback, hasPayloadOfType(Credentials.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getPath(), is("/oauth/token"));
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", "password"));
        assertThat(body, hasEntry("username", SUPPORT_AUTH0_COM));
        assertThat(body, hasEntry("password", "<PASSWORD>"));
        assertThat(body, not(hasKey("realm")));
        assertThat(body, not(hasKey("connection")));
        assertThat(body, not(hasKey("scope")));
        assertThat(body, not(hasKey("audience")));
    }

    @Test
    public void shouldLoginWithUserAndPasswordSyncUsingOAuthTokenEndpoint() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final Credentials credentials = client
                .login(SUPPORT_AUTH0_COM, "<PASSWORD>")
                .execute();
        assertThat(credentials, is(notNullValue()));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getPath(), is("/oauth/token"));
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", "password"));
        assertThat(body, hasEntry("username", SUPPORT_AUTH0_COM));
        assertThat(body, hasEntry("password", "<PASSWORD>"));
        assertThat(body, not(hasKey("realm")));
        assertThat(body, not(hasKey("connection")));
        assertThat(body, not(hasKey("scope")));
        assertThat(body, not(hasKey("audience")));
    }

    @Test
    public void shouldFetchTokenInfo() throws Exception {
        mockAPI.willReturnTokenInfo();
        final MockAuthenticationCallback<UserProfile> callback = new MockAuthenticationCallback<>();

        client.tokenInfo("ID_TOKEN")
                .start(callback);

        assertThat(callback, hasPayloadOfType(UserProfile.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/tokeninfo"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("id_token", "ID_TOKEN"));
    }

    @Test
    public void shouldFetchTokenInfoSync() throws Exception {
        mockAPI.willReturnTokenInfo();

        final UserProfile profile = client
                .tokenInfo("ID_TOKEN")
                .execute();

        assertThat(profile, is(notNullValue()));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/tokeninfo"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("id_token", "ID_TOKEN"));
    }

    @Test
    public void shouldFetchUserInfo() throws Exception {
        mockAPI.willReturnTokenInfo();
        final MockAuthenticationCallback<UserProfile> callback = new MockAuthenticationCallback<>();

        client.userInfo("ACCESS_TOKEN")
                .start(callback);

        assertThat(callback, hasPayloadOfType(UserProfile.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getHeader("Authorization"), is("Bearer ACCESS_TOKEN"));
        assertThat(request.getPath(), equalTo("/userinfo"));
    }

    @Test
    public void shouldFetchUserInfoSync() throws Exception {
        mockAPI.willReturnTokenInfo();

        final UserProfile profile = client
                .userInfo("ACCESS_TOKEN")
                .execute();

        assertThat(profile, is(notNullValue()));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getHeader("Authorization"), is("Bearer ACCESS_TOKEN"));
        assertThat(request.getPath(), equalTo("/userinfo"));
    }

    @Test
    public void shouldLoginWithOAuthAccessToken() throws Exception {
        mockAPI
                .willReturnSuccessfulLogin();

        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();
        client.loginWithOAuthAccessToken("fbtoken", "facebook")
                .start(callback);

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/oauth/access_token"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("connection", "facebook"));
        assertThat(body, hasEntry("access_token", "fbtoken"));
        assertThat(body, hasEntry("scope", OPENID));

        assertThat(callback, hasPayloadOfType(Credentials.class));
    }

    @Test
    public void shouldLoginWithOAuthAccessTokenSync() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final Credentials credentials = client
                .loginWithOAuthAccessToken("fbtoken", "facebook")
                .execute();

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/oauth/access_token"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("connection", "facebook"));
        assertThat(body, hasEntry("access_token", "fbtoken"));
        assertThat(body, hasEntry("scope", OPENID));

        assertThat(credentials, is(notNullValue()));
    }

    @Test
    public void shouldLoginWithPhoneNumberWithCustomConnectionWithOTPGrantIfOIDCConformant() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
        auth0.setOIDCConformant(true);
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0);

        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();
        client.loginWithPhoneNumber("+10101010101", "1234", MY_CONNECTION)
                .start(callback);

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));<commit_msg>add tests for the token exchange method<commit_after>/*
 * AuthenticationAPIClientTest.java
 *
 * Copyright (c) 2015 Auth0 (http://auth0.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.auth0.android.authentication;


import android.content.Context;
import android.content.res.Resources;

import com.auth0.android.Auth0;
import com.auth0.android.request.internal.OkHttpClientFactory;
import com.auth0.android.request.internal.RequestFactory;
import com.auth0.android.result.Authentication;
import com.auth0.android.result.Credentials;
import com.auth0.android.result.DatabaseUser;
import com.auth0.android.result.Delegation;
import com.auth0.android.result.UserProfile;
import com.auth0.android.util.AuthenticationAPI;
import com.auth0.android.util.MockAuthenticationCallback;
import com.auth0.android.util.Telemetry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.squareup.okhttp.HttpUrl;
import com.squareup.okhttp.mockwebserver.RecordedRequest;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import java.lang.reflect.Type;
import java.security.PublicKey;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import static com.auth0.android.util.AuthenticationAPI.GENERIC_TOKEN;
import static com.auth0.android.util.AuthenticationAPI.ID_TOKEN;
import static com.auth0.android.util.AuthenticationAPI.REFRESH_TOKEN;
import static com.auth0.android.util.AuthenticationCallbackMatcher.hasError;
import static com.auth0.android.util.AuthenticationCallbackMatcher.hasNoError;
import static com.auth0.android.util.AuthenticationCallbackMatcher.hasPayload;
import static com.auth0.android.util.AuthenticationCallbackMatcher.hasPayloadOfType;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(RobolectricTestRunner.class)
@Config(sdk = 21)
public class AuthenticationAPIClientTest {

    private static final String CLIENT_ID = "CLIENTID";
    private static final String DOMAIN = "samples.auth0.com";
    private static final String PASSWORD = "<PASSWORD>";
    private static final String SUPPORT_AUTH0_COM = "<EMAIL>";
    private static final String SUPPORT = "support";
    private static final String MY_CONNECTION = "MyConnection";
    private static final String FIRST_NAME = "John";
    private static final String LAST_NAME = "Doe";
    private static final String COMPANY = "Auth0";
    private static final String OPENID = "openid";

    private AuthenticationAPIClient client;
    private Gson gson;

    private AuthenticationAPI mockAPI;

    @Before
    public void setUp() throws Exception {
        mockAPI = new AuthenticationAPI();
        final String domain = mockAPI.getDomain();
        Auth0 auth0 = new Auth0(CLIENT_ID, domain, domain);
        client = new AuthenticationAPIClient(auth0);
        gson = new GsonBuilder().serializeNulls().create();
    }

    @After
    public void tearDown() throws Exception {
        mockAPI.shutdown();
    }

    @Test
    public void shouldSetUserAgent() {
        Auth0 account = mock(Auth0.class);
        RequestFactory factory = mock(RequestFactory.class);
        OkHttpClientFactory clientFactory = mock(OkHttpClientFactory.class);
        AuthenticationAPIClient client = new AuthenticationAPIClient(account, factory, clientFactory);
        client.setUserAgent("nexus-5x");
        verify(factory).setUserAgent("nexus-5x");
    }

    @Test
    public void shouldSetTelemetryIfPresent() {
        final Telemetry telemetry = mock(Telemetry.class);
        when(telemetry.getValue()).thenReturn("the-telemetry-data");
        RequestFactory factory = mock(RequestFactory.class);
        OkHttpClientFactory clientFactory = mock(OkHttpClientFactory.class);
        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN);
        auth0.setTelemetry(telemetry);
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0, factory, clientFactory);
        verify(factory).setClientInfo("the-telemetry-data");
    }

    @Test
    public void shouldNotSetTelemetryIfMissing() {
        RequestFactory factory = mock(RequestFactory.class);
        OkHttpClientFactory clientFactory = mock(OkHttpClientFactory.class);
        Auth0 auth0 = new Auth0(CLIENT_ID, DOMAIN);
        auth0.doNotSendTelemetry();
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0, factory, clientFactory);
        verify(factory, never()).setClientInfo(any(String.class));
    }

    @Test
    public void shouldCreateClientWithAccountInfo() {
        AuthenticationAPIClient client = new AuthenticationAPIClient(new Auth0(CLIENT_ID, DOMAIN));
        assertThat(client, is(notNullValue()));
        assertThat(client.getClientId(), equalTo(CLIENT_ID));
        assertThat(HttpUrl.parse(client.getBaseURL()), notNullValue());
        assertThat(HttpUrl.parse(client.getBaseURL()).scheme(), equalTo("https"));
        assertThat(HttpUrl.parse(client.getBaseURL()).host(), equalTo(DOMAIN));
        assertThat(HttpUrl.parse(client.getBaseURL()).pathSize(), is(1));
        assertThat(HttpUrl.parse(client.getBaseURL()).encodedPath(), is("/"));
    }

    @Test
    public void shouldCreateClientWithContextInfo() {
        Context context = Mockito.mock(Context.class);
        Resources resources = Mockito.mock(Resources.class);
        when(context.getResources()).thenReturn(resources);
        when(resources.getIdentifier(eq("com_auth0_client_id"), eq("string"), anyString())).thenReturn(222);
        when(resources.getIdentifier(eq("com_auth0_domain"), eq("string"), anyString())).thenReturn(333);

        when(context.getString(eq(222))).thenReturn(CLIENT_ID);
        when(context.getString(eq(333))).thenReturn(DOMAIN);

        AuthenticationAPIClient client = new AuthenticationAPIClient(context);

        assertThat(client, is(notNullValue()));
        assertThat(client.getClientId(), is(CLIENT_ID));
        assertThat(client.getBaseURL(), equalTo("https://" + DOMAIN + "/"));
    }

    @Test
    public void shouldLoginWithMFAOTPCode() throws Exception {
        mockAPI.willReturnSuccessfulLogin();
        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();

        Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
        auth0.setOIDCConformant(true);
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0);
        client.loginWithOTP("ey30.the-mfa-token.value", "123456")
                .start(callback);
        assertThat(callback, hasPayloadOfType(Credentials.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);

        assertThat(request.getPath(), equalTo("/oauth/token"));
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", "http://auth0.com/oauth/grant-type/mfa-otp"));
        assertThat(body, hasEntry("mfa_token", "<PASSWORD>"));
        assertThat(body, hasEntry("otp", "123456"));
        assertThat(body, not(hasKey("username")));
        assertThat(body, not(hasKey("password")));
        assertThat(body, not(hasKey("connection")));
    }

    @Test
    public void shouldLoginWithUserAndPassword() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();

        client.login(SUPPORT_AUTH0_COM, "voidpassword", MY_CONNECTION)
                .start(callback);

        assertThat(callback, hasPayloadOfType(Credentials.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("connection", MY_CONNECTION));
        assertThat(body, not(hasKey("realm")));
    }

    @Test
    public void shouldLoginWithUserAndPasswordSync() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final Credentials credentials = client
                .login(SUPPORT_AUTH0_COM, "voidpassword", MY_CONNECTION)
                .execute();

        assertThat(credentials, is(notNullValue()));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("connection", MY_CONNECTION));
        assertThat(body, not(hasKey("realm")));
    }

    @Test
    public void shouldLoginWithPasswordRealmGrant() throws Exception {
        mockAPI.willReturnSuccessfulLogin();
        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();

        Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
        auth0.setOIDCConformant(true);
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0);
        client.login(SUPPORT_AUTH0_COM, "<PASSWORD>-password", MY_CONNECTION)
                .start(callback);
        assertThat(callback, hasPayloadOfType(Credentials.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);

        assertThat(request.getPath(), equalTo("/oauth/token"));
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", "http://auth0.com/oauth/grant-type/password-realm"));
        assertThat(body, hasEntry("username", SUPPORT_AUTH0_COM));
        assertThat(body, hasEntry("password", "<PASSWORD>"));
        assertThat(body, hasEntry("realm", MY_CONNECTION));
        assertThat(body, not(hasKey("connection")));
        assertThat(body, not(hasKey("scope")));
        assertThat(body, not(hasKey("audience")));
    }

    @Test
    public void shouldLoginWithUserAndPasswordUsingOAuthTokenEndpoint() throws Exception {
        mockAPI.willReturnSuccessfulLogin();
        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();

        client.login(SUPPORT_AUTH0_COM, "some-password")
                .start(callback);
        assertThat(callback, hasPayloadOfType(Credentials.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getPath(), is("/oauth/token"));
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", "password"));
        assertThat(body, hasEntry("username", SUPPORT_AUTH0_COM));
        assertThat(body, hasEntry("password", "<PASSWORD>"));
        assertThat(body, not(hasKey("realm")));
        assertThat(body, not(hasKey("connection")));
        assertThat(body, not(hasKey("scope")));
        assertThat(body, not(hasKey("audience")));
    }

    @Test
    public void shouldLoginWithUserAndPasswordSyncUsingOAuthTokenEndpoint() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final Credentials credentials = client
                .login(SUPPORT_AUTH0_COM, "<PASSWORD>")
                .execute();
        assertThat(credentials, is(notNullValue()));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getPath(), is("/oauth/token"));
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", "password"));
        assertThat(body, hasEntry("username", SUPPORT_AUTH0_COM));
        assertThat(body, hasEntry("password", "<PASSWORD>"));
        assertThat(body, not(hasKey("realm")));
        assertThat(body, not(hasKey("connection")));
        assertThat(body, not(hasKey("scope")));
        assertThat(body, not(hasKey("audience")));
    }

    @Test
    public void shouldFetchTokenInfo() throws Exception {
        mockAPI.willReturnTokenInfo();
        final MockAuthenticationCallback<UserProfile> callback = new MockAuthenticationCallback<>();

        client.tokenInfo("ID_TOKEN")
                .start(callback);

        assertThat(callback, hasPayloadOfType(UserProfile.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/tokeninfo"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("id_token", "ID_TOKEN"));
    }

    @Test
    public void shouldFetchTokenInfoSync() throws Exception {
        mockAPI.willReturnTokenInfo();

        final UserProfile profile = client
                .tokenInfo("ID_TOKEN")
                .execute();

        assertThat(profile, is(notNullValue()));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/tokeninfo"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("id_token", "ID_TOKEN"));
    }

    @Test
    public void shouldFetchUserInfo() throws Exception {
        mockAPI.willReturnTokenInfo();
        final MockAuthenticationCallback<UserProfile> callback = new MockAuthenticationCallback<>();

        client.userInfo("ACCESS_TOKEN")
                .start(callback);

        assertThat(callback, hasPayloadOfType(UserProfile.class));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getHeader("Authorization"), is("Bearer ACCESS_TOKEN"));
        assertThat(request.getPath(), equalTo("/userinfo"));
    }

    @Test
    public void shouldFetchUserInfoSync() throws Exception {
        mockAPI.willReturnTokenInfo();

        final UserProfile profile = client
                .userInfo("ACCESS_TOKEN")
                .execute();

        assertThat(profile, is(notNullValue()));

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getHeader("Authorization"), is("Bearer ACCESS_TOKEN"));
        assertThat(request.getPath(), equalTo("/userinfo"));
    }

    @Test
    public void shouldLoginWithOAuthAccessToken() throws Exception {
        mockAPI
                .willReturnSuccessfulLogin();

        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();
        client.loginWithOAuthAccessToken("fbtoken", "facebook")
                .start(callback);

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/oauth/access_token"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("connection", "facebook"));
        assertThat(body, hasEntry("access_token", "fbtoken"));
        assertThat(body, hasEntry("scope", OPENID));

        assertThat(callback, hasPayloadOfType(Credentials.class));
    }

    @Test
    public void shouldLoginWithOAuthAccessTokenSync() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final Credentials credentials = client
                .loginWithOAuthAccessToken("fbtoken", "facebook")
                .execute();

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/oauth/access_token"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("connection", "facebook"));
        assertThat(body, hasEntry("access_token", "fbtoken"));
        assertThat(body, hasEntry("scope", OPENID));

        assertThat(credentials, is(notNullValue()));
    }

    @Test
    public void shouldLoginWithNativeSocialToken() throws Exception {
        mockAPI
                .willReturnSuccessfulLogin();

        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();
        client.loginWithNativeSocialToken("test-token-value", "test-token-type")
                .start(callback);

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/oauth/token"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", ParameterBuilder.GRANT_TYPE_TOKEN_EXCHANGE));
        assertThat(body, hasEntry("subject_token", "test-token-value"));
        assertThat(body, hasEntry("subject_token_type", "test-token-type"));
        assertThat(body, hasEntry("scope", OPENID));

        assertThat(callback, hasPayloadOfType(Credentials.class));
    }

    @Test
    public void shouldLoginWithNativeSocialTokenSync() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        final Credentials credentials = client
                .loginWithNativeSocialToken("test-token-value", "test-token-type")
                .execute();

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
        assertThat(request.getPath(), equalTo("/oauth/token"));

        Map<String, String> body = bodyFromRequest(request);
        assertThat(body, hasEntry("client_id", CLIENT_ID));
        assertThat(body, hasEntry("grant_type", ParameterBuilder.GRANT_TYPE_TOKEN_EXCHANGE));
        assertThat(body, hasEntry("subject_token", "test-token-value"));
        assertThat(body, hasEntry("subject_token_type", "test-token-type"));
        assertThat(body, hasEntry("scope", OPENID));

        assertThat(credentials, is(notNullValue()));
    }

    @Test
    public void shouldLoginWithPhoneNumberWithCustomConnectionWithOTPGrantIfOIDCConformant() throws Exception {
        mockAPI.willReturnSuccessfulLogin();

        Auth0 auth0 = new Auth0(CLIENT_ID, mockAPI.getDomain(), mockAPI.getDomain());
        auth0.setOIDCConformant(true);
        AuthenticationAPIClient client = new AuthenticationAPIClient(auth0);

        final MockAuthenticationCallback<Credentials> callback = new MockAuthenticationCallback<>();
        client.loginWithPhoneNumber("+10101010101", "1234", MY_CONNECTION)
                .start(callback);

        final RecordedRequest request = mockAPI.takeRequest();
        assertThat(request.getHeader("Accept-Language"), is(getDefaultLocale()));
{'fraction_non_alphanumeric': 0.1165537998495109, 'fraction_numerical': 0.005768748432405317, 'mean_word_length': 3.9757893423187323, 'pattern_counts': {'":': 0, '<': 80, '<?xml version=': 0, '>': 80, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6082040', 'n_tokens_mistral': 10565, 'n_tokens_neox': 10590, 'n_words': 2163}